2

I'm trying to solve an issue passing data between different apps using Intent. The scenario is like this:

  1. Main (App 1): User clicks Register
  2. Main App launches Register activity (form) in Register (App 2)
  3. User enters first name, last name etc, clicks Send Back
  4. Register app returning values to Main app
  5. Main app displays user's data

Note that Register activity is not the main activity in Register activity. I would like to solve this without an additional class and without Broadcasting.

My code for Main App, user clicks Register method:

    /* 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 file for Register activity in Register App:

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

Now, this is the code in Register activity, of click Send Back method:

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

And here I'm stuck. Would love to hear any clarification for this topic, and a example for a solution would also be great.

Thanks!

Palantiir
  • 55
  • 5

2 Answers2

3

In the first app, add an intent-filter to receive data back from the second app, which is your Register application. Now, do the same with your Register application, we need to do this so that we can invoke it from our first app.

The intent-filter is there to make sure that we can send data back. According to 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.

From the first app, create an Intent that will bring you to the second app. If you don't want to open up the Android share sheet then I suggest you use a PackageManager that gets all the activities that can receive your data and then find in the list your second app and open it with setComponent() with your intent. (Check my code below)

On to our second app, do the same as you did in the first app but now you can add your extras or data like first name and second name.

Back to our first app, write code that will receive the incoming intent from our second app and there, done!

Refer to:

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

for more information about sending/receiving data with intents.


Here's a sample code:

First Application's Main 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();
    }
}

First Application's Manifest

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

Second Application's Receiver Activity (In this case, your Register app) Note: as you want, this is NOT the main 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();
    }
}

Second Application's Manifest

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

Happy coding!


Edit: I added explanation to my answer.

  • 1
    I'm glad it worked out for you. I want to note that this method however will create a perpetual call on intents. I suggest you to finish the current activity. This should help: https://stackoverflow.com/questions/5000787/how-to-finish-current-activity-in-android – ドラゴンハートゼクモル Apr 22 '20 at 19:22
  • This is what I am looking for, Thank you so much! – MaKi Mar 25 '21 at 07:16
0

Your RegisterActivity should look like so RegisterActivity is parsing the user data to the MainActivity

/* User clicks Send Back in register 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);

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

Your MainActivity should look like so. The MainActivity is responsible for receiving the data This line of codes should be called in your onCreate method of MainActivity

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

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

Your manifest should look like this

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

I am trying to wrap my head around what you meant by Main App and Register. It sound as though they are two different apps or probably two different project modules. But if what you are trying to say is MainActivity and RegisterActivity then the above solution should be able to fix your problem.

What you did wrong:

That intent you were trying to parse in the manifest was not needed. If I understood properly what you are trying to achieve. The same goes for the MainActivity and RegisterActivity. You were using Implicit Intent instead of explicit Intent. And when calling findViewById this extra (EditText) was not needed because it is redundant. For more on the intent you can check this

However, this guide should be useful to anyone seeking to parse data from one activity to another.