Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

Forums

OverviewFelgo 3 Support (Qt 5) › Adding Google Play services Account Picker to Felgo App

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #24837

    Carlos J Yu

    Hi Felgo Team,

    I’m trying to add Account Picker from Google Play services with custom java, but Im getting this error.

    The goal is to get the list of all accounts on the Android system. Any hints or alternative way how to fix/do this?

    error:

    F zygote64: java_vm_ext.cc:534] JNI DETECTED ERROR IN APPLICATION: JNI NewString called with pending exception java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

    Java:

    also tried extending the class to VPlayActivity but registerForActivityResult can only be called inside Activity

    package org.qtproject.example.jnimessenger;
    
    import android.util.Log;
    import android.app.Activity;
    import android.accounts.AccountManager;
    import android.content.Context;
    import android.content.Intent;
    //Android X
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.activity.result.ActivityResult;
    import androidx.activity.result.ActivityResultCallback;
    import androidx.activity.result.ActivityResultLauncher;
    import androidx.activity.result.contract.ActivityResultContracts;
    //Google Play Services
    import com.google.android.gms.common.AccountPicker;
    import com.google.android.gms.common.AccountPicker.AccountChooserOptions;
    //Felgo
    //import net.vplay.helper.VPlayActivity;
    
    public class JniMessenger extends AppCompatActivity{
    
        private static native void callFromJava(String message);
    
        public JniMessenger() {}
    
        protected void newChooseAccountIntent(Context context) {
            Intent intent = new Intent(AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"},
                   false, null, null, null, null));
                   System.err.println("Java call success!");
                   launchSomeActivity.launch(intent);
        }
    
        ActivityResultLauncher<Intent> launchSomeActivity = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            new ActivityResultCallback<ActivityResult>() {
                @Override
                public void onActivityResult(ActivityResult result) {
                   if (result.getResultCode() == Activity.RESULT_OK) {
                    Intent data = result.getData();
                    String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                    System.err.println("Account Name=" + accountName);
                    }
                }
          });
    }

    cpp:

    #ifdef Q_OS_ANDROID
    #include <QtAndroid>
    #include <QtAndroidExtras/QAndroidJniObject>
    #include <QtAndroidExtras/QAndroidJniEnvironment>
    JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
    {
        JNIEnv* env;
        if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
            qDebug() << "ERROR: JNI version";
            return JNI_ERR;
        }
        jclass javaClass = env->FindClass("org/qtproject/example/jnimessenger/JniMessenger");
        if (!javaClass) {
            qDebug() << "class not found";
            return JNI_ERR;
        } else {
            qDebug() << "class found";
            QAndroidJniObject classObject(javaClass);
            classObject.callMethod<void>("newChooseAccountIntent");
        }
        return JNI_VERSION_1_6;
    }
    #endif

     

    Thank you,

     

    #24838

    Alex
    Felgo Team

    Hi Carlos,

    you’ll need to run the intent on the UI thread, this can be done like this:

    protected void newChooseAccountIntent(Context context) {
        QtNative.activity().runOnUiThread(new Runnable() {
            Intent intent = new Intent(AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"},
            false, null, null, null, null));
            System.err.println("Java call success!");
            launchSomeActivity.launch(intent);
        });
    }

    You might need to add QtNative class to your project to access it, which is part of <Installation directory>/Felgo/android/jar/QtAndroid.jar
    So either copy this to your project or add it via gradle.

    Best,
    Alex

    #24842

    Carlos J Yu

    Hi Alex,

    After running the intent on the UI thread i’m getting an error on starting the activity.

    updated code:

    protected void newChooseAccountIntent() {
        Activity activity = QtNative.activity();
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"},
                false, null, null, null, null));
                System.err.println("Java call success! " + intent);
                launchSomeActivity.launch(intent);
            }
        });
    }

    error:

    E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference
    E AndroidRuntime: 	at android.app.Activity.startActivityForResult(Activity.java:5259)
    E AndroidRuntime: 	at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:712)
    E AndroidRuntime: 	at androidx.core.app.ActivityCompat$Api16Impl.startActivityForResult(ActivityCompat.java:766)
    E AndroidRuntime: 	at androidx.core.app.ActivityCompat.startActivityForResult(ActivityCompat.java:241)
    E AndroidRuntime: 	at androidx.activity.ComponentActivity$2.onLaunch(ComponentActivity.java:237)
    E AndroidRuntime: 	at androidx.activity.result.ActivityResultRegistry$2.launch(ActivityResultRegistry.java:175)
    E AndroidRuntime: 	at androidx.activity.result.ActivityResultLauncher.launch(ActivityResultLauncher.java:47)
    E AndroidRuntime: 	at org.qtproject.example.jnimessenger.JniMessenger$1.run(JniMessenger.java:118)
    E AndroidRuntime: 	at android.app.Activity.runOnUiThread(Activity.java:6980)
    E AndroidRuntime: 	at org.qtproject.example.jnimessenger.JniMessenger.newChooseAccountIntent(JniMessenger.java:111)
    E AndroidRuntime: 	at org.qtproject.qt5.android.QtNative.runPendingCppRunnables(Native Method)
    E AndroidRuntime: 	at org.qtproject.qt5.android.QtNative$1.run(QtNative.java:121)
    E AndroidRuntime: 	at android.os.Handler.handleCallback(Handler.java:883)
    E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:100)
    E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:237)
    E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:8167)
    E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
    E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
    E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

    Any idea what went wrong here?

    Thank you!

    #24848

    Alex
    Felgo Team

    You could try a

    activity.startActivity(intent)

    based approach instead. This would require a custom Activity class though to access the onActivityResult() handler.

    #24855

    Carlos J Yu

    Hi Alex,
    I have tried this approach, but it doesn’t call onActivityResult after selecting and email.

    @Override
        protected void onActivityResult(final int requestCode, final int resultCode,
                final Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            System.out.println("RequestCode:" + requestCode);  //this doesn't print
            System.out.println("ResultCode:" + resultCode ); //this doesn't print
            if(requestCode == PICKER_ACTIVITY){
                if (resultCode == RESULT_OK) {
                    System.out.println("Account:");
                    System.out.println(data.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE));
                    System.out.println(data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME));
                }else if (resultCode == RESULT_CANCELED) {
                    System.out.println("Account Cancel:");
                }
            }else{
                System.out.println("Error requestCode!");
            }
        }

     

    #24863

    Alex
    Felgo Team

    Are you using a custom Activity now, that is derived from the Felgo base Activity (net.vplay.helper.VPlayActivity)?

    Best,
    Alex

    #24871

    Carlos J Yu

    Hi Alex,

    Yes, already changed it after I use this

    activity.startActivityForResult(intent, PICKER_ACTIVITY);

    instead of ActivityResultLauncher<Intent>.

Viewing 7 posts - 1 through 7 (of 7 total)

RSS feed for this thread

You must be logged in to reply to this topic.

Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded