如何处理Android应用程序的多个深度链接

时间:2020-02-28 20:05:27

标签: android android-studio webview android-webview deep-linking

我创建了一个Android应用。每当有人通过该应用程序打开网站时,都会转到确切的链接。但是,如果用户打开另一个链接,则该应用程序仍在先前打开的链接上。您可以在此处检查该应用:https://play.google.com/store/apps/details?id=app.freeairdrop.io

在Telegram或Whatsapp上将这两个链接发送给自己:

  1. https://freeairdrop.io/airdrop/morpher.html
  2. https://freeairdrop.io/airdrop/simbcoin.html

现在,当系统提示您选择应用程序时,打开我的应用程序中的第一个链接。切换回Telegram / whatsapp,然后单击第二个链接。我的应用程序将打开,但仍在该页面(第一个链接)上。没有任何反应,除非关闭应用程序,否则该应用程序将无法加载第二个链接。

MainActivity.java代码:

package app.freeairdrop.io;

import...    

public class MainActivity extends Activity{
    private ProgressBar progressBar;
    private WebView webView;
    private SwipeRefreshLayout mySwipeRefreshLayout;
    private boolean mShouldPause;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    public void onCreate(Bundle savedInstanceState) {


        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        progressBar.setMax(100);
        webView = (WebView) findViewById(R.id.webView);
        webView.setWebViewClient(new WebViewClientDemo());
        webView.setWebChromeClient(new WebChromeClientDemo());
        mySwipeRefreshLayout = (SwipeRefreshLayout) this.findViewById(R.id.swipeContainer);


        mySwipeRefreshLayout.setOnRefreshListener(
                new SwipeRefreshLayout.OnRefreshListener() {
                    @Override
                    public void onRefresh() {
                        webView.reload();
                        mySwipeRefreshLayout.setRefreshing(false);
                    }
                }
        );

        // ATTENTION: This was auto-generated to handle app links.
        Intent appLinkIntent = getIntent();
        String appLinkAction = appLinkIntent.getAction();
        Uri appLinkData = appLinkIntent.getData();

        if (getIntent().getExtras() != null) {
            if (appLinkData == null){
                webView.loadUrl("https://freeairdrop.io/");
            }else
            webView.loadUrl(String.valueOf(appLinkData));

        } else if (getIntent().getExtras() == null){
            webView.loadUrl("https://freeairdrop.io/");

        }webView.reload();
    }

    private class WebViewClientDemo extends WebViewClient {

        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            super.onReceivedError(view, errorCode, description, failingUrl);
            Toasty.error(getApplicationContext(), "No Internet, pull down to refresh when you're connected to internet", Toast.LENGTH_LONG, true).show();
        }


        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Uri uri = Uri.parse(url);
            if (uri.getHost() != null && (url.startsWith("https://freeairdrop.io/") || url.startsWith("https://www.freeairdrop.io/"))) {
                return false;
            }

            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            view.getContext().startActivity(intent);
            return true;
        }
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            progressBar.setVisibility(View.GONE);
            progressBar.setProgress(100);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            progressBar.setVisibility(View.VISIBLE);
            progressBar.setProgress(0);
        }
    }


    private class WebChromeClientDemo extends WebChromeClient {

        public void onProgressChanged(WebView view, int progress) {
            progressBar.setProgress(progress);
        }
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
            webView.goBack();
            return true;
        }
        else {
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return true;
    }

    @Override
    // This method is used to detect back button
    public void onBackPressed() {
        if (this.webView.canGoBack()) {
            this.webView.goBack();
            return;
        }

        else {
            // Let the system handle the back button
           super.onBackPressed();
        }
    }


}

AndroidManifest代码:

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

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

    <application
        android:appCategory="productivity"
        android:hardwareAccelerated="true"
        android:allowBackup="true"
        android:fullBackupContent="true"
        android:icon="@mipmap/ic_launcher"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        android:name=".ApplicationClass"
        tools:ignore="GoogleAppIndexingWarning">
        <activity
            android:name="app.freeairdrop.io.MainActivity"
            android:label="@string/app_name"
            android:configChanges="orientation|screenSize|screenLayout"
            android:resizeableActivity="false"
            android:supportsPictureInPicture="false"
            android:launchMode="singleInstance"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:scheme="https"
                    android:host="freeairdrop.io" />
            </intent-filter>


        </activity>
    </application>


