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

Two apps communicating using Intent, passing data

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

  1. Main(App 1):用户点击Register
  2. Main 应用程序在 Register(应用程序 2)
  3. 中启动 Register activity(表单)
  4. 用户输入名字、姓氏等,点击Send Back
  5. Register 应用返回值到 Main 应用
  6. Main 应用程序显示用户数据

注意Registeractivity不是Registeractivity中的主要activity。 我想在没有额外 class 且没有广播的情况下解决这个问题。

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

    /* 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);
    }
}

Manifest 文件 Register activity 在 Register 应用中:

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

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

    /* 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 share sheet 那么我建议您使用 PackageManager 获取所有可以接收您的数据的活动,然后在列表中找到您的第二个应用程序并使用 setComponent() 和你的 intent。 (检查下面我的代码)

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

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

参考:

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

有关 sending/receiving 具有意图的数据的更多信息。


这是一个示例代码:

第一个应用程序的主要 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();
    }
}

第一个应用程序的清单

    <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();
    }
}

第二个应用程序的清单

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

编码愉快!


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

你的 RegisterActivity 应该是这样的 RegisterActivity 正在解析用户数据到 MainActivity

/* 用户在寄存器中点击发送回 activity */

public void clickSendBack(View view) {
   // Create an Intent for Register class

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

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

   Intent i = new Intent(RegisterActiivty.this, MainActivity.class);
   i.putExtra("firstName", firstName);
   i.putExtra("secondName", secondName);
   startActivity(i);

    }
 #################################################################

您的 MainActivity 应该看起来像这样。 MainActivity负责接收数据 这行代码应该在你的MainActivity

的onCreate方法中调用
    String firstName = getIntent().getStringExtra("firstName");
    String secondName = getIntent().getStringExtra("firstName")

    // if you have a TextView on MainActivity you could display the data you have 
    //gotten from the RegisterActivity like so

    Textview firstName = findViewById(R.id.firstName);
    firstName.setText(firstName);

    Textview secondName = findViewById(R.id.secondName);
    secondName.setText(secondName);

       /* User clicks Register */
    public void clickRegister(View view) {

      startActivity(Intent(this, RegisterActivity.class))

     }
 ##########################################################

您的清单应如下所示

     <activity android:name="com.example.register.Register"/>

我正在努力理解您所说的主应用程序和注册是什么意思。 听起来好像它们是两个不同的应用程序,或者可能是两个不同的应用程序 项目模块。但是如果你想说的是 MainActivity 并且 RegisterActivity 那么以上方案应该可以解决你的问题。

你做错了什么:

不需要您试图在清单中解析的意图。如果我正确理解你想要达到的目标。 MainActivity 和 RegisterActivity 也是如此。您使用的是隐式意图而不是显式意图。并且在调用 findViewById 时不需要这个额外的 (EditText) 因为它是多余的。有关意图的更多信息,您可以查看 this

但是,本指南对任何试图将数据从一个 activity 解析到另一个的人应该有用。