java - 两个应用程序使用 Intent 进行通信,传递数据

标签 java android android-intent

我正在尝试解决使用 Intent 在不同应用程序之间传递数据的问题。 场景是这样的:

  1. Main(应用程序 1):用户单击注册
  2. Main 应用在 Register(应用 2)中启动 Register Activity (表单)
  3. 用户输入名字、姓氏等,然后点击发回
  4. 注册应用程序将值返回到Main应用程序
  5. 应用显示用户数据

请注意,Register Activity 不是 Register Activity 中的主要 Activity 。 我想在没有额外的类和广播的情况下解决这个问题。

我的主应用程序代码,用户单击注册方法:

    /* User clicks Register */
public void clickRegister(View view) {
    Intent intent = new Intent(Intent.ACTION_SEND);
    // Verify it resolves
    PackageManager packageManager = getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
    boolean isIntentSafe = activities.size() > 0;

    // Start an activity if it's safe
    if (isIntentSafe) {
        startActivity(intent);
    }
}
Register 应用中 Register Activity 的

Manifest 文件:

        <activity android:name="com.example.register.Register">
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="text/plain"/>
        </intent-filter>
    </activity>

现在,这是点击Send Back方法的Register Activity 中的代码:

    /* User clicks Send Back in register activity */
public void clickSendBack(View view) {
    // Create an Intent for Register class
    // Intent myIntent = new Intent(this, MainActivity.class);
    Intent myIntent = new Intent(Intent.ACTION_SEND);

    final EditText firstNameInput = (EditText) findViewById(R.id.firstNameEditText);
    final EditText secondNameInput = (EditText) findViewById(R.id.secondNameEditText);

    String firstName = firstNameInput.getText().toString();
    String secondName = secondNameInput.getText().toString();

    myIntent.setAction(Intent.ACTION_SEND);
    myIntent.putExtra("firstName",firstName);
    myIntent.putExtra("secondName",secondName);
    myIntent.setType("text/plain");

    // Starts activity
    startActivity(myIntent);

    finish();
}

我被困住了。 希望听到对此主题的任何说明,并且提供一个解决方案的示例也很棒。

谢谢!

最佳答案

在第一个应用中,添加一个 intent-filter 以接收从第二个应用(即您的Register 应用)返回的数据。 现在,对您的 Register 应用程序执行相同的操作,我们需要执行此操作,以便我们可以从第一个应用程序调用它。

intent-filter 的作用是确保我们可以发回数据。根据https://developer.android.com/guide/components/intents-filters :

To advertise which implicit intents your app can receive, declare one or more intent filters for each of your app components with an element in your manifest file.

从第一个应用程序中,创建一个Intent,它将带您进入第二个应用程序。如果您不想打开Android共享表,那么我建议您使用PackageManager来获取所有可以接收您的数据的 Activity ,然后在列表中查找您的第二个应用程序并根据您的 Intent 使用setComponent()打开它。 (检查下面的代码)

在我们的第二个应用程序中,执行与第一个应用程序中相同的操作,但现在您可以添加额外或数据,例如名字和名字。

回到我们的第一个应用程序,编写将从第二个应用程序接收传入 Intent 的代码,然后就完成了!

引用:

https://developer.android.com/training/sharing

有关发送/接收 Intent 数据的更多信息。


这是一个示例代码:

第一个应用程序的主要 Activity

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

    // Receive your data here from your Register app
    Intent receivedIntent = getIntent();
    String action = receivedIntent.getAction();
    String type = receivedIntent.getType();

    if (Intent.ACTION_SEND.equals(action) && type != null) {
        if ("text/plain".equals(type)) {
            handleReceivedData(receivedIntent);
        }
    }
}

private void handleReceivedData(Intent intent) {
    String firstName = intent.getStringExtra("first_name");
    String secondName = intent.getStringExtra("second_name");
    if (firstName == null || secondName == null) {
        Toast.makeText(this, "Cannot received data!", Toast.LENGTH_SHORT).show();
        return;
    }
    // Do here what you want with firstName and secondName
    // ...
    Toast.makeText(this, "First name: " + firstName +
            " Second name: " + secondName, Toast.LENGTH_SHORT).show();
}

