百度地图定位集成及问题汇总No implementation found for int com.baidu.platform.comjni.tools.JNITools.initClass

本文档详细介绍了如何在Android应用中集成百度地图定位功能,包括库文件的导入、AndroidManifest.xml的配置以及权限声明等内容。同时,针对集成过程中常见的错误提供了具体的排查和解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于在百度地图使用的过程中遇到各种问题,这里简单整理一下。

1.地图定位集成

导入库文件

在下载页面下载最新的库文件。将liblocSDK2.4.so文件拷贝到libs/armeabi目录下。将locSDK2.4.jar文件拷贝到工程根目录下,并在工程属性->Java Build Path->Libraries中选择“Add JARs”,选定locSDK2.4.jar,确定后返回。这样您就可以在程序中使用百度定位API了。 

设置AndroidManifest.xml

为区分2.3版本service,需要将manifest file中的 intent filter声明为com.baidu.location.service_v2.4 在application标签中声明service组件

 
  1. <service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote"
  2. android:permission="android.permission.BAIDU_LOCATION_SERVICE">
  3. <intent-filter>
  4. <action android:name="com.baidu.location.service_v2.4"></action>
  5. </intent-filter>
  6. </service>

声明使用权限

 
  1. <permission android:name="android.permission.BAIDU_LOCATION_SERVICE"></permission>
  2. <uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE"></uses-permission>
  3. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
  4. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
  5. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
  6. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
  7. <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
  8. <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
  9. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
  10. <uses-permission android:name="android.permission.INTERNET" />
  11. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
  12. <uses-permission android:name="android.permission.READ_LOGS"></uses-permission>

import相关类

 
  1. import com.baidu.location.BDLocation ;
  2. import com.baidu.location.BDLocationListener ;
  3. import com.baidu.location.LocationClient ;
  4. import com.baidu.location.LocationClientOption ;
  5. import com.baidu.location.BDNotifyListener ; //假如用到位置提醒功能,需要import该类

功能类的使用

初始化LocationClient类

此处需要注意:LocationClient类必须在主线程中声明。需要Context类型的参数。

 
  1. public LocationClient mLocationClient = null ;
  2. public BDLocationListener myListener = new MyLocationListener ( ) ;
  3.  
  4. public void onCreate ( ) {
  5. mLocationClient = new LocationClient ( this ) ; //声明LocationClient类
  6. mLocationClient. registerLocationListener ( myListener ) ; //注册监听函数
  7. }

实现BDLocationListener接口

BDLocationListener接口有2个方法需要实现:
1.接收异步返回的定位结果,参数是BDLocation类型参数。
2.接收异步返回的POI查询结果,参数是BDLocation类型参数。

 
  1. public class MyLocationListenner implements BDLocationListener {
  2. @Override
  3. public void onReceiveLocation (BDLocation location ) {
  4. if (location == null )
  5. return ;
  6. StringBuffer sb = new StringBuffer ( 256 ) ;
  7. sb. append ( "time : " ) ;
  8. sb. append (location. getTime ( ) ) ;
  9. sb. append ( "\nerror code : " ) ;
  10. sb. append (location. getLocType ( ) ) ;
  11. sb. append ( "\nlatitude : " ) ;
  12. sb. append (location. getLatitude ( ) ) ;
  13. sb. append ( "\nlontitude : " ) ;
  14. sb. append (location. getLongitude ( ) ) ;
  15. sb. append ( "\nradius : " ) ;
  16. sb. append (location. getRadius ( ) ) ;
  17. if (location. getLocType ( ) == BDLocation. TypeGpsLocation ) {
  18. sb. append ( "\nspeed : " ) ;
  19. sb. append (location. getSpeed ( ) ) ;
  20. sb. append ( "\nsatellite : " ) ;
  21. sb. append (location. getSatelliteNumber ( ) ) ;
  22. } else if (location. getLocType ( ) == BDLocation. TypeNetWorkLocation ) {
  23. sb. append ( "\naddr : " ) ;
  24. sb. append (location. getAddrStr ( ) ) ;
  25. }
  26.  
  27. logMsg (sb. toString ( ) ) ;
  28. }
  29. public void onReceivePoi (BDLocation poiLocation ) {
  30. if (poiLocation == null ) {
  31. return ;
  32. }
  33. StringBuffer sb = new StringBuffer ( 256 ) ;
  34. sb. append ( "Poi time : " ) ;
  35. sb. append (poiLocation. getTime ( ) ) ;
  36. sb. append ( "\nerror code : " ) ;
  37. sb. append (poiLocation. getLocType ( ) ) ;
  38. sb. append ( "\nlatitude : " ) ;
  39. sb. append (poiLocation. getLatitude ( ) ) ;
  40. sb. append ( "\nlontitude : " ) ;
  41. sb. append (poiLocation. getLongitude ( ) ) ;
  42. sb. append ( "\nradius : " ) ;
  43. sb. append (poiLocation. getRadius ( ) ) ;
  44. if (poiLocation. getLocType ( ) == BDLocation. TypeNetWorkLocation ) {
  45. sb. append ( "\naddr : " ) ;
  46. sb. append (poiLocation. getAddrStr ( ) ) ;
  47. }
  48. if (poiLocation. hasPoi ( ) ) {
  49. sb. append ( "\nPoi:" ) ;
  50. sb. append (poiLocation. getPoi ( ) ) ;
  51. } else {
  52. sb. append ( "noPoi information" ) ;
  53. }
  54. logMsg (sb. toString ( ) ) ;
  55. }
  56. }

