C++ on android, how to get app's document directory? - android

I'm integrating a native c++ library (sqlite3) into android, in order to save the database file I need a path to put it somewhere, on iOS I used this code to get the documents directory:
char *home = getenv("HOME");
However this environment variable not available on Android, is there anyway to get the applications documents path from the c++ or is it necessary to always get it from some higher java call?
Thanks a lot for the help!
Edit
After looking around, I found this small snippet that I already had in my codebase:
SequelModule.initialize(
this.getReactApplicationContext().getJavaScriptContextHolder().get(),
this.getReactApplicationContext().getFilesDir().getAbsolutePath()
);
which is being passed to my cpp-adapter.cpp, how do I convert the second value (the absolute path) JNI/Java string into a C++ std::string?
#include <jni.h>
#include "react-native-sequel.h"
extern "C"
JNIEXPORT void JNICALL
Java_com_reactnativesequel_SequelModule_initialize(JNIEnv* env, jclass clazz, jlong jsiPtr) {
installSequel(*reinterpret_cast<facebook::jsi::Runtime*>(jsiPtr));
}
extern "C"
JNIEXPORT void JNICALL
Java_com_reactnativesequel_SequelModule_destruct(JNIEnv* env, jclass clazz) {
cleanUpSequel();
}

Related

Failed to read files in NDK C++ using fstream and ifstream

I am trying to load a file in NDK using ifstream but it fails to read it. I've double checked the path of the file and it is not wrong. The same program works in normal C++(without the JNI stuff ofcourse).
#include <jni.h>
#include <string>
#include <iostream>
#include <istream>
#include <sstream>
#include <fstream>
using namespace std;
extern "C"
{
JNIEXPORT jstring JNICALL Java_com_example_aaaaatrytest_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */) {
string file_path = "/home/moe/Desktop/blah.txt";
std::ifstream fim(file_path);
if(fim.is_open())
{
string pass = "File Loaded";
return env->NewStringUTF(pass.c_str());
}
else{
std::string fail = "Failed to load file";
return env->NewStringUTF(fail.c_str());
}
}
}
After removing if-else and debugging, this is what debugger displays:
SIGTRAP (signal SIGTRAP)
env = {JNIEnv * | 0x55bc7ccc00} 0x00000055bc7ccc00
{jobject | 0x7fcefb1af4} 0x0000007fcefb1af4
I have tried to use fstream instead of ifstream but same error. I've also provided external storage write and read permission in manifest.xml but it didn't help.
This problem is format independent as I've tried to put different files in the path. Why is it failing to read the file?
l have copied the file to my device and gave android path but it still fails to read. My android's path to file looks like this "/storage/emulated/0/abc/abc.txt".
Your app needs READ_EXTERNAL_STORAGE permission.
Here is a small snippet that helps to request this permission at runtime: see READ_EXTERNAL_STORAGE permission is in manifest but still doesn't work.

NDK unable to deal with #include with relative paths?

I'm writing an Adroid app with some C++ code behind the UI using Eclipse + NDK (r8d). I have some code that I thought was fool proof but the compiler just gives me weird errors like "Invalid arguments" without specifics. Here is what my C++ code looks like:
#include <jni.h>
#include <string>
using namespace std;
#include "../../Evaluator.Engine/Evaluator.Engine.h"
Evaluator evaluator;
extern "C" {
JNIEXPORT jstring JNICALL Java_haskellevaluator_android_MainActivity_evaluateNative(JNIEnv *env, jobject, jstring jInput)
{
...
string sInput(L"Hello world");
string sResult = evaluator.evaluate(sInput);
jstring jResult = env->NewStringUTF(sResult.data());
return jResult;
}
}
Evaluator.Engine.h is nothing fancy, but just a declaration of the class Evaluator.
#include <string>
using namespace std;
class Evaluator
{
public:
string evaluate(string input);
};
However, the compiler complains:
Invalid arguments '
Candidates are:
? evaluate(?)
'
as if string is not defined. But if I put a copy of the header file under the same folder, the error goes away. This is a Windows box. I have tried using \ and escaped \\ as path separators and it didn't work.
Does this sound like a NDK (or whatever the preprocessor it uses) bug? I don't want to move the header file because it'll be shared by other projects. I also hate to keep 2 copies of the same file.
Any ideas? Thanks.
Sorry I don't have windows OS, but I've tried you code on a MacOS, but it doesn't work because of:
string sInput(L"Hello world");
Saying that wchar_t cannot be put on std::string. Is it possible to be the same problem ?

