在过去的两天里,我一直在探索在我自己的应用程序中使用私有三星框架的可能性.jar特别是/system/frameworks/seccamera。什么都没用,所以我想知道这是否可能。
一些背景
我正在开发一个涉及扫描二维码的应用程序,因此非常依赖于相机图像质量。因此,我正在努力从应用程序级别尽可能多地控制相机。大大提高扫描速度和可靠性的功能之一是相机能够进行点曝光测光。但是,没有用于指定曝光测光模式的公共 API。
但是,使用Galaxy Tab 2上的内置相机应用程序,您可以指定几种曝光测光模式,其中包括点测光模式。所以我决定进一步调查。
我已经尝试过的
- 我使用 Eclipse 从/system/frameworks 中提取了内置相机应用程序的 apk 和 odex 文件
- 我通过 baksmali 运行了 odex 文件,并以一些 .smali 文件结束
- 我在它们中搜索了"曝光测光",并找到了一个类com.sec.android.seccamera.SecCamera,它支持通过其参数内部类指定曝光测光模式 。
我确定这个类驻留在seccamera.jar(seccamera.odex)中,所以我单独删除了它:
java -jar baksmali-1.3.3.jar --deodex seccamera.odex -o seccamera
然后我又把它放在一起:
java -jar smali-1.3.3.jar seccamera/ -o seccamera.dex
最后,我通过 dex2jar 运行 dex-file 创建了一个 jar 库:
../dex2jar-0.0.9.8/dex2jar.sh seccamera.dex
我将其作为外部jar链接到我的Eclipse项目。我发现 SecCamera 类的 API 与公共 android.hardware.Camera 几乎相同,因此它使转换我的代码变得更加容易。
该项目构建时没有错误,但是它在启动时几乎立即崩溃,并出现以下错误:
06-28 16:49:31.648: E/AndroidRuntime(2329): FATAL EXCEPTION: main
06-28 16:49:31.648: E/AndroidRuntime(2329): java.lang.NoClassDefFoundError: com.google.zxing.client.android.camera.PreviewCallback
06-28 16:49:31.648: E/AndroidRuntime(2329): at com.google.zxing.client.android.camera.CameraManager.<init>(CameraManager.java:70)
06-28 16:49:31.648: E/AndroidRuntime(2329): at com.treelev.biennale.MainActivity.onResume(MainActivity.java:212)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1158)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.app.Activity.performResume(Activity.java:4539)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2448)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2486)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2000)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.app.ActivityThread.access$600(ActivityThread.java:128)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.os.Handler.dispatchMessage(Handler.java:99)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.os.Looper.loop(Looper.java:137)
06-28 16:49:31.648: E/AndroidRuntime(2329): at android.app.ActivityThread.main(ActivityThread.java:4514)
06-28 16:49:31.648: E/AndroidRuntime(2329): at java.lang.reflect.Method.invokeNative(Native Method)
06-28 16:49:31.648: E/AndroidRuntime(2329): at java.lang.reflect.Method.invoke(Method.java:511)
06-28 16:49:31.648: E/AndroidRuntime(2329): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
06-28 16:49:31.648: E/AndroidRuntime(2329): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
06-28 16:49:31.648: E/AndroidRuntime(2329): at dalvik.system.NativeStart.main(Native Method)
com.google.zxing.client.android.camera.PreviewCallback
是我的项目类之一,我从ZXing项目中借来的,所以很明显它在那里。我不得不更改它,以便它实现SecCamera.PreviewCallback
而不是Camera.PreviewCallback
.也许这就是这里的罪魁祸首。
在该错误之前,还有其他一些警告:
06-28 16:49:31.625: I/dalvikvm(2329): Failed resolving Lcom/google/zxing/client/android/camera/PreviewCallback; interface 264 'Lcom/sec/android/seccamera/SecCamera$PreviewCallback;'
06-28 16:49:31.625: W/dalvikvm(2329): Link of class 'Lcom/google/zxing/client/android/camera/PreviewCallback;' failed
06-28 16:49:31.625: E/dalvikvm(2329): Could not find class 'com.google.zxing.client.android.camera.PreviewCallback', referenced from method com.google.zxing.client.android.camera.CameraManager.<init>
06-28 16:49:31.625: W/dalvikvm(2329): VFY: unable to resolve new-instance 111 (Lcom/google/zxing/client/android/camera/PreviewCallback;) in Lcom/google/zxing/client/android/camera/CameraManager;
06-28 16:49:31.625: D/dalvikvm(2329): VFY: replacing opcode 0x22 at 0x000c
06-28 16:49:31.632: I/dalvikvm(2329): Could not find method com.sec.android.seccamera.SecCamera.release, referenced from method com.google.zxing.client.android.camera.CameraManager.closeDriver
06-28 16:49:31.632: W/dalvikvm(2329): VFY: unable to resolve virtual method 1436: Lcom/sec/android/seccamera/SecCamera;.release ()V
06-28 16:49:31.632: D/dalvikvm(2329): VFY: replacing opcode 0x6e at 0x0007
06-28 16:49:31.632: I/dalvikvm(2329): Could not find method com.sec.android.seccamera.SecCamera.open, referenced from method com.google.zxing.client.android.camera.CameraManager.openDriver
06-28 16:49:31.632: W/dalvikvm(2329): VFY: unable to resolve static method 1435: Lcom/sec/android/seccamera/SecCamera;.open ()Lcom/sec/android/seccamera/SecCamera;
06-28 16:49:31.632: D/dalvikvm(2329): VFY: replacing opcode 0x71 at 0x0005
06-28 16:49:31.632: I/dalvikvm(2329): Could not find method com.sec.android.seccamera.SecCamera.setPreviewDisplay, referenced from method com.google.zxing.client.android.camera.CameraManager.openDriver
06-28 16:49:31.632: W/dalvikvm(2329): VFY: unable to resolve virtual method 1439: Lcom/sec/android/seccamera/SecCamera;.setPreviewDisplay (Landroid/view/SurfaceHolder;)V
06-28 16:49:31.632: D/dalvikvm(2329): VFY: replacing opcode 0x6e at 0x0016
那么,我在这里做错了什么?是否可以在我的自定义应用程序中使用私有框架(而不是修补现有应用程序)?
当使用这样的外部库时,你必须通知包管理器在运行时链接它们
在这种情况下,您可以将以下 XML 添加到 AndroidManifest 中的
<uses-library android:name="seccamera" />
Android 在启动时读取/system/etc/permissions/seccamera.xml,并将 secCamera lib 名称映射到 xml 提到的文件(在本例中为/system/framework/seccamera.jar)
然后,当您将其标记为已使用的库时,操作系统将在运行时链接该代码,并且您可以自由使用这些类
看起来你已经弄清楚了困难的部分,让 Eclipse 针对它进行编译
至于"窃取"代码,只要您不与任何人共享重建的 seccamera.jar并且仅使用它来引用代码中的函数(不要将其包含在 apk 中),我看不出任何真正的问题
但三星可能会稍后在没有警告的情况下更改 API 并破坏您的应用程序
您可能还希望将其标记为不需要 1,否则它将拒绝在没有该库的设备上安装