【问题标题】:Two apps communicating using Intent, passing data两个应用程序使用 Intent 进行通信,传递数据
【发布时间】:2020-04-20 22:24:36
【问题描述】:

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

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

注意Register活动不是Register活动中的主要活动。 我想在没有额外课程和广播的情况下解决这个问题。

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

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

ManifestRegister 活动在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活动中的代码,点击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();
}

我在这里卡住了。 希望听到对此主题的任何澄清,以及解决方案的示例也很棒。

谢谢!

【问题讨论】:

    标签: java android android-intent


    【解决方案1】:

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

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

    要宣传您的应用可以接收哪些隐式 Intent,请使用清单文件中的一个元素为您的每个应用组件声明一个或多个 Intent 过滤器。

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

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

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

    参考:

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

    有关使用意图发送/接收数据的更多信息。


    这是一个示例代码:

    第一个应用程序的主要活动

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

    第二个应用程序的接收器活动(在这种情况下,您的注册应用程序) 注意:如您所愿,这不是主要活动

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

    编码愉快!


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

    【讨论】:

    • 我很高兴它对你有用。我想指出的是,这种方法会产生对意图的永久调用。我建议你完成当前的活动。这应该会有所帮助:stackoverflow.com/questions/5000787/…
    • 这就是我要找的,非常感谢!
    【解决方案2】:

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

    /* 用户在注册活动中点击发回 */

    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

    但是,本指南对任何想要将数据从一个活动解析到另一个活动的人都应该有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      相关资源
      最近更新 更多