jni获得应用icon有两步
1.在java端写一个方法,通过包名获取appIcon,返回byte[]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public static byte[] getAppIcon(String packageName) { BzDebugLog.i(TAG, "getAppIcon, " + packageName); try { PackageManager pm = BzAppConfig.context.getContext().getApplicationContext().getPackageManager(); Drawable iconDrawable = pm.getApplicationIcon(packageName); Bitmap my_bitmap = ((BitmapDrawable) iconDrawable).getBitmap(); ByteArrayOutputStream stream = new ByteArrayOutputStream(); my_bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] b = stream.toByteArray(); // String encodedString = new String(b); return stream.toByteArray(); } catch (Exception e) { BzDebugLog.e(TAG, "getAppIcon error: " + e.toString()); return null; } } |
native初始化时,获取这个method,同时拿到VM和全局context
jobject mBzAppContext;
JavaVM *m_appContext_VM = NULL;
mAppContext = env->NewGlobalRef(thiz);
env->GetJavaVM(&m_appContext_VM);
FIND_CLASS(clazz, "com/xx/xx/xx");
if (clazz == NULL) {
loge("class not exist!!");
}
GET_METHOD_ID(gAppGlobalCallMethod.getAppIcon, clazz,
"getAppIcon", "(Ljava/lang/String;)[B");
if (gAppGlobalCallMethod.getAppIcon == NULL) {
loge("method get fail!!");
}
(Ljava/lang/String;)[B 指入参是String,回参是jbyteArray
2.调用jni函数,拿到byte[],转成char*
void readAppIcon(const char* packageName)
{
if (m_appContext_VM == NULL) {
loge("m_appContext_VM null");
return;
}
if (mAppContext == NULL) {
loge("mAppContext null");
return;
}
if (gAppGlobalCallMethod.getAppIcon== NULL) {
loge("gAppGlobalCallMethod.getAppIcon null");
return;
}
CHECK_JVM_THREAD(m_appContext_VM);
if (error) {
loge("check jvm thread error");
return;
}
jstring jPackageName = env->NewStringUTF(packageName);
jbyteArray jbarray = (jbyteArray)env->CallObjectMethod(mBzAppContext, gAppGlobalCallMethod.getAppIcon, jPackageName);
if (jbarray == nullptr) {
logi("getAppIcon null");
} else {
len = (int)env->GetArrayLength (jbarray);
char *data = (char*)env->GetByteArrayElements(jbarray, 0);
// 这里就把appicon拿到并转成了char*,注意释放data
env->ReleaseByteArrayElements(jbarray, data, 0);
}
if (attached) {
m_appContext_VM->DetachCurrentThread();
}
}