</manifest>

1 个答案:

答案 0 :(得分:0)

为活动设置android:launchMode="singleInstance"将仅使该活动的一个实例运行。这意味着当您通过Deeplink打开一次活动后,该实例正在运行。当您打开第二个链接时,您希望您的UI得到更新,但是由于实例仍在运行,因此未调用活动的onCreate,这就是为什么您从较早的链接中看到视图的原因。(另一点是singleInstance是设置为不允许在堆栈中进行任何其他活动。)

您可以在official docs中获得更多信息。

现在,即使从不调用onCreate,但是在设置singleInstance时也会调用onResumeonNewIntent方法。尽管通常提到onNewIntentsingleTop一起使用,但是根据我的经验,当设置三个单个标志中的任何一个时,确实会调用它。

因此,您需要覆盖二者之一并编写代码以更新其中的UI。另请注意,在onResume之后的第一次创建活动时,确实会调用onCreate,因此,如果在该位置放置代码,则可能需要优化以避免重复两次加载相同的东西,并且每次onResume都被获取从后台返回后的调用方式在这种情况下,onNewIntent()似乎是一个更好的选择。

希望这对您有所帮助。

更新:根据要求,您可以在下面找到修改后的代码

package app.freeairdrop.io;

        import...

public class MainActivity extends Activity{
    private ProgressBar progressBar;
    private WebView webView;
    private SwipeRefreshLayout mySwipeRefreshLayout;
    private boolean mShouldPause;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        progressBar.setMax(100);
        webView = (WebView) findViewById(R.id.webView);
        webView.setWebViewClient(new WebViewClientDemo());
        webView.setWebChromeClient(new WebChromeClientDemo());
        mySwipeRefreshLayout = (SwipeRefreshLayout) this.findViewById(R.id.swipeContainer);

        mySwipeRefreshLayout.setOnRefreshListener(
                new SwipeRefreshLayout.OnRefreshListener() {
                    @Override
                    public void onRefresh() {
                        webView.reload();
                        mySwipeRefreshLayout.setRefreshing(false);
                    }
                }
        );
        // call your method here to manage the intent
        manageIntent(getIntent());
    }

    /* Simply moved your code which handles the intent to a common method
     * Call this method from onCreate so that when first instance of activity gets created it handles it
     * Similarly call it from onNewIntent to manage the new link you get
     * You just need to pass the respective intents from the methods
     */
    public void manageIntent(Intent intent) {
        // ATTENTION: This was auto-generated to handle app links.
        Intent appLinkIntent = intent;
        String appLinkAction = appLinkIntent.getAction();
        Uri appLinkData = appLinkIntent.getData();

        if (getIntent().getExtras() != null) {
            if (appLinkData == null){
                webView.loadUrl("https://freeairdrop.io/");
            }else
                webView.loadUrl(String.valueOf(appLinkData));

        } else if (getIntent().getExtras() == null){
            webView.loadUrl("https://freeairdrop.io/");

        }
    }

    // override to get the new intent when this activity has an instance already running
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        // again call the same method here with the new intent received
        manageIntent(intent);
    }

    private class WebViewClientDemo extends WebViewClient {

        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            super.onReceivedError(view, errorCode, description, failingUrl);
            Toasty.error(getApplicationContext(), "No Internet, pull down to refresh when you're connected to internet", Toast.LENGTH_LONG, true).show();
        }


        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Uri uri = Uri.parse(url);
            if (uri.getHost() != null && (url.startsWith("https://freeairdrop.io/") || url.startsWith("https://www.freeairdrop.io/"))) {
                return false;
            }

            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            view.getContext().startActivity(intent);
            return true;
        }
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            progressBar.setVisibility(View.GONE);
            progressBar.setProgress(100);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            progressBar.setVisibility(View.VISIBLE);
            progressBar.setProgress(0);
        }
    }


    private class WebChromeClientDemo extends WebChromeClient {

        public void onProgressChanged(WebView view, int progress) {
            progressBar.setProgress(progress);
        }
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
            webView.goBack();
            return true;
        }
        else {
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return true;
    }

    @Override
    // This method is used to detect back button
    public void onBackPressed() {
        if (this.webView.canGoBack()) {
            this.webView.goBack();
            return;
        }

        else {
            // Let the system handle the back button
            super.onBackPressed();
        }
    }

}

看看这是否对您有用,让我知道。