[SOLVED] Fetching the sim card's phone number on Android



  • I've been developing an app using QTCreator, but I've got to a point where I need to determine the phone number of the device the app is running on. Is there a straightforward way of doing this in Qt 5.1? Do I need to call a function in the Android SDK to do it? Thanks for any help!



  • I don't know any straightforward way to get phone number thorugh Qt on Android... you need to do it throught JNI I think....



  • I was afraid of that! Oh well, time to work out how to call java java functions, I guess. Thanks! :)



  • Calling java functions seems to be a difficult proposition. I have found a dozen different pages on doing this in Qt and they all seem to be missing a detail or for older versions of Qt with differently laid-out applications.

    I have created a PNumber.java file to test this in the android\src\org\kde\necessitas\ministro directory of my project, and added it in Qt Creator under Other files - src/org - kde/necessitas/ministro but when I call FindClass, I get an exception saying it couldn't find the class. My FindClass call looks like this:

    @jclass native_object= jnienv->FindClass("org/kde/necessitas/ministro/PNumber");@

    And my java file looks like this:
    @public class PNumber {
    String number="1234567890";
    public String getPhoneNumber() {
    return number;
    }
    }@

    Is that the correct placement of the .java file? Do I need to do anything else to ensure Qt includes the class when it builds the apk for deployment to Android?



  • Ahh, I was missing a line at the top declaring the package. Never mind!

    I will post a solution in this thread when I get the problem sorted.



  • Hmm, still struggling with this. It seems like googling for information on android related development using Qt will often turn up results which are irrelevant to the problem, or which are out of date, but here's the problem where I have it now. I have a java class:

    public class PNumber extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Log.i("PNumber","onCreate");
    }
    public String getPhoneNumber() {
      Log.i("PNumber","getPhoneNumber");
       TelephonyManager telephonyManager;
       telephonyManager=(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
       return telephonyManager.getDeviceId();
    }
    }
    

    As far as I can tell this is correct for what I'm doing (the aim has changed slightly to getting the uniqueid, as apparently the phone number is not always obtainable, but getting the phone number is just a matter of calling getLine1Number instead of getDeviceId)

    I also have this hunk of code in my main.cpp to actually create an instance of the java class and call the function:

      jclass native_class= jnienv->FindClass("org/qtproject/qt5/android/bindings/PNumber");
      if(native_class) {
          jmethodID constructor = jnienv->GetMethodID(native_class,"<init>", "()V");
          jobject native_object=jnienv->NewObject(native_class,constructor);
          jmethodID method_getPhoneNumber = jnienv->GetMethodID(native_class,"getPhoneNumber","()Ljava/lang/String;");
          if(method_getPhoneNumber) {
              result = (jstring)jnienv->CallObjectMethod(native_object, method_getPhoneNumber);
              if(result) phnumber=jnienv->GetStringUTFChars(result,JNI_FALSE);
          }
          else phnumber="No methodID!";
      }
      else phnumber="No class!";
    

    However when I run, it throws an exception: java.lang.IllegalStateException: System services not available to Activities before onCreate()

    So the onCreate function isn't getting called for some reason. All of the information I've been able to google up suggests this is done automatically, but frustratingly this either isn't the case, or I'm going wrong in some way I can't tell. I'm thinking of picking an easier line of work, like cat herding. :)



  • What I think the problem is that your activity is never actually started. The only thing you do is invoke a function inside this activity. On android you would need an intent to actually start your activity.

    What you could try is overwriting the activity that gets created by the QtCreator src/org/qtproject/qt5/android/bindings/QtActivity.java. This one should be running actually.



  • have you add your activity in AndroidManifest?



  • Thanks for the responses! I wondered about adding the function to the QtActivity class, but I'm not sure how to get access to the already running instance of it, either through JNI or otherwise. I haven't been able to find an example or tutorial, so any pointers on doing so would be gratefully received.

    I hadn't added the activity into the AndroidManifest - I'll have to see what's involved in that. Thanks!



  • Even if he added it to his AndroidManifest, the error would still be the same. The Activity would still not be active, since you need an intent to start an activity.
    Btw, to access QtActivity, wouldnt you just need to do the same as you did with your PNumber class, just inside QtActivity?



  • Well, to access PNumber from C++, I'm calling NewObject, which creates a new PNumber object. In the case of QtActivity, the object has presumably already been created and is running, so I don't need to create a new one, I need to find a pointer to the already running QtActivity. I'm not sure how to do that.



  • Hmm, have you read this http://community.kde.org/Necessitas/JNI ? I know its for necessitas, but the current Qt5 for android builds on it. You could create a class that uses this runOnUiThread and gives back the phone number.

    http://stackoverflow.com/questions/16410567/android-java-runonuithread



  • Hahahaha, OK, after some more work, I seem to have this problem licked.

    In the QtActivity class, I added these two function:

    public String fetchPhoneNumber() {
            TelephonyManager telephonyManager;
            telephonyManager=(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            return telephonyManager.getDeviceId();
        }
        public String getPhoneNumber() {
          return QtActivity.phonenumber;
        }
    

    Then near the start of the loadApplication method, I called the fetchPhoneNumber method:
    phonenumber=fetchPhoneNumber();

    And added in a new static member phone number at the top:
    public static String phonenumber;

    Then it was just a matter of changing the function in my main.cpp to call getPhoneNumber on QtActivity and Bob was my uncle. (There are probably Qt experts who'd be aghast at the solution, but I've spent enough time on this problem for now)

    It's not an issue with this particular task, but it would be useful to know if there's a way to call java code at any point in the program. At the moment it seems to be the case that you can only call java from the JNI_OnLoad function in main.cpp

    Thank you, everyone who has responded in this thread!



  • I see that this is marked [SOLVED] however that is a bit of a stretch...
    In the ensuing time is there a better solution that is now available for Qt / Android?
    Having to modify the QtActivity class, as the author points out, is not great.

    Does anyone have something to add here?
    I need to do the same thing and really don't want to have to modify the distributed code...

    Thanks,
    Ed


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.