设置参数

设置定位参数包括:定位模式(单次定位,定时定位),返回坐标类型,是否打开GPS等等。eg:

 
  1. LocationClientOption option = new LocationClientOption ( ) ;
  2. option. setOpenGps ( true ) ;
  3. option. setAddrType ( "detail" ) ;
  4. option. setCoorType ( "gcj02" ) ;
  5. option. setScanSpan ( 5000 ) ;
  6. option. disableCache ( true ) ; //禁止启用缓存定位
  7. option. setPoiNumber ( 5 ) ; //最多返回POI个数
  8. option. setPoiDistance ( 1000 ) ; //poi查询距离
  9. option. setPoiExtraInfo ( true ) ; //是否需要POI的电话和地址等详细信息
  10. mLocClient. setLocOption (option ) ;

发起定位请求

发起定位请求。请求过程是异步的,定位结果在上面的监听函数onReceiveLocation中获取。

 
  1. if (mLocClient != null && mLocClient. isStarted ( ) )
  2. mLocClient. requestLocation ( ) ;
  3. else
  4. Log. d ( "LocSDK_2.0_Demo1", "locClient is null or not started" ) ;

发起POI查询请求

发起POI查询请求。请求过程是异步的,定位结果在上面的监听函数onReceivePoi中获取。

 
  1. if (mLocClient != null && mLocClient. isStarted ( ) )
  2. mLocClient. requestPoi ( ) ;

位置提醒使用

位置提醒最多提醒3次,3次过后将不再提醒。 假如需要再次提醒,或者要修改提醒点坐标,都可通过函数SetNotifyLocation()来实现。

 
  1. //位置提醒相关代码
  2. mNotifyer = new NotifyLister ( ) ;
  3. mNotifyer. SetNotifyLocation ( 42.03249652949337, 113.3129895882556, 3000, "gps" ) ; //4个参数代表要位置提醒的点的坐标,具体含义依次为:纬度,经度,距离范围,坐标系类型(gcj02,gps,bd09,bd09ll)
  4. mLocationClient. registerNotify (mNotifyer ) ;
  5. //注册位置提醒监听事件后,可以通过SetNotifyLocation 来修改位置提醒设置,修改后立刻生效。

 
  1. //BDNotifyListner实现
  2. public class NotifyLister extends BDNotifyListener {
  3. public void onNotify (BDLocation mlocation, float distance ) {
  4. mVibrator01. vibrate ( 1000 ) ; //振动提醒已到设定位置附近
  5. }
  6. }
  1. //取消位置提醒
  2. mLocationClient. removeNotifyEvent (mNotifyer ) ;
 
2.集成时报错: 
(1) No implementation found for int com.baidu.platform.comjni.tools.JNITools.initClass(java.lang.Object, int) (tried Java_com_baidu_platform_comjni_tools_JNITools_initClass and Java_com_baidu_platform_comjni_tools_JNITools_initClass__Ljava_lang_Object_2I)
这个问题 目前碰到, 有4个原因:
1. SDKInitializer 方法执行的位置不对  
2. so 文件 没有放到 jniLibs 下(并且  armeabi   armeabi-v7a  mips x86 都要放一份)
       不过即使 都放了 一份也不能保证 模拟器是 没有问题, 真机 目前 测试没有发现问题。
3. 是一个最隐秘,也是比较恶心的问题:
     相应功能的开发资源的时候,你可能选择 
基础地图   or  基础地图 + 计算 工具  or 基础地图+ 定位功能 + 计算工具,

不同组合下载下来的,通常 都已 两个文件,分别是:
BaiduLBS_Android.jar
libBaiduMapSDK_v3_4_0_X.so (X 代表 0  1 2 .....)

不同组合 的这个两个文件 都不同( 看起来jar 是同名) , 

如果你把 基础地图 的 jar   +  (基础地图 + 计算 工具) 的 sdk . so ,组合编译,就会出现上述问题

