Android JNI: java.lang.UnsatisfiedLinkError

Я пишу код, чтобы очистить собственную кучу, которая увеличивает мои собственные результаты кучи из-за ошибки нехватки памяти. Таким образом, я пишу код с использованием Android ndk, но это дает java.lang.UnsatisfiedLinkError

вот мой код

android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := sounds_english
LOCAL_SRC_FILES := JniBitmapStorageTest.cpp
LOCAL_LDLIBS := -llog
LOCAL_LDFLAGS += -ljnigraphics

include $(BUILD_SHARED_LIBRARY)
APP_OPTIM := debug
LOCAL_CFLAGS := -g

JniBitmapStorageTest.cpp

#include <jni.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <android/bitmap.h>
#include <cstring>
#include <unistd.h>#define  LOG_TAG    "DEBUG"#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

extern "C"{
JNIEXPORT jobject JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap);
JNIEXPORT jobject JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle);
JNIEXPORT void JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle);
}

class JniBitmap
{
public:
uint32_t* _storedBitmapPixels;
AndroidBitmapInfo _bitmapInfo;
JniBitmap()
{
_storedBitmapPixels = NULL;
}
};

JNIEXPORT void JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
return;
delete[] jniBitmap->_storedBitmapPixels;
jniBitmap->_storedBitmapPixels = NULL;
delete jniBitmap;
}

JNIEXPORT jobject JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
{
LOGD("no bitmap data was stored. returning null...");
return NULL;
}
//
//creating a new bitmap to put the pixels into it - using Bitmap Bitmap.createBitmap (int width, int height, Bitmap.Config config) :
//
//LOGD("creating new bitmap...");
jclass bitmapCls = env->FindClass("android/graphics/Bitmap");
jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jstring configName = env->NewStringUTF("ARGB_8888");
jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass, valueOfBitmapConfigFunction, configName);
jobject newBitmap = env->CallStaticObjectMethod(bitmapCls, createBitmapFunction, jniBitmap->_bitmapInfo.height, jniBitmap->_bitmapInfo.width, bitmapConfig);
//
// putting the pixels into the new bitmap:
//
int ret;
void* bitmapPixels;
if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &bitmapPixels)) < 0)
{
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
return NULL;
}
uint32_t* newBitmapPixels = (uint32_t*) bitmapPixels;
int pixelsCount = jniBitmap->_bitmapInfo.height * jniBitmap->_bitmapInfo.width;
memcpy(newBitmapPixels, jniBitmap->_storedBitmapPixels, sizeof(uint32_t) * pixelsCount);
AndroidBitmap_unlockPixels(env, newBitmap);
//LOGD("returning the new bitmap");
return newBitmap;
}

JNIEXPORT jobject JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap)
{
AndroidBitmapInfo bitmapInfo;
uint32_t* storedBitmapPixels = NULL;
//LOGD("reading bitmap info...");
int ret;
if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0)
{
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return NULL;
}
LOGD("width:%d height:%d stride:%d", bitmapInfo.width, bitmapInfo.height, bitmapInfo.stride);
if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
{
LOGE("Bitmap format is not RGBA_8888!");
return NULL;
}
//
//read pixels of bitmap into native memory :
//
//LOGD("reading bitmap pixels...");
void* bitmapPixels;
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0)
{
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
return NULL;
}
uint32_t* src = (uint32_t*) bitmapPixels;
storedBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
int pixelsCount = bitmapInfo.height * bitmapInfo.width;
memcpy(storedBitmapPixels, src, sizeof(uint32_t) * pixelsCount);
AndroidBitmap_unlockPixels(env, bitmap);
JniBitmap *jniBitmap = new JniBitmap();
jniBitmap->_bitmapInfo = bitmapInfo;
jniBitmap->_storedBitmapPixels = storedBitmapPixels;
return env->NewDirectByteBuffer(jniBitmap, 0);
}

JniBitmapHolder.java

package com.example.sounds_english;

import java.nio.ByteBuffer;

import android.graphics.Bitmap;
import android.util.Log;

public class JniBitmapHolder
{
ByteBuffer _handler =null;
static
{
System.loadLibrary("sounds_english");
}

private native ByteBuffer jniStoreBitmapData(Bitmap bitmap);

private native Bitmap jniGetBitmapFromStoredBitmapData(ByteBuffer handler);

private native void jniFreeBitmapData(ByteBuffer handler);

public JniBitmapHolder()
{}

public JniBitmapHolder(final Bitmap bitmap)
{
storeBitmap(bitmap);
}

public void storeBitmap(final Bitmap bitmap)
{
if(_handler!=null)
freeBitmap();
_handler=jniStoreBitmapData(bitmap);
}

public Bitmap getBitmap()
{
if(_handler==null)
return null;
return jniGetBitmapFromStoredBitmapData(_handler);
}

public Bitmap getBitmapAndFree()
{
final Bitmap bitmap=getBitmap();
freeBitmap();
return bitmap;
}

public void freeBitmap()
{
if(_handler==null)
return;
jniFreeBitmapData(_handler);
_handler=null;
}

@Override
protected void finalize() throws Throwable
{
super.finalize();
if(_handler==null)
return;
Log.w("DEBUG","JNI bitmap wasn't freed nicely.please rememeber to free the bitmap as soon as you can");
freeBitmap();
}
}

myactivity.java

      aa=p2.getWordimage();
aa1=decodeSampledBitmapFromResource(aa);
final JniBitmapHolder bitmapHolder=new   JniBitmapHolder(aa1);
aa1.recycle();aa1=bitmapHolder.getBitmapAndFree();

iv.setImageBitmap(aa1);

public Bitmap decodeSampledBitmapFromResource(byte[] aa)
{
return BitmapFactory.decodeByteArray(aa, 0, aa.length,option);
}

1

Решение

Я предполагаю, что имя вашего пакета содержит подчеркивание, но подчеркивание используется для определения структуры пакета в определениях функций JNI. Возможно, «sounds_english» вызывает проблему. Я предлагаю вам не использовать подчеркивания в вашей структуре пакета.

1

Другие решения

Проблема заключается в подчеркивании в вашем пакете (как уже упоминалось @ user2359247).

Изменить все случаи:

Java_com_example_sounds_english_JniBitmapHolder_jniStoreBitmapData
Java_com_example_sounds_english_JniBitmapHolder_jniGetBitmapFromStoredBitmapData
Java_com_example_sounds_english_JniBitmapHolder_jniFreeBitmapData

чтобы:

Java_com_example_sounds_1english_JniBitmapHolder_jniStoreBitmapData
Java_com_example_sounds_1english_JniBitmapHolder_jniGetBitmapFromStoredBitmapData
Java_com_example_sounds_1english_JniBitmapHolder_jniFreeBitmapData
0

наконец я получил решение:

Я изменил название своего пакета на soundsenglish

и изменил мой код cpp на

Java_com_example_soundsenglish_JniBitmapHolder_jniStoreBitmapData
Java_com_example_soundsenglish_JniBitmapHolder_jniGetBitmapFromStoredBitmapData
Java_com_example_soundsenglish_JniBitmapHolder_jniFreeBitmapData

0

JNI не поддерживает пакет с «_»

package com.example.sounds_english

изменить на

package com.example.sounds.english
0
По вопросам рекламы [email protected]