Unity學習筆記007.Unity接入原生Android百度AR地圖
阿新 • • 發佈:2019-01-10
大概操作步驟按筆記006執行。
1.背景
環境:
OS:Windows10
Android Studio3.2
Unity 2018.1.2f1
思路
Unity端:主調方,UI
Android端:底層介面,打包aar方式
2.步驟
2.1 Android Studio基礎配置
2.1.1 新建工程、匯入Unity介面包。
對比百度demo,匯入百度lib,如圖:
模仿demo,新建Activity,如下:
2.1.2 配置app的build.gradle
//apply plugin: 'com.android.application'
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
// Add
sourceSets {
main {
//Path to your source code
main {
jniLibs.srcDir('libs')
jni.srcDirs = []
}
java {
srcDir 'src/main/java'
}
}
}
defaultConfig {
// applicationId "com.polin.baiduarmapsdk"
minSdkVersion 15
targetSdkVersion 28
// versionCode 1
// versionName "1.0"
// testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// Add
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation files('libs/android-support-v4.jar')
implementation files('libs/BaiduLBS_Android.jar')
implementation files('libs/classes.jar')
implementation files('libs/gson-2.2.4.jar')
implementation files('libs/org.apache.http.legacy.jar')
}
// Add Backup
//task to delete the old jar
task deleteOldJar(type: Delete) {
delete 'release/BaiduMapKit.jar'
}
//task to export contents as jar
task exportJar(type: Copy) {
from('build/intermediates/packaged-classes/release/')
into('release/')
include('classes.jar')
///Rename the jar
rename('classes.jar', 'BaiduMapKit.jar')
}
exportJar.dependsOn(deleteOldJar, build)
2.1.3 配置AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.polin.baiduarmapsdk">
<!--訪問相機許可權-->
<uses-permission android:name="android.permission.CAMERA"/>
<!--訪問閃光燈-->
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<!-- 這個許可權用於進行網路定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!-- 這個許可權用於訪問GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!-- 用於訪問wifi網路資訊,wifi資訊會用於進行網路定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!-- 獲取運營商資訊,用於支援提供運營商資訊相關的介面-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!-- 這個許可權用於獲取wifi的獲取許可權,wifi資訊會用來進行網路定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!-- 用於讀取手機當前的狀態-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!-- 寫入擴充套件儲存,向擴充套件卡寫入資料,用於寫入離線定位資料-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!-- 訪問網路,網路定位需要上網-->
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:label="@string/app_name">
<!-- 開發金鑰 -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="****">
</meta-data>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="unityplayer.UnityActivity"
android:value="true" />
</activity>
<activity android:name=".ArActivity" >
<meta-data
android:name="unityplayer.UnityActivity"
android:value="true" />
</activity>
<activity android:name=".BuildingArActivity" >
<meta-data
android:name="unityplayer.UnityActivity"
android:value="true" />
</activity>
<activity android:name=".SceneryArActivity">
<meta-data
android:name="unityplayer.UnityActivity"
android:value="true" />
</activity>
<!-- 接入百度地圖定位SDK -->
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote"></service>
</application>
</manifest>
2.1.4 嘗試打包成aar
在該目錄下找到aar包,連同AndroidManifest.xml一起,即是我們將放入Unity中的Android資源。
至此,Android Studio端的配置完成。
2.2 Unity端基礎配置
2.2.1 新建工程
2.2.2 填入Android工程包名
2.3 編寫與測試
2.3.1 嘗試在AndroidManifest.xml中新增百度Key,並獲取在其中註冊獲取手機許可權
將MainActivity作為入口,編寫工具類LocSdkClient、PermissionsChecker、UntiyClient。
LocSdkClient:
public class LocSdkClient {
/**
*
* 百度定位sdk 座標獲取工具類
*/
private static LocSdkClient mInstance = null;
public LocationClient mLocationClient = null;
private LocSdkClient(Context context) {
mLocationClient = new LocationClient(context.getApplicationContext());
// 宣告LocationClient類
// mLocationClient.registerLocationListener(myListener);
// 註冊監聽函式
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
// 可選,設定定位模式,預設高精度
// LocationMode.Hight_Accuracy:高精度;
// LocationMode. Battery_Saving:低功耗;
// LocationMode. Device_Sensors:僅使用裝置;
option.setCoorType("bd09");
// 可選,設定返回經緯度座標型別,預設gcj02
// gcj02:國測局座標;
// bd09ll:百度經緯度座標;
// bd09:百度墨卡託座標;
// 海外地區定位,無需設定座標型別,統一返回wgs84型別座標
option.setScanSpan(2000);
// 可選,設定發起定位請求的間隔,int型別,單位ms
// 如果設定為0,則代表單次定位,即僅定位一次,預設為0
// 如果設定非0,需設定1000ms以上才有效
option.setOpenGps(true);
// 可選,設定是否使用gps,預設false
// 使用高精度和僅用裝置兩種定位模式的,引數必須設定為true
option.setLocationNotify(true);
// 可選,設定是否當GPS有效時按照1S/1次頻率輸出GPS結果,預設false
option.setIgnoreKillProcess(false);
// 可選,定位SDK內部是一個service,並放到了獨立程序。
// 設定是否在stop的時候殺死這個程序,預設(建議)不殺死,即setIgnoreKillProcess(true)
option.SetIgnoreCacheException(false);
// 可選,設定是否收集Crash資訊,預設收集,即引數為false
option.setWifiCacheTimeOut(5 * 60 * 1000);
// 可選,7.2版本新增能力
// 如果設定了該介面,首次啟動定位時,會先判斷當前WiFi是否超出有效期,若超出有效期,會先重新掃描WiFi,然後定位
option.setEnableSimulateGps(false);
// 可選,設定是否需要過濾GPS模擬結果,預設需要,即引數為false
mLocationClient.setLocOption(option);
// mLocationClient為第二步初始化過的LocationClient物件
// 需將配置好的LocationClientOption物件,通過setLocOption方法傳遞給LocationClient物件使用
// 更多LocationClientOption的配置,請參照類參考中LocationClientOption類的詳細說明
mLocationClient.start();
// mLocationClient為第二步初始化過的LocationClient物件
// 呼叫LocationClient的start()方法,便可發起定位請求e
}
public LocationClient getLocationStart() {
return mLocationClient;
}
public static LocSdkClient getInstance(Context context) {
if (mInstance == null) {
Class var0 = LocSdkClient.class;
synchronized (LocSdkClient.class) {
if (mInstance == null) {
mInstance = new LocSdkClient(context);
}
}
}
return mInstance;
}
}
PermissionsChecker:
/**
* 許可權申請
*/
public class PermissionsChecker {
private final Context mContext;
public PermissionsChecker(Context context) {
mContext = context.getApplicationContext();
}
// 判斷許可權集合
public boolean lacksPermissions() {
String[] permissions = new String[] {
// Manifest.permission.FLASHLIGHT,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.INTERNET,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_WIFI_STATE
};
for (String permission : permissions) {
if (lacksPermission(permission)) {
return true;
}
}
return false;
}
// 判斷是否缺少許可權
private boolean lacksPermission(String permission) {
return ContextCompat.checkSelfPermission(mContext, permission) == PackageManager.PERMISSION_DENIED;
}
}
UntiyClient:
public class UntiyClient extends UnityPlayerActivity {
/**
* unity專案啟動時的的上下文
*/
private static Activity _unityActivity;
/**
* 獲取unity專案的上下文
* @return
*/
public static Activity GetActivity(){
if(null == _unityActivity) {
try {
Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer");
Activity activity = (Activity) classtype.getDeclaredField("currentActivity").get(classtype);
_unityActivity = activity;
} catch (ClassNotFoundException e) {
} catch (IllegalAccessException e) {
} catch (NoSuchFieldException e) {
}
}
return _unityActivity;
}
/**
* 呼叫Unity的方法
* @param gameObjectName 呼叫的GameObject的名稱
* @param functionName 方法名
* @param args 引數
* @return 呼叫是否成功
*/
public static boolean CallUnity(String gameObjectName, String functionName, String args){
try {
Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer");
Method method =classtype.getMethod("UnitySendMessage", String.class,String.class,String.class);
method.invoke(classtype,gameObjectName,functionName,args);
return true;
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
return false;
}
}
MainActivity:
public class MainActivity extends UnityPlayerActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
}
// MainActivity初始化函式
public void init(){
// 判斷許可權
PermissionsChecker permissionsChecker = new PermissionsChecker(GetActivity());
if (permissionsChecker.lacksPermissions()) {
Toast.makeText(GetActivity(), "缺少許可權,請開啟許可權!", Toast.LENGTH_LONG).show();
openSetting();
}
else{
Toast.makeText(GetActivity(), "許可權已開啟!", Toast.LENGTH_LONG).show();
}
}
/**
* 開啟設定許可權介面
*
* @param
*/
public void openSetting() {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
}
在Unity中建立MainActivity初始化測試按鈕:
匯出aar包與AndroidManifest.xml到Unity的Plugins/Android中,編寫Unity主調指令碼:
public class UIControl : MonoBehaviour {
// Use this for initialization
void Start () {
transform.Find("MainActivityInit").GetComponent<Button>().onClick.AddListener(InitMainActivity);
}
public void InitMainActivity()
{
AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");
currentActivity.Call("init");
}
}
打包apk
報錯1.
解決方案1.
把Unity打包方式從Gradle改為Internal。
報錯2.
解決方案2.
報錯資訊顯示:aar包中的Unity介面包classes.jar重複了,那就刪掉。
用壓縮軟體開啟aar包,找到libs目錄下的classes.jar,刪除此包。
報錯3.
解決方案3.
這些資源找不到,再次開啟aar包,找到./res/values/values.xml並進行修改:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorAccent">#D81B60</color>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<string name="app_name">BaiduArMapSDK</string>
<style name="AppTheme" parent="android:Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="android:colorPrimary">@color/colorPrimary</item>
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="android:colorAccent">@color/colorAccent</item>
</style>
</resources>
報錯4.
解決方案4.
依然找不到這個主題,我們就不用它了
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorAccent">#D81B60</color>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<string name="app_name">BaiduArMapSDK</string>
<style name="AppTheme" parent="android:Theme.Light">
<!-- Customize your theme here. -->
<item name="android:colorPrimary">@color/colorPrimary</item>
<item name=