For the protection issue of the shared library I will try to get package name using JNI but it will give errors. So, is it possible to get package name or applicationId using JNI? If anyone have example or references for this problem then suggests. Because not any good tutorial or solution available. Else any other way suggest of the protection of the shared library.
Yes, it's possible. Android is based on Linux, we can obtain a lot of information in user space provided by kernel.
In your example, the information stored here /proc/${process_id}/cmdline
We can read this file, and get the application id.
See a simple example
#include <jni.h>
#include <unistd.h>
#include <android/log.h>
#include <stdio.h>
#define TAG "YOURAPPTAG"
extern "C"
JNIEXPORT void JNICALL
Java_com_x_y_MyNative_showApplicationId(JNIEnv *env, jclass type) {
pid_t pid = getpid();
__android_log_print(ANDROID_LOG_DEBUG, TAG, "process id %d\n", pid);
char path[64] = { 0 };
sprintf(path, "/proc/%d/cmdline", pid);
FILE *cmdline = fopen(path, "r");
if (cmdline) {
char application_id[64] = { 0 };
fread(application_id, sizeof(application_id), 1, cmdline);
__android_log_print(ANDROID_LOG_DEBUG, TAG, "application id %s\n", application_id);
fclose(cmdline);
}
}
This works for me:
static jstring get_package_name(
JNIEnv *env,
jobject jActivity
) {
jclass jActivity_class = env->GetObjectClass(jActivity);
jmethodID jMethod_id_pn = env->GetMethodID(
jActivity_class,
"getPackageName",
"()Ljava/lang/String;");
jstring package_name = (jstring) env->CallObjectMethod(
jActivity,
jMethod_id_pn);
return package_name;
}
Related
I'm trying to integrate OpenCV in Android Java native interface using C++ language. I have placed the OpenCV inside the jni folder, where I'm writing my C++ code. I have included the Opencv header files in my HelloNative.c file. But I'm still getting this error while trying to access Mat object.
"Can't resolve variable Mat".
I have tried using namespace cv, but it gives an error to predeclare using and namespace; which is not a solution. I'm posting my code below, please somebody have a look at it and let me know what I'm doing wrong.
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/log.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <OpenCV/include/opencv2/opencv.hpp>
#include <OpenCV/include/opencv/cv.h>
#include <OpenCV/modules/core/include/opencv2/core.hpp>
#include <OpenCV/modules/core/include/opencv2/core/core_c.h>
#include <OpenCV/modules/core/include/opencv2/core/mat.hpp>
#include <OpenCV/modules/imgproc/include/opencv2/imgproc/imgproc.hpp>
#include <OpenCV/modules/imgproc/include/opencv2/imgproc/imgproc_c.h>
#include <OpenCV/modules/legacy/include/opencv2/legacy/legacy.hpp>
#include <OpenCV/modules/videostab/include/opencv2/videostab/motion_stabilizing.hpp>
#include <OpenCV/modules/videostab/include/opencv2/videostab/global_motion.hpp>
JNIEXPORT jint JNICALL
Java_com_example_soimporttest_MainActivity_getStringFromJNI(JNIEnv *env, jobject thisObj,
jstring imagepath) {
const char *jnamestr = (*env)->GetStringUTFChars(env, imagepath, 0);
int width, height, gray;
FILE *fp = fopen(jnamestr, "rb");
if (fp) {
//Read .pgm file
int scan = fscanf(fp, "P5%d%d%d", &width, &height, &gray);
if (scan != 3 || &gray > 256 || &width > 0xfffff || &height > 0xfffff || &gray <= 1 ||
&width < 32 || &height < 32) {
fclose(fp);
return 9;
} else {
return 0;
}
} else {
return -1;
}
}
JNIEXPORT void JNICALL
Java_com_example_soimporttest_MainActivity_displayImage(JNIEnv *env, jobject thisObj, jclass type, jlong inpAddr, jlong outAddr) {
::Mat &src = *(Mat*)inpAddr;
Mat &dst = *(Mat*)outAddr;
applyFilter(src , dst);
}
There are two functions in this file, the first function getStringFromJNI is working perfectly fine.
Thank you.
After a lot of research, I finally managed to find out a good solution for my question. Please follow below mentioned tutorial:
https://github.com/leadrien/opencv_native_androidstudio
You'll be facing some issues while integrating it. You can post those solutions in the comments and I will guide you through each.
Thanks.
I'm trying to return a string from native. For that I'm using the following code.
Native:
#include <string.h>
#include <jni.h>
jstring Java_com_test_Demo_getString(JNIEnv *env, jobject javaThis) {
return (*env)->NewStringUTF(env, "hello");
}
Java:
private native String getString(); //in com.test.Demo
After this I'm generating .so files using ndk-build and including them in jniLibs.
However, the string returned is null. Any ideas on what is wrong ?
I use this snippet code to turn log on or off
#define DEBUG 1
#if DEBUG
#include <android/log.h>
#define LOG_TAG "native_log"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#else
# define LOGD(...) do {} while (0) // do nothing
#endif
// use it
LOGD("%s : %d","value", val);
It worked fine by turn DEBUG flag on/off. The problem is I want to do it at run time in java side. What I want like this:
// java
private native void nativeSetDebug(boolean flag);
// jni
JNIEXPORT void JNICALL Java_com_my_package_Native_nativeSetDebug(JNIEnv *env, jobject thiz, jboolean flag){
// what should I do in this method?
}
Since the macros in c++ are replaced by the preprocessor by their value before source file even compiles, so I'm looking for another approach. Is there any ideas?
macro file
extern bool useDebug;
#include <android/log.h>
#define LOG_TAG "native_log"
#define LOGD(...) if(useDebug){__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)}
C file
bool useDebug = true;
JNIEXPORT void JNICALL Java_com_my_package_Native_nativeSetDebug(JNIEnv *env, jobject thiz, jboolean flag){
useDebug = flag;
}
The extern is important, otherwise each file including the header will define its own variable and they won't be set correctly.
I have this JNI code that uses C++.
#include <eigenfaces_jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/contrib/contrib.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
using namespace cv;
JNIEXPORT jstring JNICALL Java_com_example_facedetector_FaceTracker_nativeCreateObject
(JNIEnv *env, jclass, jstring JFileDir){
// These vectors hold the images and corresponding labels.
vector<Mat> images;
const char *str = env->GetStringUTFChars(jFileDir, NULL);
const char *buf;
/*Releasing the Java String once you have got the C string
is very important!!!*/
env->ReleaseStringUTFChars(jFileDir, str);
Mat im = imread(jFileDir);
if (im.empty())
{
cout << "Cannot load image!" << endl;
buf = "Can load image";
}
else{
buf = "Cannot load image";
}
return env->NewStringUTF("Hello");
}
However, there is always an error at
const char *str = env->GetStringUTFChars(jFileDir, NULL);
which states that
- Symbol 'jFileDir' could not be resolved
- 'jFileDir' was not declared in this scope
- Invalid arguments ' Candidates are: const char * GetStringUTFChars(_jstring *, unsigned
char *) '
Tried the solution in this link Type 'std::string' could not be resolved.
Still not working. Any help to solve this problem would be appreciated. Thank you.
You've declared a function parameter called JFileDir, but nothing called jFileDir. C++ is case-sensitive.
Well, since I don't have enough reputation points to commend, I have to write this as an answer. Check your function parameter list (JNIEnv *env, jclass, jstring JFileDir), what is jclass about, I feel something is missing here.
I did an Opencv's application en windows and now I am using JNI to convert this code to Android but I am having some problems.
In concrete my native code not do nothing.
This is my Java class where I define my native methods:
package com.example.telo3;
import org.opencv.core.Mat;
public class Process {
static {
System.loadLibrary("nativo");
}
public Process(){
dir=inicializar_nativo();
}
public void Procesar(Mat framedetect, Mat framedraw){
procesar_nativo(dir,framedetect.getNativeObjAddr(),framedraw.getNativeObjAddr());
}
private long dir;
private static native long inicializar_nativo();
private static native void procesar_nativo(long thiz, long framedetect, long framedraw);
}
This is my JNI code:
#include "nativo.h"
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/video/tracking.hpp"
#include <iostream>
#include <stdio.h>
#include "FaceDetector.h"
#include "Draw.h"
#include "Almacena.h"
#include "Runnable.h"
using namespace std;
using namespace cv;
#include <android/log.h>
#define LOG_TAG "NATIVO"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
struct variables {
Almacena almacena;
Draw draw;
FaceDetector face_detector;
};
JNIEXPORT jlong JNICALL Java_com_example_telo3_Process_inicializar_1nativo(
JNIEnv *, jobject) {
long dir = (long) new variables();
return (dir);
}
JNIEXPORT void JNICALL Java_com_example_telo3_Process_procesar_1nativo(JNIEnv *,
jobject, jlong dir, jlong framedetect, jlong framedraw) {
Mat* telo =(Mat*)framedetect;
Mat* telo2= (Mat*)framedraw;
((variables*)dir)->almacena = ((variables*)dir)->face_detector.Detect(*telo);
//almacena = face_detector.Detect(frame_gray);
((variables*)dir)->draw.Dibujar(*telo2,((variables*)dir)->almacena);
//frame_capturado = draw.Dibujar(frame_capturado, almacena);
if( (((variables*)dir)->almacena.get_faces()).size() ==0){
LOGD("no detecto caras");
}
}
I think that I use the Jni correctly but the function Detect not works correctly because when I uses this if return 0.
Is framedetect 0? I made a test app based on this and it worked fine (that is, the jlong was converted to and from just fine, so that shouldn't be the issue).
Try catching the error with ndk-gdb to better understand the problem. Attaching it to the process might a problem though if it crashes straight away, in that case I like to put breakpoint on the java side before the crash, make the execution pause there using the debugger, attach ndk-gdb and continue let the java process continue.
Also I recommend using reinterpret_cast<jlong> and reinterpret_cast<variables*> instead of the C style casts, and save that cast to a separate variable to avoid casting all the time! cleaner code!