Unity +Android studio + 高德地图 == 地图显示和定位

  初次写这个,记录一下 我这个从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.......

一般问题网上都有答案,可以自己百度下,我写的可能不全 欢迎各位大佬给指正下~~~。 写的很详细了 一般按照我说的来的话应该是没问题的。

成功了的话 ,记得给刷一颗小心啊~~~~~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,406评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,976评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,302评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,366评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,372评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,457评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,872评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,521评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,717评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,523评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,590评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,299评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,859评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,883评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,127评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,760评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,290评论 2 342