4. 模拟器运行 (即使 armeabi   armeabi-v7a  mips x86 放一份) 也无法解决, @百度  这个你们得看看吧??
    无奈只有:
         if (!"generic".equalsIgnoreCase(Build.BRAND)) {
            SDKInitializer.initialize(getApplicationContext());
        }
在这里。如果使用androidStudio 最好将.so文件放在 src/main 下面自己创建的jniLibs文件夹下面。这种方式不必配置module的build.gradle文件。
如果所有.so文件放在libs文件夹下,AS不会主动加载libs下面so库,需要手动引导配置:
  1. android {

  2.     sourceSets {
  3.         main {
  4.             manifest.srcFile 'AndroidManifest.xml'
  5.             //添加下面一行就行了,其他的不用动
  6.             jniLibs.srcDirs = ['libs']
  7.         }

  8.     
  9. }
(2)  errorcode: 230 uid: -1 appid -1 msg: APP Scode码校验失败 

首先,了解下什么是230错误:

为增强移动APP对百度开发SDK/API服务访问的控制,也避免恶意开发者对百度地图服务进行攻击,我们对Mobile类型(Android/IOS)的服务请求进行了安全码校验;所谓安全码即开发者在API控制台申请AKAKAPP一一对应)时提供的APP签名的SHA1+”;”+包名

