基本问题,但需要复杂的代码:

我想主要使用Android NDK获取在Android设备上使用的帐户名。为了安全起见,应尽可能在本机代码中完成。在分析Android源代码中* 1(见下文)中建议的调用时,结果表明,可能由于缺少权限而无法访问原始数据库文件,而只能读出帐户名。

因此,我的下一个方法是使用代码* 1(请参见下文),并将其放入src文件夹中单独的Java类“ Account”中。不幸的是,它需要活动上下文,而且我不知道如何在本机代码中请求它,因为所有事情都应该在不包含主要活动的情况下从本机代码完成。我认为这可能是JNI调用的第二个参数,但我对此不太确定。

我当前的本机代码基于* 2,看起来像这样,但是到目前为止还无法正常工作。您有什么提示或更好的解决方案吗?我可以直接从本地代码调用AccountManager吗?

// 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;
        }


    }


回应评论1:当然,最初必须在某个地方调用本机代码。为了进行测试,我将该调用放在了主活动的onCreate()方法中。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MyNDK a = new MyNDK();
        Log.i("MyTag", a.getMyString());


在回应第二条评论时:MyNDK只是一个简单的类,用于在定义getMyString()方法时加载本机库。

public class MyNDK {

    static{
        System.loadLibrary("MyLibrary");
    }
    public native String getMyString();
}


* 1 How can I get the google username on Android?

* 2 http://www.rgagnon.com/javadetails/java-0284.html

最佳答案

好吧,谢谢你的提示。我解决了所以这是解决方案:

构造函数需要作为名称

jmethodID constructorID = env->GetMethodID
        (myclass_class, "<init>", "()V")


此外,我接受了Michael的建议,并在Java和相应的C函数中将上下文作为参数添加了。 thiz2是我们想要的上下文,而thiz是MyNDK的实例,正如上面迈克尔已经提到的那样。

public native String getMyString(Context c);


JNIEXPORT jstring JNICALL Java_com_example_nils_myapplication_MyNDK_getMyString
        (JNIEnv * env, jobject thiz, jobject thiz2) {


好了,还剩下什么?帐户名称未返回,但是出于测试目的,我使用了固定的返回字符串。这样就解决了实际的JNI问题,并且应用程序运行良好,而Java实施中在接收帐户名时仍然必须存在错误。

无论如何。充分解决。感谢大家。

10-08 06:14
查看更多