? 初次寫這個,記錄一下 我這個從0基礎(chǔ)的小白,因?yàn)楣拘枰M(jìn)入unity 與android 交互的大門。
? 之前看的網(wǎng)上的很多東西,太亂而且很多文章有些東西一筆帶過太簡單,所以記錄一下自己的經(jīng)歷。
1、配置環(huán)境和安裝androidstudio 不用說,網(wǎng)上都有。這個還是可以的。
2、下載高德地圖sdk,百度 高德地圖API 根據(jù)自己需求下載(下圖為本人下載)

3、創(chuàng)建一個安卓工程,將下載的高德地圖的sdk解壓并將下圖中的jar(AMap3DMap_6.3.0_AMapLocation_4.1.0_20180619)包復(fù)制到新建的工程的Project->app->libs里面。將 Unity的jar也導(dǎo)入到 libs 里面(D:\U3D\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes)

4、添加依賴關(guān)系,選中導(dǎo)入的兩個jar包,右鍵 add as Library。
5、在Project->app->src->main 中新建一個jniLibs文件夾,如下圖所示將文件包復(fù)制進(jìn)去。

6、基本上差不多了,不要先修改build.grade里面的東西。
7、修改AndroidManifest.xml里面的東西,將所需要的權(quán)限加入其中。鏈接里面很清楚。 https://lbs.amap.com/api/android-sdk/guide/create-map/show-map,重要一步記得在里面? 添上一句話
8、當(dāng)然 在這之前你要申請Key值? 這個 給鏈接? 很簡單,我寫的步驟 是按照我的腦袋里記住的來的 ,可以適當(dāng)自己調(diào)整emmmmm? 是的。:? https://lbs.amap.com/api/android-sdk/gettingstarted ? ??

