Android:从第三方应用分享数据和接收文本。为什么我的应用没有收到新文字?

时间:2016-03-16 14:58:03

标签: android android-intent intentfilter

摘要

我正在尝试通过“共享”菜单从用户发送数据。在这种情况下,我将使用基本的Android网络浏览器选择文本,然后将其分享到我的应用程序。

问题

用户第一次共享文本我的应用程序按预期获取文本并通过 Log.d()显示它 - 请参阅 handleSendText()方法下面的代码。

但是,每次此后,即使用户在Web浏览器中选择了新文本并与我的应用程序共享,我仍然可以获得用户选择的原始文本(之前的值)。

问题

你如何重置意图 - 或者它是什么 - 以便我可以获得用户在第一次选择之后选择的新文本?

详情

我的应用程序有一个MainActivity,我跟着Google文档: http://developer.android.com/training/sharing/receive.html

使用我的MainActivity中的以下代码

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent intent = getIntent();
    String action = intent.getAction();
    String type = intent.getType();

    if (Intent.ACTION_SEND.equals(action) && type != null) {
        if ("text/plain".equals(type)) {
            handleSendText(intent, "onCreate"); // Handle text being sent
        }
    }
}

@Override
public void onResume(){
    super.onResume();
    Intent intent = getIntent();
    String action = intent.getAction();
    String type = intent.getType();

    if (Intent.ACTION_SEND.equals(action) && type != null) {
        if ("text/plain".equals(type)) {
            handleSendText(intent, "onResume"); // Handle text being sent
        }
    }

}

void handleSendText(Intent intent, String callingMethodName) {
    String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
    if (sharedText != null) {
    Log.d("MainActivity", "sharedText : " + sharedText + " called from : " + callingMethodName);
    }
}

}

我的AndroidManifest活动部分添加了过滤器,如:

<activity android:name=".MainActivity">
            <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/plain" />
            </intent-filter>
        </activity>

使用屏幕和日志进行直播

注意:请注意我已经在我的应用中实现了onResume(),以确保在调用onCreate()时我不会只获取Intent(仅限)一次应用程序启动时。)

启动浏览器并抓取文字&#34;飓风&#34;。

grab text hurricane

选择要与之分享的应用(我们的测试应用)。

share with GrabText app

查看日志并注意调用onCreate()和onResume()并且值为&#39;飓风&#39;

view log see values

再次返回浏览器以分享更多文字...

back to browser

选择要分享的新单词Atlantic。

select new word: atlantic

额外注意:当我们点击此分享链接时,Android MenuChooser不会显示,而是会再次自动打开GrabText。我发现这种行为有点奇怪。

请注意,Intent文本仍然具有飓风的值。您可以看到logcat中现在有两个新条目。

intent text is still hurricane

尝试的解决方法解决方案

我发现我可以通过覆盖 onPause()并在我的Activity上调用 finish()来完全破坏应用程序(从而关闭整个应用程序)工作,但是有没有其他方法来重置Intent或相关文本或什么?

您是否知道有任何其他方法可以确保检索到新数据? 我感谢任何帮助。

更新 注意:我正在更新,因为没有很好的方式来展示尝试的其他代码,但是,如果没有来自其他SO用户的输入,我也不会知道这样做, CommonsWare

我收到的第一个答案是我应该添加 @Override onNewIntent(),所以我将以下代码添加到我的MainActivity中:

 @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.d("MainActivity", "onNewIntent()...");
        String action = intent.getAction();
        String type = intent.getType();
        if (Intent.ACTION_SEND.equals(action) && type != null) {
            if ("text/plain".equals(type)) {
                handleSendText(intent, "onNewIntent"); // Handle text being sent
            }
        }

    }

在添加该代码并运行并尝试复制然后第二次复制新单词后,我仍然在logcat中看到以下内容:

still doesn't capture new word

它甚至看起来好像甚至没有调用 onNewItent()方法。

编辑2

我更改了模拟器设置...开发人员选项...并关闭了“不要保持活动”#34;设置。之前已打开(已选中)。 don't keep activities

之后,我运行了包含 onNewIntent()覆盖的应用程序,但现在它只显示了一个 onCreate()消失了(这是有意义的,因为活动是仍然加载)但仍然没有显示onNewIntent()调用。 在这个示例中,我捕获了“#n残余&#34;”这个词。

