? 初次寫這個,記錄一下 我這個從0基礎的小白,因為公司需要進入unity 與android 交互的大門。
? 之前看的網上的很多東西,太亂而且很多文章有些東西一筆帶過太簡單,所以記錄一下自己的經歷。
1、配置環境和安裝androidstudio 不用說,網上都有。這個還是可以的。
2、下載高德地圖sdk,百度 高德地圖API 根據自己需求下載(下圖為本人下載)
3、創建一個安卓工程,將下載的高德地圖的sdk解壓并將下圖中的jar(AMap3DMap_6.3.0_AMapLocation_4.1.0_20180619)包復制到新建的工程的Project->app->libs里面。將 Unity的jar也導入到 libs 里面(D:\U3D\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes)
4、添加依賴關系,選中導入的兩個jar包,右鍵 add as Library。
5、在Project->app->src->main 中新建一個jniLibs文件夾,如下圖所示將文件包復制進去。
6、基本上差不多了,不要先修改build.grade里面的東西。
7、修改AndroidManifest.xml里面的東西,將所需要的權限加入其中。鏈接里面很清楚。 https://lbs.amap.com/api/android-sdk/guide/create-map/show-map,重要一步記得在里面? 添上一句話
8、當然 在這之前你要申請Key值? 這個 給鏈接? 很簡單,我寫的步驟 是按照我的腦袋里記住的來的 ,可以適當自己調整emmmmm? 是的。:? https://lbs.amap.com/api/android-sdk/gettingstarted ? ??
9、填入key值之后,繼續走步驟哈? 代碼了,代碼狗啊!!,我建議 如果想要在unity程序中 再創建一個Activity了,作為顯示地圖和定位的Activity? 。MainActivity? extends? Activity(暫時的,等安卓真機測試沒問題就要改成 extends? UnityPlayerActivity!! 一定要是 這個? 。要不 emmmm....出錯了別找我 后果自負!!!!)。
10、顯示 地圖的代碼,下圖這些應該足夠了。該死的簡書 不讓我復制。。。。
11、咳咳貌似可以了,,,,下面給你們看看我的各個Activity,根據這個可以自己寫。
MainActivity:請忽略我的傳值。
定位和顯示地圖的Activity,名字隨便起,但是我的這個activity exends?extends CheckPermissionsActivity implements AMapLocationListener ? ,CheckPermissionsActivity我一會會貼出來。一個老哥幫忙改了下,在這里萬分感謝 我哥。
private AMapLocationClientmlocationClient =null;//定位發起端
private AMapLocationClientOptionmLocationOption =null;//定位參數
private LocationSource.OnLocationChangedListenermListener =null;//定位監聽器
//定位回調字符串
private static StringLocationInfo;
private MapViewmapView;
private AMapaMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
? ? setContentView(R.layout.activity_main);
? ? mapView = (MapView) findViewById(R.id.map);//找到地圖控件
//在activity執行onCreate時執行mMapView.onCreate(savedInstanceState),創建地圖
? ? mapView.onCreate(savedInstanceState);
? ? if (aMap ==null) {
aMap =mapView.getMap();
? ? }
aMap.moveCamera(CameraUpdateFactory.zoomTo(16));
? ? btn1 = (Button) findViewById(R.id.button1);
? ? btn1.setOnClickListener(new View.OnClickListener() {
@Override
? ? ? ? public void onClick(View view) {
finish();
? ? ? ? }
});
mlocationClient =new AMapLocationClient(this);
? ? ? ? //初始化定位參數
? ? ? ? mLocationOption =new AMapLocationClientOption();
? ? ? ? //設置定位監聽
? ? ? ? mlocationClient.setLocationListener(this);
? ? ? ? //設置定位模式為高精度模式,Battery_Saving為低功耗模式,Device_Sensors是僅設備模式
? ? ? ? mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
? ? ? ? //設置定位間隔,單位毫秒,默認為2000ms
? ? ? ? mLocationOption.setInterval(2000);
? ? ? ? //設置定位參數
? ? ? ? mlocationClient.setLocationOption(mLocationOption);
? ? ? ? // 此方法為每隔固定時間會發起一次定位請求,為了減少電量消耗或網絡流量消耗,
// 注意設置合適的定位時間的間隔(最小間隔支持為1000ms),并且在合適時間調用stopLocation()方法來取消定位請求
// 在定位結束后,在合適的生命周期調用onDestroy()方法
// 在單次定位情況下,定位無論成功與否,都無需調用stopLocation()方法移除請求,定位sdk內部會移除
//啟動定位
? ? ? ? mlocationClient.startLocation();
//定位藍點
? ? ? ? BitmapDescriptor bitmapDescriptor3 = BitmapDescriptorFactory.fromResource(R.mipmap.ic_zhujue);
? ? ? ? MyLocationStyle myLocationStyle;
? ? ? ? myLocationStyle =new MyLocationStyle();//初始化定位藍點樣式類myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//連續定位、且將視角移動到地圖中心點,定位點依照設備方向旋轉,并且會跟隨設備移動。(1秒1次定位)如果不設置myLocationType,默認也會執行此種模式。
? ? ? ? myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW);
? ? ? ? myLocationStyle.interval(5000); //設置連續定位模式下的定位間隔,只在連續定位模式下生效,單次定位模式下不會生效。單位為毫秒。
? ? ? ? aMap.setMyLocationStyle(myLocationStyle);//設置定位藍點的Style
? ? ? ? myLocationStyle.radiusFillColor(0);
? ? ? ? //aMap.getUiSettings().setMyLocationButtonEnabled(true);設置默認定位按鈕是否顯示,非必需設置。
? ? ? ? aMap.setMyLocationEnabled(true);// 設置為true表示啟動顯示定位藍點,false表示隱藏定位藍點并不進行定位,默認是false。
? ? ? ? myLocationStyle.myLocationIcon(bitmapDescriptor3);
}
@Override
? ? public void onLocationChanged(AMapLocation location) {
if (null != location) {
StringBuffer sb =new StringBuffer();
? ? ? ? ? ? //errCode等于0代表定位成功,其他的為定位失敗,具體的可以參照官網定位錯誤碼說明
? ? ? ? ? ? if (location.getErrorCode() ==0) {
sb.append("定位成功" +"\n");
? ? ? ? ? ? ? ? sb.append("定位類型: " + location.getLocationType() +"\n");
? ? ? ? ? ? ? ? sb.append("經? ? 度? ? : " + location.getLongitude() +"\n");
? ? ? ? ? ? ? ? sb.append("緯? ? 度? ? : " + location.getLatitude() +"\n");
? ? ? ? ? ? ? ? sb.append("精? ? 度? ? : " + location.getAccuracy() +"米" +"\n");
? ? ? ? ? ? ? ? sb.append("提供者? ? : " + location.getProvider() +"\n");
? ? ? ? ? ? ? ? sb.append("速? ? 度? ? : " + location.getSpeed() +"米/秒" +"\n");
? ? ? ? ? ? ? ? sb.append("角? ? 度? ? : " + location.getBearing() +"\n");
? ? ? ? ? ? ? ? // 獲取當前提供定位服務的衛星個數
? ? ? ? ? ? ? ? sb.append("星? ? 數? ? : " + location.getSatellites() +"\n");
? ? ? ? ? ? ? ? sb.append("國? ? 家? ? : " + location.getCountry() +"\n");
? ? ? ? ? ? ? ? sb.append("省? ? ? ? ? ? : " + location.getProvince() +"\n");
? ? ? ? ? ? ? ? sb.append("市? ? ? ? ? ? : " + location.getCity() +"\n");
? ? ? ? ? ? ? ? sb.append("城市編碼 : " + location.getCityCode() +"\n");
? ? ? ? ? ? ? ? sb.append("區? ? ? ? ? ? : " + location.getDistrict() +"\n");
? ? ? ? ? ? ? ? sb.append("區域 碼? : " + location.getAdCode() +"\n");
? ? ? ? ? ? ? ? sb.append("地? ? 址? ? : " + location.getAddress() +"\n");
? ? ? ? ? ? ? ? sb.append("興趣點? ? : " + location.getPoiName() +"\n");
? ? ? ? ? ? ? ? LocationInfo = sb.toString();
? ? ? ? ? ? ? ? ListMarker.longitude = location.getLatitude();
? ? ? ? ? ? ? ? ListMarker.latitude = location.getLongitude();
? ? ? ? ? ? ? ? //定位完成的時間
? ? ? ? ? ? ? ? sb.append("定位時間: " + Utils.formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") +"\n");
? ? ? ? ? ? }else {
//定位失敗
? ? ? ? ? ? ? ? sb.append("定位失敗" +"\n");
? ? ? ? ? ? ? ? sb.append("錯誤碼:" + location.getErrorCode() +"\n");
? ? ? ? ? ? ? ? sb.append("錯誤信息:" + location.getErrorInfo() +"\n");
? ? ? ? ? ? ? ? sb.append("錯誤描述:" + location.getLocationDetail() +"\n");
? ? ? ? ? ? }
sb.append("***定位質量報告***").append("\n");
? ? ? ? ? ? sb.append("* WIFI開關:").append(location.getLocationQualityReport().isWifiAble() ?"開啟" :"關閉").append("\n");
? ? ? ? ? ? sb.append("* GPS星數:").append(location.getLocationQualityReport().getGPSSatellites()).append("\n");
? ? ? ? ? ? sb.append("* 網絡類型:" + location.getLocationQualityReport().getNetworkType()).append("\n");
? ? ? ? ? ? sb.append("* 網絡耗時:" + location.getLocationQualityReport().getNetUseTime()).append("\n");
? ? ? ? ? ? sb.append("****************").append("\n");
? ? ? ? ? ? //定位之后的回調時間
? ? ? ? ? ? sb.append("回調時間: " + Utils.formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") +"\n");
? ? ? ? ? ? //解析定位結果,
? ? ? ? ? ? String result = sb.toString();
? ? ? ? ? ? Log.i("tag", result);
? ? ? ? ? ? System.out.println(MarkerGather.latitude);
? ? ? ? }
}
//調用經度
? ? public double GetInfoxlongitude() {
//? ? ? ? startLocation();
? ? ? ? return ListMarker.longitude;
? ? }
//調用緯度
? ? public double GetInfoylatitude() {
//? ? ? ? startLocation();
? ? ? ? return ListMarker.latitude;
? ? }
/**
* 方法必須重寫
*/
? ? @Override
? ? protected void onResume() {
super.onResume();
? ? ? ? mapView.onResume();
? ? }
/**
* 方法必須重寫
*/
? ? @Override
? ? protected void onPause() {
super.onPause();
? ? ? ? mapView.onPause();
? ? }
/**
* 方法必須重寫
*/
? ? @Override
? ? protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
? ? ? ? mapView.onSaveInstanceState(outState);
? ? }
/**
* 方法必須重寫
*/
? ? @Override
? ? protected void onDestroy() {
super.onDestroy();
? ? ? ? mapView.onDestroy();
? ? ? ? if (null !=mlocationClient )
{
mlocationClient.onDestroy();
? ? ? ? }
}
@Override
? ? public ResourcesgetResources() {
return getBaseContext().getResources();
? ? }
}
12、CheckPermissionsActivity 其實就是動態獲權限,因為android 6.0以上都需要這么搞,別問我為什么,為了安全!!!!至于這個Activity? 自己去看。不解釋 因為這是很詳細 ,蛋疼中....................。
public class CheckPermissionsActivityextends Activity {
/**
* 需要進行檢測的權限數組
*/
? ? protected String[]needPermissions = {
Manifest.permission.ACCESS_COARSE_LOCATION,
? ? ? ? ? ? Manifest.permission.ACCESS_FINE_LOCATION,
? ? ? ? ? ? Manifest.permission.WRITE_EXTERNAL_STORAGE,
? ? ? ? ? ? Manifest.permission.READ_PHONE_STATE
? ? };
? ? private static final int PERMISSON_REQUESTCODE =0;
? ? /**
* 判斷是否需要檢測,防止不停的彈框
*/
? ? private static boolean isNeedCheck =true;
? ? @Override
? ? protected void onResume() {
super.onResume();
? ? ? ? if (Build.VERSION.SDK_INT >=23
? ? ? ? ? ? ? ? && getApplicationInfo().targetSdkVersion >=23) {
if (isNeedCheck) {
checkPermissions(needPermissions);
? ? ? ? ? ? ? ? isNeedCheck =false;
? ? ? ? ? ? }
}
}
/**
*
? ? * @param permissions
? ? * @since 2.5.0
*
*/
? ? private void checkPermissions(String... permissions) {
try {
if (Build.VERSION.SDK_INT >=23
? ? ? ? ? ? ? ? ? ? && getApplicationInfo().targetSdkVersion >=23) {
List needRequestPermissonList = findDeniedPermissions(permissions);
? ? ? ? ? ? ? ? if (null != needRequestPermissonList
&& needRequestPermissonList.size() >0) {
String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);
? ? ? ? ? ? ? ? ? ? Method method = getClass().getMethod("requestPermissions", new Class[]{String[].class, int.class});
? ? ? ? ? ? ? ? ? ? method.invoke(this, array, PERMISSON_REQUESTCODE);
? ? ? ? ? ? ? ? }
}
}catch (Throwable e) {
}
}
/**
* 獲取權限集中需要申請權限的列表
*
? ? * @param permissions
? ? * @return
? ? * @since 2.5.0
*
*/
? ? private ListfindDeniedPermissions(String[] permissions) {
List needRequestPermissonList =new ArrayList();
? ? ? ? if (Build.VERSION.SDK_INT >=23
? ? ? ? ? ? ? ? && getApplicationInfo().targetSdkVersion >=23){
try {
for (String perm : permissions) {
Method checkSelfMethod = getClass().getMethod("checkSelfPermission", String.class);
? ? ? ? ? ? ? ? ? ? Method shouldShowRequestPermissionRationaleMethod = getClass().getMethod("shouldShowRequestPermissionRationale",
? ? ? ? ? ? ? ? ? ? ? ? ? ? String.class);
? ? ? ? ? ? ? ? ? ? if ((Integer)checkSelfMethod.invoke(this, perm) != PackageManager.PERMISSION_GRANTED
? ? ? ? ? ? ? ? ? ? ? ? ? ? || (Boolean)shouldShowRequestPermissionRationaleMethod.invoke(this, perm)) {
needRequestPermissonList.add(perm);
? ? ? ? ? ? ? ? ? ? }
}
}
catch (Throwable e) {
}
}
return needRequestPermissonList;
? ? }
/**
* 檢測是否所有的權限都已經授權
? ? * @param grantResults
? ? * @return
? ? * @since 2.5.0
*
*/
? ? private boolean verifyPermissions(int[] grantResults) {
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
isNeedCheck =false;
return false;
? ? ? ? ? ? }
else
? ? ? ? ? ? {
isNeedCheck =true;
? ? ? ? ? ? }
}
return true;
? ? }
@TargetApi(23)
public void onRequestPermissionsResult(int requestCode,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String[] permissions, int[] paramArrayOfInt) {
if (requestCode ==PERMISSON_REQUESTCODE) {
isNeedCheck =false;
? ? ? ? ? ? if (!verifyPermissions(paramArrayOfInt)) {
//? ? ? ? ? ? ? ? showMissingPermissionDialog();
? ? ? ? ? ? ? ? isNeedCheck =false;
? ? ? ? ? ? }
}
}
/**
* 顯示提示信息
*
? ? * @since 2.5.0
*
*/
? ? private void showMissingPermissionDialog() {
AlertDialog.Builder builder =new AlertDialog.Builder(this);
//? ? ? ? builder.setTitle(R.string.notifyTitle);
//? ? ? ? builder.setMessage(R.string.notifyMsg);
// 拒絕, 退出應用
? ? ? ? builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
? ? ? ? ? ? ? ? ? ? public void onClick(DialogInterface dialog, int which) {
finish();
? ? ? ? ? ? ? ? ? ? }
});
? ? ? ? builder.setPositiveButton(R.string.setting,
? ? ? ? ? ? ? ? new DialogInterface.OnClickListener() {
@Override
? ? ? ? ? ? ? ? ? ? public void onClick(DialogInterface dialog, int which) {
startAppSettings();
? ? ? ? ? ? ? ? ? ? }
});
? ? ? ? builder.setCancelable(false);
? ? ? ? builder.show();
? ? }
/**
*? 啟動應用的設置
*
? ? * @since 2.5.0
*
*/
? ? private void startAppSettings() {
Intent intent =new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
? ? ? ? intent.setData(Uri.parse("package:" + getPackageName()));
? ? ? ? startActivity(intent);
? ? }
@Override
? ? public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
this.finish();
return true;
? ? ? ? }
return super.onKeyDown(keyCode, event);
? ? }
}
13、基本上都差不多了? emmm...... 記得在AndroidManifest.xml中注冊你的每個Activity!!!要不 后果自負啊啊啊啊啊。
14、在MainActivity的 onCreate 函數中調用下? OtherGameLocation()函數 。跑跑試試吧 。真機測試啊 。手機連電腦 ,跑 android? studio 啊? ,記得打開你的開發者模式和usb調試? 記得匹配密碼就差不調可以跑了。點三角號,會顯示出你的機型,跑就可以了。
15、如果成功了啊,就按住9括號里面的改一下 然后? 在將build.gradle里面改成 6 那樣紙的就好了。然后 點擊? buile 里面的 Rebuild Project 完成之后 在點擊buile apk 然后將aar和 AndroidManifest.xml復制到 桌面 等待著 導入unity 中。emmm......unity不用我多說了吧? 。
16、 新建一個unity的工程然后在Accets 文件夾下面創建一個Plugins 文件夾,而后在Plugins里面創建一個android 文件夾,將導出的aar包和 AndroidManifest.xml 導入進去 ,之后呢? ,迂回一下,將你解壓完成的高德地圖里面的jar里面的 assets 文件夾復制一份,丟入unity中和 aar 包他們在一起。
17、之后的事情嗎 簡單的多了, 設置一個按鈕,當點擊按鈕時候 unity 調用 android里面的方法,進入地圖和定位、? button 我就不說了,各位 unity大佬,自行搞定唄emmm.....出事別怪我頭上。。。記得啊 把你MainActivity中的onCreate 的調用的函數刪除啊。
unity 調用安卓的方法:超級簡單。。mmp,我覺得 前兩句就是固定的,call的時候一定看清楚你 的返回值是什么 如果有返回值 那么就要在call<你的返回值類型>,如果要傳參數 就?? jo.Call("你在andoid studio里面的函數名", 傳的參數);?可以多個參數中間用“,”,這樣就調用了android 的方法,別問我為什么這樣可以,也別天吶,怎么可以這么簡單,emmm.......因為? mmp,我也我也很懵逼啊,蛋疼。
AndroidJavaClass jc;? AndroidJavaObject jo;
public void GameCreat() {
jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic("currentActivity");
?jo.Call("OtherGameLocation");
? ? }
18、最后一步,別特么 開心的直接跑unity ,因為你一跑人 unity 就會告訴你: 對不起,請在真機上測試。。。。。。。。
打包 自己搞吧,記得把 sdk和jdk路徑寫上、、好了,打包成功就差不多了 。
特別感謝兩個老哥,幫了我好多的忙。
最后? 別特么問我太難的問題 老子也懵逼啊? 我也是萌新啊 。。。。。。。emmmm.......
一般問題網上都有答案,可以自己百度下,我寫的可能不全 歡迎各位大佬給指正下~~~。 寫的很詳細了 一般按照我說的來的話應該是沒問題的。
成功了的話 ,記得給刷一顆小心啊~~~~~~~