(具体可参考http://developer.baidu.com/map/index.php?title=androidsdk/guide/key)。

请求服务必须要携带该安全码作为参数,不携带或者携带不一致的安全码给服务端,均会返回230错误。

一般的解决方式: 

 查看一下APP当前签名的SHA1值(注意不是MD5)和包名,然后去API控制台把查看该AK对应配置的安全码是否和           APP实际的一致

 如果检查后数字签名、包名、API_KEY没错的话,就是下面说的第二种问题了。

【1】AK错误 :那么就检查你的数字签名和包名有没有弄错

                          (我的检验后证明不是第一种错误)

        

【2】签名文件没有打包到程序

  菜单栏选择 file -> project structure,选择应用的modules

安全码是sdk自动从APP配置中获取的,开发者无需自己填写。当出现230错误时,请开发者先查看一下APP当前签名的SHA1值(注意不是MD5)和包名,然后去API控制台把查看该AK对应配置的安全码是否和APP实际的一致,如果不一致请去API控制台手动修改一致即可~~

3. java.lang.UnsatisfiedLinkError: No implementation found for int com.baidu.platform.comjni.tools.JNITools.initClass

  • 解决方案:百度地图接入的配置有两种方法:
1.如果你是将jar包和so文件都放在app-libs文件夹下,就需要在build.grade文件中添加代码指定so文件路径,具体看截图



2.第二种配置方式是将jar包放在app-libs文件夹下,而将so文件放在src-main-jniLibs文件夹下,这个位置的so文件,工程会自动加载,不用做其他处理.


3.完成上面的步骤,并在清单文件中设置了百度API_KEY值,就可以愉快的试用了.
接下来,专门文章介绍AndroidStudio如何申请

百度地图新版Key中SHA1值:详情请转下一篇文章:http://blog.youkuaiyun.com/maiduoudo/article/details/78399790

 

<think>好的,我现在需要解决用户遇到的“No implementation found for ExternalPrintController.closeDevice”错误。这个问题通常出现在使用NDK时,Java本地方法没有对应的C/C++实现或者链接错误。让我先回忆一下相关的知识。 根据引用[2]和[5],这个错误是java.lang.UnsatisfiedLinkError,说明JNI在调用本地方法时找不到对应的原生实现。可能的原因有几个:首先,生成的C/C++函数名不符合JNI的命名规则,比如包名、类名或方法名的大小写不一致。其次,生成的.so文件没有被正确加载,或者加载的库名不正确。另外,也有可能是在编译过程中没有将对应的C/C++文件包含进去,导致方法没有被编译进.so库中。 接下来,我需要按照步骤来排查问题。首先检查Java中的native方法声明是否正确,确保方法名和参数与C++中的实现一致。然后检查JNI函数的命名是否遵循规范,比如包名中的点要转换为下划线,类名和方法名要保持一致。例如,如果Java方法是com.example.ExternalPrintController.closeDevice,对应的C函数名应该是Java_com_example_ExternalPrintController_closeDevice。 然后需要确认.so库是否正确加载。在Java中应该使用System.loadLibrary("库名"),而库名对应的文件应该是lib库名.so。比如加载库名为“externalprint”,则文件名为libexternalprint.so。同时,要确保.so文件被正确打包到APK的jni目录下的对应ABI文件夹中。 另外,编译过程中是否包含了对应的C/C++文件?比如在Android.mk或CMakeLists.txt中是否有将包含该方法的源文件加入编译。引用[3]提到修改Android.mk文件后成功生成so库,所以需要检查编译配置是否正确。 还有,函数签名是否一致?Java中的方法签名和C++中的参数是否匹配,比如是否有JNIEnv*和jobject参数,以及返回类型是否正确。如果方法有参数,是否在C++中正确声明? 另外,可能需要检查是否有拼写错误,比如类名或方法名的大小写问题,这在JNI中是很严格的。还要确认在调用native方法之前已经成功加载了.so库,否则会报错。 如果以上步骤都检查过了,还是有问题,可能需要使用ndk-build的命令查看编译时的日志,确认是否有编译错误或链接错误。或者使用objdump工具查看.so文件中的符号,确认对应的JNI函数是否存在。 最后,如果用户是新手,可能需要指导他们如何正确配置NDK环境,包括Android.mk或CMake的配置,以及如何生成正确的头文件,使用javah或javac -h命令。引用[4]提到不能直接包含javah生成的.h文件,可能需要调整,所以需要确保生成的函数名正确,并且实现部分没有遗漏。 总结一下,解决这个问题的步骤大致是:检查方法声明和实现的一致性,确认库加载正确,检查编译配置和符号存在,以及验证函数签名是否正确。接下来我需要将这些步骤整理成用户容易理解的解决方案,分点说明,并给出示例代码和命令,帮助用户逐步排查问题。</think>针对“No implementation found for ExternalPrintController.closeDevice”错误,以下是分步解决方案: --- ### **问题原因分析** 该错误属于`java.lang.UnsatisfiedLinkError`,表示JVM在调用JNI方法时未找到对应的C/C++实现。可能原因包括: 1. **JNI函数命名不规范**(如包名/类名/方法名不匹配)[^2][^4]。 2. **未正确加载.so库**(库名错误或路径问题)[^5]。 3. **C/C++代码未编译进.so文件**(编译配置遗漏)[^3]。 4. **函数签名不一致**(参数或返回值类型不匹配)。 --- ### **解决步骤** #### **1. 检查JNI函数命名规范** Java中的native方法声明为: ```java public native void closeDevice(); ``` 对应的C++实现函数名必须遵循格式: `Java_{包名}_{类名}_{方法名}`,其中包名的`.`替换为`_`,类名和方法名需完全一致。例如: ```cpp // 假设包名为com.example,类名为ExternalPrintController extern "C" JNIEXPORT void JNICALL Java_com_example_ExternalPrintController_closeDevice(JNIEnv* env, jobject thiz) { // 实现代码 } ``` > **注意**:若类名含下划线(如`External_PrintController`),需在JNI函数名中保留`_1`(例如`External_1PrintController`)[^4]。 --- #### **2. 确认.so库正确加载** 在Java类中通过`System.loadLibrary`加载库: ```java static { System.loadLibrary("externalprint"); // 对应libexternalprint.so } ``` 检查: - **库名一致性**:`.so`文件前缀需为`lib`,如`libexternalprint.so`。 - **打包路径**:确保.so文件位于`app/src/main/jniLibs/{abi}`目录下(如`arm64-v8a`)[^3]。 --- #### **3. 验证编译配置** 在`CMakeLists.txt`或`Android.mk`中确保包含目标源文件: ```cmake # CMake示例 add_library(externalprint SHARED src/main/cpp/external_print_controller.cpp # 包含closeDevice实现的文件 ) ``` 编译后检查`.so`文件是否包含符号: ```bash # 使用nm命令查看符号(需NDK工具链) nm -D libexternalprint.so | grep closeDevice ``` 输出应包含`Java_com_example_ExternalPrintController_closeDevice`。 --- #### **4. 检查函数签名** 使用`javac -h`生成JNI头文件,确保函数签名一致: ```bash # 生成头文件 javac ExternalPrintController.java -h ./jni ``` 头文件会生成函数原型,直接复制到C++代码中。 --- #### **5. 排查常见错误** - **线程问题**:JNI函数需在Java线程调用,避免跨线程访问JNIEnv。 - **ProGuard混淆**:在`proguard-rules.pro`中保留native方法: ```proguard -keepclasseswithmembers class com.example.ExternalPrintController { native <methods>; } ``` --- ### **示例代码** ```cpp // external_print_controller.cpp #include <jni.h> extern "C" JNIEXPORT void JNICALL Java_com_example_ExternalPrintController_closeDevice(JNIEnv* env, jobject thiz) { // 关闭设备的实现逻辑 } ``` --- ### **相关问题** 1. 如何生成JNI头文件? 2. NDK编译时如何指定不同的ABI? 3. JNI中如何处理Java对象和C++对象的交互? 4. 如何调试JNI层的崩溃问题? 通过以上步骤,可系统性解决`No implementation found`错误。若问题仍存在,建议检查NDK本兼容性及编译日志。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值