初次写这个,记录一下 我这个从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.......
一般问题网上都有答案,可以自己百度下,我写的可能不全 欢迎各位大佬给指正下~~~。 写的很详细了 一般按照我说的来的话应该是没问题的。
成功了的话 ,记得给刷一颗小心啊~~~~~~~