修改Android 4.2.2的原生Camera应用,做一些定制,将Camera的包名从之前的 package com.android.* 修改成了com.zhao3546.*。

调整后,应用可以正常运行,但是Camera自带的特效编辑等功能,无法正常使用。一点图片编辑的图标,就出现了下面的异常:

09-12 18:52:48.131: E/AndroidRuntime(6071): java.lang.UnsatisfiedLinkError: Native method not found: com.zhao3546.gallery3d.filtershow.filters.ImageFilterFx.nativeApplyFilter:(Landroid/graphics/Bitmap;IILandroid/graphics/Bitmap;II)V09-12 18:52:48.131: E/AndroidRuntime(6071): at com.zhao3546.gallery3d.filtershow.filters.ImageFilterFx.nativeApplyFilter(Native Method)09-12 18:52:48.131: E/AndroidRuntime(6071): at com.zhao3546.gallery3d.filtershow.filters.ImageFilterFx.apply(ImageFilterFx.java:58)09-12 18:52:48.131: E/AndroidRuntime(6071): at com.zhao3546.gallery3d.filtershow.presets.ImagePreset.apply(ImagePreset.java:291)09-12 18:52:48.131: E/AndroidRuntime(6071): at com.zhao3546.gallery3d.filtershow.cache.DirectPresetCache.compute(DirectPresetCache.java:156)09-12 18:52:48.131: E/AndroidRuntime(6071): at com.zhao3546.gallery3d.filtershow.cache.DelayedPresetCache.handleMessage(DelayedPresetCache.java:50)


原来,ImageFilterFx.nativeApplyFilter() 的这个方法是通过JNI实现的,想想也是,不使用JNI的话,使用Java实现图片编辑的特效,效率要低不少。

关于JNI的介绍,个人觉得写得最好的是《Android框架揭秘》这本书的 “第四章 JNI和NDK”,从示例出发,再将原理娓娓道来,很深入浅出。

言归正传,看看怎么解决吧。

如下是根据 nativeApplyFilter 关键字搜索,找到的结果如下,只保留一小部分:

---- nativeApplyFilter Matches (55 in 30 files) ----Bw.c (jni\filters):void JNIFUNCF(ImageFilterBW, nativeApplyFilter, jobject bitmap, jint width, jint height)Bw.c (jni\filters):void JNIFUNCF(ImageFilterBWRed, nativeApplyFilter, jobject bitmap, jint width, jint height)Bw.c (jni\filters):void JNIFUNCF(ImageFilterBWGreen, nativeApplyFilter, jobject bitmap, jint width, jint height)Bw.c (jni\filters):void JNIFUNCF(ImageFilterBWBlue, nativeApplyFilter, jobject bitmap, jint width, jint height)Bwfilter.c (jni\filters):void JNIFUNCF(ImageFilterBwFilter, nativeApplyFilter, jobject bitmap, jint width, jint height, jint rw, jint gw, jint bw)Contrast.c (jni\filters):void JNIFUNCF(ImageFilterContrast, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat bright)Exposure.c (jni\filters):void JNIFUNCF(ImageFilterExposure, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat bright)Fx.c (jni\filters):void JNIFUNCF(ImageFilterFx, nativeApplyFilter, jobject bitmap, jint width, jint height, jobject lutbitmap,jint lutwidth, jint lutheight )Geometry.c (jni\filters):void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterFlip, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint flip) {Geometry.c (jni\filters):void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterRotate, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint rotate) {Geometry.c (jni\filters):void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterCrop, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint offsetWidth, jint offsetHeight) {Geometry.c (jni\filters):void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterStraighten, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jfloat straightenAngle) {Hue.c (jni\filters):void JNIFUNCF(ImageFilterHue, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloatArray matrix)ImageFilterBW.java (src\com\android\gallery3d\filtershow\filters):    native protected void nativeApplyFilter(Bitmap bitmap, int w, int h);ImageFilterBW.java (src\com\android\gallery3d\filtershow\filters):        nativeApplyFilter(bitmap, w, h);


Native方法的实现,肯定是在C或CPP中,直接看第一个结果吧:

void JNIFUNCF(ImageFilterBW, nativeApplyFilter, jobject bitmap, jint width, jint height){    ...}


JNIFUNCF这个函数名有点怪啊,怎么全是大写,C或C++中,全大写一般是都常量或宏,啥情况?

看看是怎么定义的,再根据JNIFUNCF搜索下,在filters.h中有定义:

#define JNIFUNCF(cls, name, vars...) Java_com_android_gallery3d_filtershow_filters_ ## cls ## _ ## name(JNIEnv* env, jobject obj, vars)

原来是个宏,这个宏是啥意思如果你不明白,需要了解一些C的基础,

此处将 “Java_com_android_gallery3d_filtershow_filters_” 和 cls 对应的实际值和 name 对应的实际值,拼接成一个字符串作为实际的方法名。


之前我们修改了Java的包名,但是 Java_com_android_gallery3d_filtershow_filters_ 这个没有修改,所以导致最终生成的方法与修改后Java实现的Native方法的符号匹配不上了,将 Java_com_android_gallery3d_filtershow_filters_ 修改成 Java_com_zhao3546_gallery3d_filtershow_filters_ ,再放到源码编译环境上重新生成相应的so,再重新生成APK测试,ok,问题解决。

了解JNI机制,才是解决此类问题的KEY。

更多相关文章

  1. Android(安卓)Camera2教程之打开相机、开启预览、实现PreviewCal
  2. android 单元测试方法 类继承 Instrumentation
  3. android之定时器AlarmManager .
  4. android小知识之意图(intent)
  5. Android(安卓)ActivityGroup实现tab功能
  6. Android之TelephonyManager类的方法详解
  7. OkHttp在Android中使用详解
  8. Android(安卓)Handler消息机制
  9. android 按两次返回键强制退出整个APP

随机推荐

  1. c语言二进制如何表示
  2. c语言中的关键字有哪些类型?
  3. c语言中long是什么意思
  4. c语言0x什么意思
  5. printf在c语言中什么意思
  6. c语言中void的含义
  7. c语言的基本组成单位是什么
  8. c语言switch case语句怎么用
  9. c语言strcpy函数用法
  10. c语言scanf是啥意思