在安卓系统中,如何在两个应用程序之间传输数据?

10

我尝试在Android中通过Intent将数据从App1发送到App2,但我无法解决我的问题。

这是我使用的代码,但它并没有解决我的问题。

App1 MainActivity:

        Intent i2 = new Intent("com.appstore.MainActivity");
        i2.setPackage("com.appstore");//the destination packageName
        i2.putExtra("Id", "100");
        startActivity(i2);

App2 主活动:

Bundle data = getIntent().getExtras;
if(data!=null){
    String myString = b.getString("Id");

}

应用程序2的主活动:

   <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="image/*" />
            </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>
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
            </intent-filter>

        </activity>

2
利用内容提供者在应用程序之间发送数据。 - Arshak
3
使用内容提供者(Content Provider)来在两个Activity之间传递一个字符串可能有些过度,可以考虑其他更加简单的方式。 - David Wasser
6个回答

8

最终代码:

应用程序1:

        Intent intent = new Intent();
        intent.setClassName("com.appstore", "com.appstore.MyBroadcastReceiver");
        intent.setAction("com.appstore.MyBroadcastReceiver");
        intent.putExtra("KeyName","code1id");
        sendBroadcast(intent);

应用程序2:

Reciver:
public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "Data Received from External App", Toast.LENGTH_SHORT).show();

    }
}

清单:

        <receiver
            android:name=".MyBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="first_app_packagename" />
            </intent-filter>
        </receiver>

MainActivity :

  MyBroadcastReceiver mReceiver = new MyBroadcastReceiver();
        registerReceiver(mReceiver,
                new IntentFilter("first_app_packagename"));

5
这种方法可能适用于您,但您的代码里有太多东西了,而且您可能不理解为什么您的代码有效。 首先,如果您在清单文件中声明了<intent-filter>,则无需指定exported ="true",因为这是默认值; 也无需指定enabled ="true",因为默认情况下所有组件都是启用的。 其次,如果您在清单文件中指定了一个<intent-filter>,则不需要通过调用registerReceiver()来注册BroadcastReceiver。 您只需选择其中一种方法即可,不要两者都使用 - David Wasser
4
第三点,你在清单文件中声明的<intent-filter>和在registerReceiver()中使用的IntentFilter都是无用的,因为你从未实际发送包含"ACTION"为"first_app_packagename"的广播意图。第四点,由于你使用setClassName()在广播意图上显式设置了组件,所以你不需要在广播意图中设置"ACTION",这也是无用的。 - David Wasser

4

我的需求是从App1发送“用户ID”到App2并获取“用户名”返回到App1。

我需要直接启动我的应用程序,而不使用任何选择器。我能够使用隐式意图和startActivityForResult来实现这一点。

App1 > MainActivity.java

private void launchOtherApp() {
    Intent sendIntent = new Intent();
    //Need to register your intent filter in App2 in manifest file with same action.
    sendIntent.setAction("com.example.sender.login"); // <packagename.login>
    Bundle bundle = new Bundle();
    bundle.putString("user_id", "1111");
    sendIntent.putExtra("data", bundle);
    sendIntent.setType("text/plain");
    if (sendIntent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(sendIntent, REQUEST_CODE);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE) {
        if (resultCode == Activity.RESULT_OK) {
            Bundle bundle = data.getBundleExtra("data");
            String username = bundle.getString("user_name");
            result.success(username);
        }
    } else {
        super.onActivityResult(requestCode, resultCode, data);
    }
}

我在App2中有两个活动,即MainActivity和LoginActivity。

App2 > AndroidManifest.xml

<activity android:name=".LoginActivity">
    <intent-filter>
        <!--The action has to be same as App1-->
        <action android:name="com.example.sender.login" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
</activity>

很抱歉,我的Java和Kotlin混淆了一下。我的第二个应用程序是用Kotlin编写的,但不会有任何影响。

App2 > LoginActivity.java

override fun onResume() {
    super.onResume()
    var userId = "No data received"
    val intent = intent
    if (intent != null
        && intent.action != null
        && intent.action.equals("com.example.sender.login")
    ) {
        val bundle = intent.getBundleExtra("data")
        if (bundle != null) {
            userId = bundle.getString("user_id")
            userId = " User id is $userId"
        }
    }
    tvMessage.text = "Data Received: $userId"
}

fun onClickBack(view: View) {
    val intent = intent
    val bundle = Bundle()
    bundle.putString("sesion_id", "2222")
    intent.putExtra("data", bundle)
    setResult(Activity.RESULT_OK, intent)
    finish()
}

3
当你执行以下操作时:

    Intent i2 = new Intent("com.appstore.MainActivity");
    i2.setPackage("com.appstore");//the destination packageName
    i2.putExtra("Id", "100");
    startActivity(i2);

你正在调用 Intent 的单参数构造函数。在这个构造函数中,该参数被解释为 Intent 的操作。然后你在 Intent 中设置包名。
当你使用这个 Intent 调用 startActivity() 时,Android 将查找包含指定操作的 <intent-filter>Activity。在清单文件中没有定义如此的Activity 的已安装应用程序。
<activity>
    <intent-filter>
        <action android:name="com.appstore.MainActivity"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

因此,Android 将无法找到并启动您想要的 Activity

如果您想明确指定要使用的组件,而不是使用 1 个参数的 Intent 构造函数,您应该执行以下操作:

    Intent i2 = new Intent();
    i2.setClassName("com.appstore", "com.appstore.MainActivity");
    i2.putExtra("Id", "100");
    startActivity(i2);

使用setClassName()方法,您可以提供要启动的组件的包名和类名。

你的代码运行其他应用程序,但不发送数据。 - Farzad
你需要解释一下你所说的“发送数据”的意思。你想发送什么样的数据? - David Wasser

1
这应该可以工作:

APP1

    Intent i2 = new Intent();
    i2.setComponent(new ComponentName(PACKAGE,ACTIVITY));//the destination packageName
    i2.putExtra("Id", "100");
    startActivity(i2);
    

APP2

    String myString = getIntent().getStringExtra("Id");

0

使用 Bundle.putSerializable(Key,Object);Bundle.putParcelable(Key, Object); 方法,前者的对象必须实现 Serializable 接口,而后者的对象必须实现 Parcelable 接口。


如何将 bundle Bundle.putSerializable(Key,Object); 放入 intent 中? - Farzad
因为String已经实现了Serializable,所以i2.putExtra("Id", "100");是可以的。但是,如果要启动一个显式活动,请使用i2.setClassName("com.appstore" "com.appstore.MainActivity"); - samm

0

内容提供者:

内容提供者是标准接口,将一个进程中的数据与另一个进程中运行的代码连接起来。

请参阅Android文档。

内容提供者工作演示{{link2:在此处查看。}}


我找到了这个例子。http://infobloggall.com/2015/04/14/communication-between-two-applications-in-android-using-messenger/ - Farzad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接