2016-03-22 21 views
2

temel mesele almak için içerik (bu) gerektiren JNI gelen yöntem, ama karmaşık kodu gerekir:çağrılması Java hesap adı

Ben esas Android NDK kullanarak Android cihazda kullanılan hesap adı almak istiyorum. Yerel amaçlar için güvenlik amacıyla olabildiğince çok yapılmalıdır. Android'in kaynak kodlarında * 1'de (aşağıya bakın) önerilen çağrıları analiz ederken, ham veritabanı dosyasına erişmenin mümkün olmadığını ve muhtemelen eksik izinler nedeniyle hesap adını okuyabildiğini gördük.

Bundan sonraki yaklaşımım, * 1 kodunu (aşağıya bakınız) kullanmak ve src klasöründeki ayrılmış bir "java" sınıfına yerleştirmekti. Maalesef, etkinlik bağlamını gerektiriyor ve yerel kodda nasıl isteneceğine dair bir fikrim yok, çünkü ana aktiviteyi içermeden her şey yerel koddan yapılmalıdır. JNI çağrısının 2. parametre tezi olabileceğini sanıyorum, ama bu konuda çok emin değilim.

Geçerli yerel kodumda * 2 var ve buna benziyor, ancak şu ana kadar çalışmıyor. Herhangi bir ipucunuz veya daha iyi çözümleriniz var mı? AccountManager'ı doğrudan yerel koddan arayabilir miyim?

// 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); 
[...] 

İşte Java sınıfı

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


    } 

cevapta 1. Yorum yapmak: Tabii, yerel kod bir yere başlangıçta çağrılacak vardır. Test amaçlı olarak, bu aramayı ana etkinliğimin onCreate() yöntemine yerleştirdim. 2 yoruma cevap olarak

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() yöntemini tanımlarken, yerli kütüphane yüklemek için sadece basit bir sınıftır.

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

+0

_ "JNI çağrısının 2. parametresi olabileceğini varsayalım" _ 'thiz ', getMyString öğesinin çalıştırıldığı Java nesnesine yapılan bir başvurudır. Bize bu kodu göstermediniz, bu yüzden geçerli bir 'İçerik 'olup olmadığını gerçekten söyleyemeyiz. – Michael

+0

yukarıdan bakın; JNI çağrısının şu an ana aktiviteden alındığı test amaçlı. – Nils

+1

Ancak, "MainActivity" örneğinde _on_ çağrılmıyor.Kodunuza göre, ne olursa olsun, MyNDK'nin bir örneğinde çağrılır. – Michael

cevap

1

Eh, ipuçları için teşekkürler. Çözdüm. Yani burada çözüm:

yapıcı < init> adı olarak

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

Ayrıca Michael'ın tavsiye aldı ve sadece bir java parametre ve C fonksiyonunu karşılık gelen bağlam ilave gerektirir. thiz2 bizim istediğimiz bağlamdır, oysa yukarıda zikredilen Michael gibi MyNDK örneğidir.

public native String getMyString(Context c); 


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

Peki, ne kaldı? Hesap adı iade edilmedi, ancak test amacıyla sabit bir dönüş dizesi kullandım. Bu gerçek JNI sorununu çözdü ve uygulama iyi çalışır, ancak hesap adını almak için java uygulamasında hala bir hata olması gerekir.

Neyse. Yeterince çözüldü. Herkese teşekkürler.