include .h file into java file in android using jni as source folder of .h file?

void ProcedureParams_Initialize(ProcedureParams* pVal);
flag ProcedureParams_IsConstraintValid(const ProcedureParams* val, int* pErrCode);
flag ProcedureParams_XER_Encode(const ProcedureParams* val, ByteStream* pByteStrm, int* pErrCode, flag bCheckConstraints);
flag ProcedureParams_XER_Decode(ProcedureParams* pVal, ByteStream* pByteStrm, int* pErrCode);
flag ProcedureParams_BER_Encode(const ProcedureParams* val, ByteStream* pByteStrm, int* pErrCode, flag bCheckConstraints);
flag ProcedureParams_BER_Decode(ProcedureParams* pVal, ByteStream* pByteStrm, int* pErrCode);
typedef struct {
GeneralEvthParams g_params;
DataParams d_params;
} EvtHandlerParams;
how i can add .h file directly into my .java file. i'm using NDk and .h file inside my jni folder.i want to use the functions of header file . how i can directly use functions in java activity? please help me
You cannot invoke the C/C++ functions directly. The C implementations of Java native functions all have a very specific set of parameters:
JNIEXPORT jint JNICALL Java_com_mycompany_MyClassName_myfunc
(JNIEnv * env, jobject obj, jint code) {
...
}
So you will have to create wrapper functions.
A reasonable approach is to define a class including the Java versions of all your native functions (as either static or instance methods), and invoke them via that class.
To generate C headers from the Java (well, not source but the .class files), you can do:
cd bin/classes
javah com.mycompany.MyClassName com.mycompany.AnotherClassName

how to call javah from ADT ide

Took the basic example from NDK.
Added a function, which doesn't exist yet at native side.
Now I am looking a way to call javah from ADT IDE and expect to be generated the function header to my file, near the others:
extern "C" {
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj);
}
;
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height) {
setupGraphics(width, height);
}
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj) {
renderFrame();
}
at least to extern "C" section.
Is there any way to do it? What is the best practice?
generate with a tool to gl2jni.cpp than Cut and Paste to gl_code.cpp, to keep the existing code in gl_code.cpp ? - or do I miss a basic environment setup?
Do I need to write some build configuration? - like always generate those headers to an empty file?
Is there any plugin which can do it from IDE?
Since you are using the Eclipse IDE, running javah can be easily automated to put header files anywhere you want them whenever your Java code is compiled. See my answer on SO here.

Identify Calling Application in Android NDK

I have a native android library (.so) I am bundling with some application. In the native code I want to verify the signer/package name of the calling application.
The reason is, currently anyone can open up the .apk file take my .so file and use it to built their own applications.
Is there a way to securely identify the calling application from Java side? This could be package name, signature or anything else that can identify the Android application in a unique way.
JNI code is coupled with Java package name, and can be called only from the same package and class. To improve security further, you can check some Java private static final field from the JNI code.
In the native code I want to verify the signer/package name of the
calling application.
how about this?
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring JNICALL
Java_com_x_y_TestActivity_stringFromJNI(JNIEnv *env, jobject thiz)
{
jclass jActivity_class = env->GetObjectClass(thiz);
jmethodID jMethod_id_pn = env->GetMethodID(jActivity_class,"getPackageName","()Ljava/lang/String;");
jstring package_name = (jstring) env->CallObjectMethod(thiz,jMethod_id_pn);
return package_name;
}

Categories

Resources