Unity +Android studio + 高德地圖 == 地圖顯示和定位

? 初次寫這個,記錄一下 我這個從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 ? ??

關(guān)鍵點(diǎn),圈出來?。。?!否則 ,后果自費(fèi)。

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)該是沒問題的。

成功了的話 ,記得給刷一顆小心啊~~~~~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容