I have never worked on ndk . But I have got a project in which ndk is used.
it's giving me java.lang.UnsatisfiedLinkError: Native method not found:
I tried to search on Google. I got many link
But all are related to jni.cpp
file
But my error is in java file. So i am not able to find how to correct it.
"java.lang.UnsatisfiedLinkError: Native method not found: il.co.telavivapp2u.onceapponatime.SharedResources.ocvBitmapPreMultAlpha:(Landroid/graphics/Bitmap;Landroid/graphics/Bitmap;)
I integrated NDK following this link. This project is done by another developer We are adding some more features in it. This part is done by previous dev.
I just added Google Search API Activity And Gallery image Activity which will show images on grid. previous dev has put some number of images in drawable folder and showing it into gallery view. it's running perfectly whatever he done at his end. even now also. But what I have added in that the same thing is not happening
After clicking an image on app drawable gallery view , it'll go to a camera activity which will capture image with the selected image as a background. and then we can make edit and save that image. But in case of mobile gallery and Google search images after capturing the app goes ANR.
I have set NDK path and variable to eclipse also I installed c c++ plugins
Also console is showing
Cannot run program "\ndk-build.cmd": Launching failed .
I am not able to understand where I am making mistake. Please help me.
JNI FILE
The ANR happens at line number 207.
Here is my code:
package il.co.telavivapp2u.onceapponatime;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
public class SharedResources {
public static Bitmap bmpOld = null;
public static Bitmap bmpOldScaled = null;
public static Bitmap bmpNew = null;
public static Bitmap bmpNewScaled = null;
public static int scaledX = 0, scaledY = 0;
public static int dispX = 0, dispY = 0;
public static int fullX = 0, fullY = 0;
public static int picX = 0, picY = 0;
public static String fileDir = "/OnceAppOnATime/";
public static String fileTempDir = fileDir + "/.temp/";
public static String fileTempNew = fileTempDir + "/temp-new.jpg";
public static String fileTempOld = fileTempDir + "/temp-old.jpg";
public static String fileTempMask = fileTempDir + "/temp-mask.jpg";
public static String fileTempBlend = fileTempDir + "/temp-blend.jpg";
public static String fileTempRetouch = fileTempDir + "/temp-retouch.jpg";
//public static String fileLastBlend = "";
public static BitmapFactory.Options op = new BitmapFactory.Options();
public static Locale localeHebrew = null;
public static int taskID = -1;
public static boolean Init(Activity activity) { return Init(activity, false); }
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static boolean Init(Activity activity, boolean force) {
if (dispX > 0 && dispY > 0) { // Don't re-init to avoid wrong file names
if (!force)
return false;
} else {
fileDir = Environment.getExternalStorageDirectory() + fileDir;
fileTempDir = Environment.getExternalStorageDirectory() + fileTempDir;
fileTempNew = Environment.getExternalStorageDirectory() + fileTempNew;
fileTempOld = Environment.getExternalStorageDirectory() + fileTempOld;
fileTempMask = Environment.getExternalStorageDirectory() + fileTempMask;
fileTempBlend = Environment.getExternalStorageDirectory() + fileTempBlend;
fileTempRetouch = Environment.getExternalStorageDirectory() + fileTempRetouch;
}
taskID = activity.getTaskId();
// Find Hebrew locale, if available
Locale availableLocales[] = Locale.getAvailableLocales();
for (int i = 0; i < availableLocales.length; ++i) {
String lang = availableLocales[i].getLanguage();
if (lang.equals("he") || lang.equals("iw")) {
localeHebrew = availableLocales[i];
break;
}
}
op.inPreferredConfig = Bitmap.Config.ARGB_8888;
//op.inScaled = false; // Not needed if loading bitmaps from drawable-nodpi
op.inMutable = true;
Display display = activity.getWindowManager().getDefaultDisplay();
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
dispX = display.getWidth();
dispY = display.getHeight();
} else {
Point dispSize = new Point();
display.getSize(dispSize);
dispX = dispSize.x;
dispY = dispSize.y;
}
Log.w("Display Size", dispX + "x" + dispY);
//scaledX = dispX / 2; scaledY = dispY / 2;
scaledX = dispX; scaledY = dispY;
return true;
}
public static void setLocale(Activity activity, Locale locale) {
// This doesn't work reliably
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
activity.getBaseContext().getResources().updateConfiguration(config,
activity.getBaseContext().getResources().getDisplayMetrics());
}
public static boolean haveScaling() {
return (dispX != scaledX || dispY != scaledY);
}
public static void SaveTempBitmap(Bitmap bitmap, String filename) {
try {
new File(fileTempDir).mkdirs();
FileOutputStream out = new FileOutputStream(filename);
bitmap.compress(Bitmap.CompressFormat.JPEG, 98, out);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void RecycleOldBitmaps(boolean full, boolean scaled) {
if (full && bmpOld != null) {
bmpOld.recycle();
bmpOld = null;
}
if (scaled && bmpOldScaled != null) {
bmpOldScaled.recycle();
bmpOldScaled = null;
}
}
public static void RecycleNewBitmaps(boolean full, boolean scaled) {
if (full && bmpNew != null) {
bmpNew.recycle();
bmpNew = null;
}
if (scaled && bmpNewScaled != null) {
bmpNewScaled.recycle();
bmpNewScaled = null;
}
}
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public static int sample2sample[] = new int[] {1, 1, 2, 2, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32};
public static Bitmap LoadScaledBitmap(Context ctx, int resId, float fracX, float fracY) {
// See: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(ctx.getResources(), resId, opts);
int imageHeight = opts.outHeight;
int imageWidth = opts.outWidth;
float requestX = dispX * fracX, requestY = dispY * fracY;
opts.inSampleSize = (int)(Math.min(imageWidth / requestX, imageHeight / requestY));
if (opts.inSampleSize < 0 || opts.inSampleSize > 32) // Sometimes index=2147483647 for some reason...
opts.inSampleSize = 1;
opts.inSampleSize = sample2sample[opts.inSampleSize];
Log.w("Bitmap Decoder", "Samples: " + opts.inSampleSize);
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
//opts.inScaled = false; // Not needed if loading bitmaps from drawable-nodpi
opts.inMutable = true;
opts.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(ctx.getResources(), resId, opts);
}
public static Bitmap LoadScaledBitmap(String filename, float fracX, float fracY) {
// See: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filename, opts);
int imageHeight = opts.outHeight;
int imageWidth = opts.outWidth;
float requestX = dispX * fracX, requestY = dispY * fracY;
opts.inSampleSize = (int)(Math.min(imageWidth / requestX, imageHeight / requestY));
if (opts.inSampleSize < 0 || opts.inSampleSize > 32) // Sometimes index=2147483647 for some reason...
opts.inSampleSize = 1;
opts.inSampleSize = sample2sample[opts.inSampleSize];
Log.w("Bitmap Decoder", "Samples: " + opts.inSampleSize);
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
//opts.inScaled = false; // Not needed if loading bitmaps from drawable-nodpi
opts.inMutable = true;
opts.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filename, opts);
}
public static String FileNameNow() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.ENGLISH);
return fileDir + sdf.format(new Date()) + ".jpg";
}
public static native void ocvBitmapPyramidalBlend(String fNew, String fOld, String fMask, String fBlend, int levels);
public static String ocvBitmapPyramidalBlendTimed(int levels) {
String fBlend = fileTempBlend;//FileNameNow();
long t = System.nanoTime();
ocvBitmapPyramidalBlend(fileTempNew, fileTempOld, fileTempMask, fBlend, levels);
long dt = (System.nanoTime() - t) / 1000; // Microseconds
Log.w("OpenCV", "Blended (pyramidal) bitmaps in " + (dt / 1000.0f) + " ms");
//fileLastBlend = fBlend;
return fBlend;
}
public static native void ocvBitmapPreMultAlpha(Bitmap bitmapImg, Bitmap bitmapMask);
public static void ocvBitmapPreMultAlphaTimed(Bitmap bitmapImg, Bitmap bitmapMask) {
long t = System.nanoTime();
ocvBitmapPreMultAlpha(bitmapImg, bitmapMask);
long dt = (System.nanoTime() - t) / 1000; // Microseconds
Log.i("Native", "Applied premultiplied alpha to bitmap in " + (dt / 1000.0f) + " ms");
}
public static native void ocvBitmapContrastSaturationSet(Bitmap bitmapImg);
public static void ocvBitmapContrastSaturationSetTimed(Bitmap bitmapImg) {
long t = System.nanoTime();
ocvBitmapContrastSaturationSet(bitmapImg);
long dt = (System.nanoTime() - t) / 1000; // Microseconds
Log.i("Native", "Assigned contrast/saturation bitmap in " + (dt / 1000.0f) + " ms");
}
public static native void ocvBitmapContrastSaturationSrc(Bitmap bitmapImg, Bitmap bitmapSrc, float contrast, float saturation);
public static void ocvBitmapContrastSaturationSrcTimed(Bitmap bitmapImg, Bitmap bitmapSrc, float contrast, float saturation) {
long t = System.nanoTime();
ocvBitmapContrastSaturationSrc(bitmapImg, bitmapSrc, contrast, saturation);
long dt = (System.nanoTime() - t) / 1000; // Microseconds
Log.i("Native", "Applied contrast/saturation (from src) to bitmap in " + (dt / 1000.0f) + " ms");
}
public static native void ocvBitmapContrastSaturation(Bitmap bitmapImg, float contrast, float saturation);
public static void ocvBitmapContrastSaturationTimed(Bitmap bitmapImg, float contrast, float saturation) {
long t = System.nanoTime();
ocvBitmapContrastSaturation(bitmapImg, contrast, saturation);
long dt = (System.nanoTime() - t) / 1000; // Microseconds
Log.i("Native", "Applied contrast/saturation to bitmap in " + (dt / 1000.0f) + " ms");
}
}
Also right click on project - >Android Tools -> Add Native Support
Add Native Support is missing. I have Android Native Development Tools installed. Then also it's missing.
UnsatisfiedLinked error is due to broken bridge between java class and c class; The name of the method in java should match to the method in C/c++ class. While compiling bridge is created between Java and c/c++ so if method name is not correct it wont response. example is following method name injava is following
public native String Stub(){}
that should be same in JNI but with your Application packagename+classname+methodname like following
JNIEXPORT jstring JNICALL Java_com_packageName_ClassName_MethodName
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With