another attempted capture

编辑3

我构建了应用程序并创建了一个APK并将其部署到我的三星Galaxy Core Prime,我得到了相同的结果。 onNewIntent() 从不被调用。

我只是查看了Google文档中的NewIntent,并声明:

  

onNewIntent(意图意图)这是调用设置的活动   在他们的包中启动模式到&#34; singleTop&#34; ,或者如果客户端使用了   调用startActivity(Intent)时的FLAG_ACTIVITY_SINGLE_TOP标志。

我还没有设置singleTop,所以我现在就试试吧。嗯...

编辑4

我现在尝试过singleTop变体。我之前在模拟器上测试API 15(v4.0.4),所以我切换到API 21(v5.0),看看是否有任何不同。

以下是singleTop添加到我的AndroidManifest.xml中的内容:

<activity android:name=".MainActivity" android:launchMode="singleTop">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
</activity>

注意我还将两个intent-filter节点折叠成一个。

所选文字已更改

在Android API Level 21上,每当我在浏览器中选择文本时,Intent文本现在都会有所不同。

onNewIntent永远不会被调用

然而,onNewIntent永远不会被调用。我永远不会看到它。

每次都显示共享菜单

此外,现在(在API 21上)每次选择文本时都会看到“共享”菜单。 但是,当我切换到浏览器时,我也看到了一件有趣的事情。您可以在列表中看到活动的多个副本。什么?!

multiple copies of grabtext

另请注意,我将MainActivity实现为ListView(可滚动),因此我甚至可以在没有logcat的情况下看到条目(用于在真实设备上运行)。这使得其他方面显而易见:ListView正在每个新显示的Activity上更新。但实际上,它应该是附加到的原始活动。

创建大量GrabText活动 是的,现在每次选择文本时它都会创建一个新的GrabText Activity窗口。我想也许是因为我有singleTop设置所以我删除了它,但即使在API LEVEL 21上删除singleTop后它们仍然出现。

现在我看到它工作了 - 每次在API 21上提供不同的文本我决定切换回API Level 15模拟器并尝试它。

在我再次尝试API级别15后,我会报告回来。

API级别15:再次测试

我启动了另一个运行API Level 15的模拟器并运行了应用程序,即使使用singleTop设置,该值也永远不会更新。

您可以在logcat和更新的ListView上看到这一点:

logcat onResume

append to ListView via api15

您还可以看到代码的行为完全不同,但我没有更改任何内容,因为它附加到api级别15上运行的Activity的ListView。

我已经写了一本关于这个记录非常严重的事情的书。我希望这可以帮助某人和谷歌Android开发人员看到并解释它。

3 个答案:

答案 0 :(得分:0)

如果您的活动已经存在,系统会使用onNewIntent()而不是onCreate()来调用它。 onNewIntent()将通过您需要用于邮件的Intent

答案 1 :(得分:0)

尝试将manifest.xml中的android:launchMode活动更改为 的 singleTop

这样,如果活动已经启动,将在 onNewIntent ()方法中收到新的意图

答案 2 :(得分:0)

实际上只有一个答案可行,但它可能会导致其他问题。

只要Activity进入onPause(),你就必须决定调用finish()。

这是我实施的确切代码,适用于所有API级别。

@Override
    public void onPause(){
        super.onPause();
        finish();
    }

销毁活动

当您添加该代码时,每次切换回您正在共享的应用程序(在我们的示例中为Web浏览器),然后onPause将触发您的MainActivity,而finish()方法将设置Activity以进行销毁。

此后每次显示共享菜单

每次从共享应用程序(Web浏览器)中选择文本时都会使用此解决方案,然后将显示“共享”菜单,并将GrabText显示为其中一个选项(而不是自动强制GrabText再次显示在前面)。

共享文字始终是新文字

由于MainActivity被完全销毁,因此必须再次完全加载(onCreate()),因此它会收到已发送的新Intent文本。

不是一个好的解决方法

然而,这并不是一个很好的解决方法,因为我相信你的应用中的对话框也会创建onPause()来调用你的Activity会被销毁。显然,破坏你的Activity onPause()并不是因为你开始管理&#34;记忆&#34;以一种真正应该留给操作系统的方式。但是,在这种情况下,它似乎是解决问题的唯一方法。