9、填入key值之后,繼續(xù)走步驟哈? 代碼了,代碼狗?。。?,我建議 如果想要在unity程序中 再創(chuàng)建一個Activity了,作為顯示地圖和定位的Activity? 。MainActivity? extends? Activity(暫時的,等安卓真機(jī)測試沒問題就要改成 extends? UnityPlayerActivity!! 一定要是 這個? 。要不 emmmm....出錯了別找我 后果自負(fù)!?。。。?。
10、顯示 地圖的代碼,下圖這些應(yīng)該足夠了。該死的簡書 不讓我復(fù)制。。。。

11、咳咳貌似可以了,,,,下面給你們看看我的各個Activity,根據(jù)這個可以自己寫。
MainActivity:請忽略我的傳值。

定位和顯示地圖的Activity,名字隨便起,但是我的這個activity exends?extends CheckPermissionsActivity implements AMapLocationListener ? ,CheckPermissionsActivity我一會會貼出來。一個老哥幫忙改了下,在這里萬分感謝 我哥。
private AMapLocationClientmlocationClient =null;//定位發(fā)起端
private AMapLocationClientOptionmLocationOption =null;//定位參數(shù)
private LocationSource.OnLocationChangedListenermListener =null;//定位監(jiān)聽器
//定位回調(diào)字符串
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執(zhí)行onCreate時執(zhí)行mMapView.onCreate(savedInstanceState),創(chuàng)建地圖
? ? 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);
? ? ? ? //初始化定位參數(shù)
? ? ? ? mLocationOption =new AMapLocationClientOption();
? ? ? ? //設(shè)置定位監(jiān)聽
? ? ? ? mlocationClient.setLocationListener(this);
? ? ? ? //設(shè)置定位模式為高精度模式,Battery_Saving為低功耗模式,Device_Sensors是僅設(shè)備模式
? ? ? ? mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
? ? ? ? //設(shè)置定位間隔,單位毫秒,默認(rèn)為2000ms
? ? ? ? mLocationOption.setInterval(2000);
? ? ? ? //設(shè)置定位參數(shù)
? ? ? ? mlocationClient.setLocationOption(mLocationOption);
? ? ? ? // 此方法為每隔固定時間會發(fā)起一次定位請求,為了減少電量消耗或網(wǎng)絡(luò)流量消耗,
// 注意設(shè)置合適的定位時間的間隔(最小間隔支持為1000ms),并且在合適時間調(diào)用stopLocation()方法來取消定位請求
// 在定位結(jié)束后,在合適的生命周期調(diào)用onDestroy()方法
// 在單次定位情況下,定位無論成功與否,都無需調(diào)用stopLocation()方法移除請求,定位sdk內(nèi)部會移除
//啟動定位
? ? ? ? mlocationClient.startLocation();
//定位藍(lán)點(diǎn)
? ? ? ? BitmapDescriptor bitmapDescriptor3 = BitmapDescriptorFactory.fromResource(R.mipmap.ic_zhujue);
? ? ? ? MyLocationStyle myLocationStyle;
? ? ? ? myLocationStyle =new MyLocationStyle();//初始化定位藍(lán)點(diǎn)樣式類myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//連續(xù)定位、且將視角移動到地圖中心點(diǎn),定位點(diǎn)依照設(shè)備方向旋轉(zhuǎn),并且會跟隨設(shè)備移動。(1秒1次定位)如果不設(shè)置myLocationType,默認(rèn)也會執(zhí)行此種模式。
? ? ? ? myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW);
? ? ? ? myLocationStyle.interval(5000); //設(shè)置連續(xù)定位模式下的定位間隔,只在連續(xù)定位模式下生效,單次定位模式下不會生效。單位為毫秒。
? ? ? ? aMap.setMyLocationStyle(myLocationStyle);//設(shè)置定位藍(lán)點(diǎn)的Style
? ? ? ? myLocationStyle.radiusFillColor(0);
? ? ? ? //aMap.getUiSettings().setMyLocationButtonEnabled(true);設(shè)置默認(rèn)定位按鈕是否顯示,非必需設(shè)置。
? ? ? ? aMap.setMyLocationEnabled(true);// 設(shè)置為true表示啟動顯示定位藍(lán)點(diǎn),false表示隱藏定位藍(lán)點(diǎn)并不進(jìn)行定位,默認(rèn)是false。
? ? ? ? myLocationStyle.myLocationIcon(bitmapDescriptor3);
}
@Override
? ? public void onLocationChanged(AMapLocation location) {
if (null != location) {
StringBuffer sb =new StringBuffer();
? ? ? ? ? ? //errCode等于0代表定位成功,其他的為定位失敗,具體的可以參照官網(wǎng)定位錯誤碼說明
? ? ? ? ? ? if (location.getErrorCode() ==0) {
sb.append("定位成功" +"\n");
? ? ? ? ? ? ? ? sb.append("定位類型: " + location.getLocationType() +"\n");
? ? ? ? ? ? ? ? sb.append("經(jīng)? ? 度? ? : " + 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");
? ? ? ? ? ? ? ? // 獲取當(dāng)前提供定位服務(wù)的衛(wèi)星個數(shù)
? ? ? ? ? ? ? ? sb.append("星? ? 數(shù)? ? : " + 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("區(qū)? ? ? ? ? ? : " + location.getDistrict() +"\n");
? ? ? ? ? ? ? ? sb.append("區(qū)域 碼? : " + location.getAdCode() +"\n");
? ? ? ? ? ? ? ? sb.append("地? ? 址? ? : " + location.getAddress() +"\n");
? ? ? ? ? ? ? ? sb.append("興趣點(diǎn)? ? : " + 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("***定位質(zhì)量報告***").append("\n");
? ? ? ? ? ? sb.append("* WIFI開關(guān):").append(location.getLocationQualityReport().isWifiAble() ?"開啟" :"關(guān)閉").append("\n");
? ? ? ? ? ? sb.append("* GPS星數(shù):").append(location.getLocationQualityReport().getGPSSatellites()).append("\n");
? ? ? ? ? ? sb.append("* 網(wǎng)絡(luò)類型:" + location.getLocationQualityReport().getNetworkType()).append("\n");
? ? ? ? ? ? sb.append("* 網(wǎng)絡(luò)耗時:" + location.getLocationQualityReport().getNetUseTime()).append("\n");
? ? ? ? ? ? sb.append("****************").append("\n");
? ? ? ? ? ? //定位之后的回調(diào)時間
? ? ? ? ? ? sb.append("回調(diào)時間: " + Utils.formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") +"\n");
? ? ? ? ? ? //解析定位結(jié)果,
? ? ? ? ? ? String result = sb.toString();
? ? ? ? ? ? Log.i("tag", result);
? ? ? ? ? ? System.out.println(MarkerGather.latitude);
? ? ? ? }
}
//調(diào)用經(jīng)度
? ? public double GetInfoxlongitude() {
//? ? ? ? startLocation();
? ? ? ? return ListMarker.longitude;
? ? }
//調(diào)用緯度
? ? 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 其實(shí)就是動態(tài)獲權(quán)限,因?yàn)閍ndroid 6.0以上都需要這么搞,別問我為什么,為了安全?。。?!至于這個Activity? 自己去看。不解釋 因?yàn)檫@是很詳細(xì) ,蛋疼中....................。
public class CheckPermissionsActivityextends Activity {
/**
* 需要進(jìn)行檢測的權(quán)限數(shù)組
*/
? ? 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) {
}
}
/**
* 獲取權(quán)限集中需要申請權(quán)限的列表
*
? ? * @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;
? ? }
/**
* 檢測是否所有的權(quán)限都已經(jīng)授權(quán)
? ? * @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);
// 拒絕, 退出應(yīng)用
? ? ? ? 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();
? ? }
/**
*? 啟動應(yīng)用的設(shè)置
*
? ? * @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!??!要不 后果自負(fù)啊啊啊啊啊。

14、在MainActivity的 onCreate 函數(shù)中調(diào)用下? OtherGameLocation()函數(shù) 。跑跑試試吧 。真機(jī)測試啊 。手機(jī)連電腦 ,跑 android? studio 啊? ,記得打開你的開發(fā)者模式和usb調(diào)試? 記得匹配密碼就差不調(diào)可以跑了。點(diǎn)三角號,會顯示出你的機(jī)型,跑就可以了。

15、如果成功了啊,就按住9括號里面的改一下 然后? 在將build.gradle里面改成 6 那樣紙的就好了。然后 點(diǎn)擊? buile 里面的 Rebuild Project 完成之后 在點(diǎn)擊buile apk 然后將aar和 AndroidManifest.xml復(fù)制到 桌面 等待著 導(dǎo)入unity 中。emmm......unity不用我多說了吧? 。

16、 新建一個unity的工程然后在Accets 文件夾下面創(chuàng)建一個Plugins 文件夾,而后在Plugins里面創(chuàng)建一個android 文件夾,將導(dǎo)出的aar包和 AndroidManifest.xml 導(dǎo)入進(jìn)去 ,之后呢? ,迂回一下,將你解壓完成的高德地圖里面的jar里面的 assets 文件夾復(fù)制一份,丟入unity中和 aar 包他們在一起。

17、之后的事情嗎 簡單的多了, 設(shè)置一個按鈕,當(dāng)點(diǎn)擊按鈕時候 unity 調(diào)用 android里面的方法,進(jìn)入地圖和定位、? button 我就不說了,各位 unity大佬,自行搞定唄emmm.....出事別怪我頭上。。。記得啊 把你MainActivity中的onCreate 的調(diào)用的函數(shù)刪除啊。
unity 調(diào)用安卓的方法:超級簡單。。mmp,我覺得 前兩句就是固定的,call的時候一定看清楚你 的返回值是什么 如果有返回值 那么就要在call<你的返回值類型>,如果要傳參數(shù) 就?? jo.Call("你在andoid studio里面的函數(shù)名", 傳的參數(shù));?可以多個參數(shù)中間用“,”,這樣就調(diào)用了android 的方法,別問我為什么這樣可以,也別天吶,怎么可以這么簡單,emmm.......因?yàn)? mmp,我也我也很懵逼啊,蛋疼。
AndroidJavaClass jc;? AndroidJavaObject jo;
public void GameCreat() {
jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic("currentActivity");
?jo.Call("OtherGameLocation");
? ? }
18、最后一步,別特么 開心的直接跑unity ,因?yàn)槟阋慌苋?unity 就會告訴你: 對不起,請在真機(jī)上測試。。。。。。。。
打包 自己搞吧,記得把 sdk和jdk路徑寫上、、好了,打包成功就差不多了 。
特別感謝兩個老哥,幫了我好多的忙。
最后? 別特么問我太難的問題 老子也懵逼啊? 我也是萌新啊 。。。。。。。emmmm.......
一般問題網(wǎng)上都有答案,可以自己百度下,我寫的可能不全 歡迎各位大佬給指正下~~~。 寫的很詳細(xì)了 一般按照我說的來的話應(yīng)該是沒問題的。
成功了的話 ,記得給刷一顆小心啊~~~~~~~