I want to create a file in my device by using JNI program.and i created a file in the location of data/local/hello.txt by using the code
JNIEXPORT jint JNICALL
Java_com_maacrofuzzyn_acsianiac_samplelibrary_MainActivity_Register(
JNIEnv *env,
jobject ob) {
int i = 0;
FILE* file = fopen("/data/local/hello.txt","w+");
if (file != NULL)
{
fputs("HELLO WORLD!\n", file);
fflush(file);
fclose(file);
}
but, i cant create a file in the location tmp/hello.txt by using the same code. i think this is something permission problem. how can i solve this problem and create a file in that location... please help me.
Related
#include <jni.h>
#include <string>
#include <opencv2/opencv.hpp>
using namespace cv;
#include <iostream>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cppinandroid_MainActivity_stringFromJNI( JNIEnv* env,
jobject)
{
Mat image;
image = imread( "/home/<name>/a.png", 1 );
if ( !image.data )
{
return env->NewStringUTF( "No data in image!" );
} else
{
return env->NewStringUTF( "Data is in image" );
}
}
That's what I have in Native Cpp part of the android project.
When I run the application with emulator, it always shows: "No data in image!" text.
I have compiled this program separately as a normal c++ opencv program. It is working perfectly fine.
I have given the absolute path too. Is that not enough?
Do I have to write something in build.gradle also?
I am using Android studio, if that matters.
Android directories do not match Linux at all.
A good solution is to find your file through Java and pass the path to the file as a parameter to function Java_com_example_cppinandroid_MainActivity_stringFromJNI.
If your file is in public files, you can try "/sdcard/a.png" - but the path may vary between different android shells.
The possible solution from reading from public files:
Java:
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator + fileName);
if (f.exists()) {
foo(f.getAbsolutePath());
NDK:
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cppinandroid_MainActivity_stringFromJNI(JNIEnv* env,
jobject, jstring javaPath)
{
const char* path = env->GetStringUTFChars(javaPath, 0);
Mat image;
image = imread( path, 1 );
env->ReleaseStringUTFChars(javaPath, path );
if ( !image.data )
{
return env->NewStringUTF( "No data in image!" );
} else
{
return env->NewStringUTF( "Data is in image" );
}
}
A better way to store a picture in assets and read AAssetManager like Android read text file from asset folder using C (ndk) or How to properly pass an asset FileDescriptor to FFmpeg using JNI in Android.
I am going to load an image by provided file_path and then downsample it then save it. The whole thing should be done on android device.
I am in trouble to load an image on device and convert to halide::buffer.
Halide::Tools::load_image didn't work on android if I use it like
JNIEXPORT bool JNICALL Java_com_example_boxdownsample_MainActivity_downsample(
JNIEnv *env, jobject obj, jstring file_path) { ...
const char *path = env->GetStringUTFChars(file_path, NULL);
std::string work_path = path;
LOGD("the path is:%s", path);
std::string input_file = work_path + "input.png";
std::string output_file = work_path + "output.png";
Halide::Buffer<uint16_t> input = Halide::Tools::load_image(input_file);//load_image didn't work ....
int ret = box_downsample_halide(input, downsample_factor, output_u16); //box_downsample_halide is a static lib generated by halide generator
... } }
So, am I use it wrong? or
I should load it use java(that would be bitmap format) then encode it to halide::buffer, but this seems a bit hard and indirect.
Is there any easier way to do it?
Thanks!
UPDATE:
I found a way, in case who also need this, please go to my github
This simple program to write into a file is running fine in my emulator as I am getting a text file generated inside the sdcard(text file has HELLO WORLD in it) along with the given message on emulator screen.
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
FILE* file = fopen("/sdcard/hello.txt","w+");
if (file != NULL)
{
fputs("HELLO WORLD!\n", file);
fflush(file);
fclose(file);
}
return (*env)->NewStringUTF(env, "Hello from JNI (with file io)!");
}
But when I try to read the file using this program I am facing problems. It outputs nothing on the emulator screen or on logcat. As seen from the above program there definitely is no problem with the location of sdcard or with using FILE operations. How to fix it?
JNIEXPORT jstring JNICALL Java_com_example_myproject_MainActivity_doSomething( JNIEnv* env, jobject thiz)
{
// Counts the characters inside file
char ch;
int cnt= 0;
FILE* fptr = fopen("/sdcard/hello.txt","r");
while((ch=fgetc(fptr))!=EOF)
cnt++;
fclose(fptr);
LOGE("cnt: %d",cnt);
return (*env)->NewStringUTF(env, "Hello from JNI (with file io)!");
}
Thanks
EDIT:
This above code to read file works well in linux gcc but has errors working in Android. Changing it as mentioned by Andrew solves it.
fgetc() returns int, not char, so this loop never terminates:
while((ch=fgetc(fptr))!=EOF)
cnt++;
because ch can never equal EOF.
I am trying to use openCV in my android project and trying to run this native code but I don't know how to use this parameter
JNIEXPORT jint JNICALL Java_com_example_helloopencvactivity_nativecalls_filepath
(JNIEnv * env, jobject jo, jstring str1, jstring str2) {
cv::Mat img1 = cv::imread("");
}
I tried using this
const char *nativeString = (*env)->GetStringUTFChars(env, str1, 0);
cv::Mat img1 = cv::imread(nativeString);
but i am getting this error error: no matching function for call to '_JNIEnv::GetStringUTFChars
I need to pass the file path from android file system to openCV's native code for processing, the passing element is string and should be read by imread
first in the java side, my codes looks likeļ¼
private String path="/mnt/sdcard/";
InitFeature(width,height,path);
public native void InitFeature(int width, int height,String path);
then in the jni side, it's:
//passed from the java part and release after InitFreature
const char* nPath;
//to save the globle path
char* g_path;
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial6_Tutorial2Activity_InitFeature(JNIEnv* env, jobject,jint width,jint height,jstring path);
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial6_Tutorial2Activity_InitFeature(JNIEnv* env, jobject,jint width,jint height,jstring path)
{
//jsize path_size;
nPath=env->GetStringUTFChars(path,NULL);
//path_size=env->GetArrayLength(path);
LOGD("path: %s \n",nPath);
int length=strlen(nPath);
LOGD("length: %d \n",length);
g_path=new char[length+1];
memcpy(g_path,nPath,length+1);
LOGD("path_2: %s \n",g_path);
LOGD("length: %d \n",strlen(g_path));
char l_path[128];
strcpy(l_path,g_path);
strcat(l_path,"color.jpg");
LOGD("path_3: %s \n",l_path);
LOGD("length: %d \n",sizeof(l_path));
m_width=width;
m_height=height;
center.x=float (m_width/2.0+0.5);//float (Img_tmp->width/2.0+0.5);
center.y=float (m_width/2.0+0.5);//float (Img_tmp->height/2.0+0.5);
env->ReleaseStringUTFChars(path,nPath);
}
since I have different native calls, one to initiate features(shown here) and others to process every frame, and after you env->ReleaseStringUTFChars(path,nPath); the string would be invisible to jni part. I have the copy the string to a global char* g_path;
and a little sample is here as well, the file path is "/mnt/sdcard/color.jpg" and check those logs.
then you can use imread() to get this jpg.
I use other libs like libjpg, so I am not showing the codes here.
I have a function in c++ and I want to call it it java for android.
I write it and build its library but the problem is I can not find file in emulator.
I use adb push text.txt sdcard to copy text.txt to sdcard of emulator.
but I could not find the file with the C function.
I call Simple("hello");
This is my C file :
jint Java_X_XX_XXX_wipeActivity_Simple(JNIEnv* env, jobject javaThis,jstring jstr)
{
jboolean iscopy;
const char *address = (*env)->GetStringUTFChars(env, jstr, &iscopy);
return replaceZero("/sdcard/text.txt");
//remove(address);
}
jint replaceZero(const char *address)
{
FILE *fp;
fp = fopen(address,"r+");
if(fp == 0)
{
printf("can not find!!");
return -1;
}
else
{
//do sth with file
return 0;
}
}
and I will see -1 in main program.
I found the answer - I needed to add this to manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
I cannot open it without permission.