braintree / popup-bridge-android

PopupBridge allows WebViews to open popup windows in a browser and send data back to the WebView
MIT License
53 stars 28 forks source link

Working in one emulator only #23

Closed molundb closed 4 years ago

molundb commented 4 years ago

General information

Issue description

The example project works fine but I am having problems getting the bridge to work in my app. I have followed the instructions and added the following necessary code to my AndroidManifest.xml file.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.poc_like_example">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.Light">

        <activity android:name="com.example.poc_like_example.PopupActivity"/>

        <activity android:name="com.example.poc_like_example.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name="com.braintreepayments.popupbridge.PopupBridgeActivity"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="${applicationId}.popupbridge" />
            </intent-filter>
        </activity>
    </application>
</manifest>

The thing is that it works on one emulator but not on any other devices. I have tried clearing the caches and restarting Android Studio, and wiping the data of the emulators that it's not working on.

The part of the code where it goes wrong is below. On the emulator where the bridge is working mContext.getPackageManager().queryIntentActivities(intent, 0) find 1 activity, but on the other devices it finds 0. I don't see why it's not finding any activities. It should match the activity that I set in the manifest and find that one, why doesn't it?

private boolean isReturnUrlSetup() {
        Intent intent = new Intent(Intent.ACTION_VIEW)
                .setData(Uri.parse(getReturnUrlScheme() + "://"))
                .addCategory(Intent.CATEGORY_DEFAULT)
                .addCategory(Intent.CATEGORY_BROWSABLE);

        return availableActivities(intent).size() == 1;
    }

    private List<ResolveInfo> availableActivities(Intent intent) {
        return mContext.getPackageManager()
                .queryIntentActivities(intent, 0);
    }

To summarize: The problem is that queryIntentActivities(intent, 0) is returning different results for the same code.

What could be causing that? Thank you so much for your time.

sshropshire commented 4 years ago

Hi @molundb, thank you for using the Braintree SDK for Android.

In this case, I would recommend viewing the final merged AndroidManifest.xml in Android Studio for your app to ensure that PopupBridgeActivity has been properly configured. You can do this by checking the "Merged Manifest" tab at the bottom of the window when viewing the manifest file.

Also, I would confirm that getReturnUrlScheme() returns a scheme that matches your app id without underscore characters for your particular build variant.

molundb commented 4 years ago

Hi @sshropshire, thank you for such a quick reply.

Thanks to your comment I was able to make progress. I noticed that the value for <data> in the <intent-filter> in the PopupBridgeActivity defined the AndroidManifest.xml didn't match data in the intent passed to the methodavailableActivites in BrowserSwitchFragment.java.

When I hardcode the value in the AndroidManifest.xml to not contain any underscores the bridge works in the proof of concept that I created. This is not a feasible solution in my actual app however since I am using different buildflavors, so it can't be hardcoded. If you have the time I would be very grateful if you could answer some follow questions.

  1. Am I correct in believing that the data parameter in the AndroidManifest.xml file needs to exactly match the data in the intent used in the call to availableActivites for the PopupBridgeActivity to be found and the bridge to work?

  2. If that is the case, why does getReturnUrlScheme remove the underscores? Then how is ${applicationId} ever going to work in a project with an application name containing underscores?

sshropshire commented 4 years ago

TL;DR: Consider changing the applicationId for each build flavor to an application id without underscores.

@molundb responses inline:

Am I correct in believing that the data parameter in the AndroidManifest.xml file needs to exactly match the data in the intent used in the call to availableActivites for the PopupBridgeActivity to be found and the bridge to work?

Yes, the available activities call is looking for the intent that will accept the redirect from the web browser. We make this run-time check to make sure that Browser Switch is possible.

If that is the case, why does getReturnUrlScheme remove the underscores? Then how is ${applicationId} ever going to work in a project with an application name containing underscores?

On one hand, removing the underscores in getReturnUrlScheme ensures we return a valid URL scheme. Without this safeguard, Browser Switch would be broken immediately.

On the other hand, I see your concern here. This may be a limitation with our current implementation and something we will look into.

In the meantime, since you are using different build flavors, you can change the applicationId for each build flavor to something without underscores, and that should work.

molundb commented 4 years ago

Thank you again for your help.

@sshropshire response inline:

In the meantime, since you are using different build flavors, you can change the applicationId for each build flavor to something without underscores, and that should work.

You're right, that would make the bridge work, but wouldn't it then be a completely different app in Google Play Store? If so, that is unfortunately not a viable solution since the app is already published and used.

What I need to do is set the URL scheme in the AndroidManifest.xml to the applicationId without the underscore. Hopefully that is possible somehow. I will look into that.

molundb commented 4 years ago

I solved it by creating and injecting a variable to the manifest as described here: https://developer.android.com/studio/build/manifest-build-variables

sshropshire commented 4 years ago

@molundb awesome! We'll take note of this in future releases. As always, we appreciate your feedback.