Receiving consecutive SEND intents brings app back

2020-04-19 16:52发布

On a project I'm working on I've come across an issue with receiving external intents, i.e. non-launcher intents. I have an Activity that can be started using the normal LAUNCHER intent, but it also responds to SEND intents from other apps, e.g. sharing a link to a video in the YouTube app. The first time I'm sharing a link from the other app, my Activity is created and I can use getIntent() to get at the details of the intent, i.e. the EXTRA_TEXT. If I close my Activity and try again with another link, that works fine too. However, if I don't close my Activity, go back to the other app via "home" or "recently launched apps", and share another link, my Activity comes back to the foreground, but getIntent() results in the old intent, not the new one that I would have thought triggered the restart of my Activity.

I have created an MCVE illustrating this issue:

The Activity:

public class MainActivity extends ActionBarActivity {
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d("MainActivity", "onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.intent_text);
    }

    @Override
    protected void onResume() {
        Log.d("MainActivity", "onResume");
        super.onResume();
        Intent intent = getIntent();
        String text;
        if (intent.hasExtra(Intent.EXTRA_TEXT)) {
            text = intent.getExtras().getString(Intent.EXTRA_TEXT);
        } else {
            text = "nothing";
        }
        tv.setText(text);
    }
}

The manifest:

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="IntentTest"
        android:theme="@style/Theme.AppCompat" >
        <activity
            android:name=".MainActivity"
            android:label="IntentTest" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/*" />
            </intent-filter>
        </activity>
    </application>

</manifest>

For completeness sake, the trivial layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.intenttest.MainActivity" >

    <TextView
        android:id="@+id/intent_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>
  1. Start app, text view prints "nothing"
  2. Start YouTube app, share link, select this app, app gets restarted, text view shows whatever text YouTube has shared
  3. Press home
  4. Back to YouTube app, share different link, select this app, app gets restarted, text view shows same old text from before
  5. Press back or swipe app from "recent apps"
  6. Back to YouTube app, share yet another link, select this app, app gets restarted (re-created), text view shows new text YouTube has just shared

I get the feeling I'm missing something fundamental here. How do I get my app to respond to the new Intent?

1条回答
男人必须洒脱
2楼-- · 2020-04-19 17:07

Add android:launchMode="singleTop" to the <activity> description.

When the Activity is launched (if it isn't already running), Android will call onCreate() and you can get the Intent by calling getIntent() (like you are already doing).

If the Activity is launched while your app is already running, Android will bring it to the foreground and will call onNewIntent() passing in the new Intent. You should override this method and do something with the passed Intent (save it in a member variable or extract what you want from it or whatever). After that Android will call onResume().

Calling getIntent() will ALWAYS return the Intent that was used to originally start the Activity.

查看更多
登录 后发表回答