Android 从JNI调用Java方法需要上下文(this)来接收帐户名
基本问题,但需要复杂的代码: 我想主要使用安卓NDK获取安卓设备上使用的帐户名。为了安全起见,应该尽可能多地使用本机代码。在分析Android源代码中*1(见下文)中建议的调用时,发现由于缺少权限,无法访问原始数据库文件并读取帐户名 因此,我的下一个方法是使用*1的代码(见下文),并将其放入src文件夹中一个单独的java类“Account”中。不幸的是,它需要活动上下文,我不知道如何在本机代码中请求它,因为一切都应该从本机代码中完成,而不包括主活动。我假设它可能是JNI调用的第二个参数thiz,但我对此非常不确定 我当前的本机代码是基于*2的,看起来是这样的,但到目前为止还不起作用。你有什么建议或更好的解决方案吗?我可以直接从本机代码调用AccountManager吗Android 从JNI调用Java方法需要上下文(this)来接收帐户名,android,android-ndk,java-native-interface,accountmanager,Android,Android Ndk,Java Native Interface,Accountmanager,基本问题,但需要复杂的代码: 我想主要使用安卓NDK获取安卓设备上使用的帐户名。为了安全起见,应该尽可能多地使用本机代码。在分析Android源代码中*1(见下文)中建议的调用时,发现由于缺少权限,无法访问原始数据库文件并读取帐户名 因此,我的下一个方法是使用*1的代码(见下文),并将其放入src文件夹中一个单独的java类“Account”中。不幸的是,它需要活动上下文,我不知道如何在本机代码中请求它,因为一切都应该从本机代码中完成,而不包括主活动。我假设它可能是JNI调用的第二个参数thiz
// based on http://www.rgagnon.com/javadetails/java-0284.html
JNIEXPORT jstring JNICALL Java_com_example_nils_myapplication_MyNDK_getMyString(JNIEnv* env, jobject thiz){
const char *str;
jclass myclass_class =(jclass) env->NewGlobalRef
(env->FindClass ("com/example/nils/myapplication/Account"));
jmethodID constructorID = env->GetMethodID
(myclass_class, "", "()V");
jmethodID methodID = env->GetMethodID
(myclass_class, "getUsername", "(Landroid/content/Context;)Ljava/lang/String;");
jobject myclass_object = env->NewObject
(myclass_class, constructorID);
jstring s = (jstring) env->CallObjectMethod
(myclass_object, methodID, thiz);
[...]
这里是Java类
public class Account {
public Account(){
};
// based on https://stackoverflow.com/questions/2727029/how-can-i-get-the-google-username-on-android
public static String getUsername(Context c) {
AccountManager manager = AccountManager.get(c);
android.accounts.Account[] accounts = manager.getAccountsByType("com.google");
LinkedList<String> possibleEmails = new LinkedList<String>();
for (android.accounts.Account account : accounts) {
// TODO: Check possibleEmail against an email regex or treat
// account.name as an email address only for certain account.type values.
possibleEmails.add(account.name);
}
if (!possibleEmails.isEmpty() && possibleEmails.get(0) != null) {
String email = possibleEmails.get(0);
String[] parts = email.split("@");
if (parts.length > 1)
return parts[0];
}
return null;
}
}
作为对第二条评论的回复:MyNDK只是一个加载本机库的简单类,同时定义getMyString()方法
*一,
*好的,谢谢你的提示。我解决了。因此,解决方案如下: 构造函数需要
jmethodID constructorID = env->GetMethodID
(myclass_class, "<init>", "()V")
还有什么?不会返回帐户名,但出于测试目的,我使用了一个固定的返回字符串。这解决了实际的JNI问题,应用程序运行正常,但java实现中接收帐户名时肯定仍然存在错误
无论如何。充分解决。谢谢大家。“我想它可能是JNI调用的第二个参数thiz”
thiz
是对调用了getMyString
的Java对象的引用。您还没有向我们展示该代码,因此我们无法确定这是否是有效的上下文;出于测试目的,JNI调用现在从主活动中调用。但它不会在MainActivity
的实例上调用。根据您的代码,它是在MyNDK
的实例上调用的,不管是什么。我现在也添加了MyNDK类。因此,问题在于如何在本机代码中获取上下文,或者当前thiz是否正确……thiz
是一个MyNDK
实例,而不是上下文。显而易见的解决方案是使用公共本机字符串getMyString(Context)代码>(并相应地更改C++函数),并用“代码> .GETMyStand(this)调用它;<代码>来自您的活动。
public class MyNDK {
static{
System.loadLibrary("MyLibrary");
}
public native String getMyString();
}
jmethodID constructorID = env->GetMethodID
(myclass_class, "<init>", "()V")
public native String getMyString(Context c);
JNIEXPORT jstring JNICALL Java_com_example_nils_myapplication_MyNDK_getMyString
(JNIEnv * env, jobject thiz, jobject thiz2) {