public void open(View view) {
    Intent sendIntent = new Intent();
    sendIntent.setAction(Intent.ACTION_SEND);
    sendIntent.putExtra(Intent.EXTRA_TEXT,
            "Here you can put a message for your 'register' application");
    sendIntent.setType("text/plain");

    PackageManager packageManager = getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(sendIntent,
            PackageManager.MATCH_DEFAULT_ONLY);

    ////////////////// Get the other application package name //////////////////
    // This is so the user cannot choose other apps to send your data
    // In order words, this will send the data back to the other
    // application without opening the Android Share sheet
    ActivityInfo activityInfo = null;
    for (ResolveInfo activity: activities) {
        // Specify here the package name of your register application
        if (activity.activityInfo.packageName.equals("com.example.registerapp")) {
            activityInfo = activity.activityInfo;
            break;
        }
    }

    // If the other application is not found then activityInfo will be null
    // So make sure you add the correct intent-filter there!
    if (activityInfo != null) {
        // This will open up your register application
        ComponentName name = new ComponentName(activityInfo.applicationInfo.packageName,
                activityInfo.name);
        sendIntent.setComponent(name);

        startActivity(sendIntent);
    }
    else {
        Toast.makeText(this,
                "Receiver app doesn't exist or not installed on this device!",
                Toast.LENGTH_SHORT).show();
    }
}

第一个应用程序的 list

    <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>

第二个应用程序的接收者 Activity (在本例中为您的注册应用程序) 注意:如您所愿,这不是主要 Activity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_receiver);
    // This is NOT the main activity!
}

public void send(View view) {
    // I just want to note that I am calling the receiving application: "other application"

    EditText firstNameEditText = findViewById(R.id.firstNameEditText);
    EditText secondNameEditText = findViewById(R.id.secondNameEditText);
    String firstName = firstNameEditText.getText().toString().trim();
    String secondName = secondNameEditText.getText().toString().trim();
    // Check if any of the inputs are empty
    if (firstName.isEmpty() || secondName.isEmpty()) {
        Toast.makeText(this, "Text boxes cannot be empty!", Toast.LENGTH_SHORT).show();
        return;
    }

    // Send data back to the other application
    Intent sendBackIntent = new Intent();
    sendBackIntent.setAction(Intent.ACTION_SEND);
    sendBackIntent.putExtra("first_name", firstName);
    sendBackIntent.putExtra("second_name", secondName);
    sendBackIntent.setType("text/plain");

    // Get all the available applications that can receive your data
    // (in this case, first name and second name)
    PackageManager packageManager = getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(sendBackIntent,
            PackageManager.MATCH_DEFAULT_ONLY);

    ////////////////// Get the other application package name //////////////////
    ActivityInfo activityInfo = null;
    for (ResolveInfo activity: activities) {
        // Specify here the package name of the other application
        if (activity.activityInfo.packageName.equals("com.example.mainapp")) {
            activityInfo = activity.activityInfo;
            break;
        }
    }

    if (activityInfo != null) {
        // Same as before, this will open up the other application
        ComponentName name = new ComponentName(activityInfo.applicationInfo.packageName,
                activityInfo.name);
        sendBackIntent.setComponent(name);

        startActivity(sendBackIntent);
    }
    else {
        Toast.makeText(this,
                "Receiver app doesn't exist or not installed on this device!",
                Toast.LENGTH_SHORT).show();
    }
}

第二个应用程序的 list

<activity android:name=".ReceiverActivity">
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="text/plain" />
        </intent-filter>
    </activity>

祝你编码愉快!


编辑:我在答案中添加了解释。

关于java - 两个应用程序使用 Intent 进行通信,传递数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61333066/

相关文章:

android - 可以绕过 Android Intent Filter 吗?

java - 从同一包中的主类访问无状态 session bean

java - Multi-Tenancy 应用程序: one database or multiple copies of same database

android - 通过安卓应用分享谷歌地图静态图片

javascript - Android native 通过 cordova 进行 JavaScript 通信

android - 无法将新的 APK 文件上传到 Android Play 商店

android - 如何打开联系人并让用户决定他/她是否要创建或选择一个联系人

java - 循环帮助!向 map API v2 添加多个标记

java - 线程运行方法内部使用的方法的同步

java - 显示每帧变化的文本(如乐谱)