Два приложения общаются с помощью Intent, передавая данные - PullRequest
2 голосов
/ 21 апреля 2020

Я пытаюсь решить проблему передачи данных между различными приложениями с помощью Intent. Сценарий выглядит следующим образом:

  1. Main (приложение 1): пользователь нажимает Register
  2. Main Приложение запускает Register действие (форма) в Register (Приложение 2)
  3. Пользователь вводит имя, фамилию и т. Д. c, нажимает Send Back
  4. Register приложение, возвращающее значения в Main приложение
  5. * Приложение 1020 * отображает данные пользователя

Обратите внимание, что Register активность не является основной деятельностью в Register активности. Я хотел бы решить эту проблему без дополнительного класса и без Broadcasting.

Мой код для основного приложения, пользователь нажимает метод регистрации:

    /* 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 активности в 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();
}

И вот я застрял. Хотелось бы услышать какие-либо разъяснения по этому топи c, и пример решения также будет отличным.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 21 апреля 2020

В первом приложении добавьте intent-filter для получения данных из второго приложения, которое является вашим Register приложением. Теперь сделайте то же самое с вашим Register приложением, нам нужно сделать это, чтобы мы могли вызвать его из нашего первого приложения.

intent-filter существует, чтобы гарантировать, что мы можем отправлять данные обратно. Согласно https://developer.android.com/guide/components/intents-filters:

Чтобы объявить, какие неявные намерения может получить ваше приложение, объявите один или несколько фильтров намерений для каждого из компонентов вашего приложения с элементом в файле манифеста .

В первом приложении создайте 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>

Удачного кодирования!


Редактировать: я добавил пояснения к своему ответу.

0 голосов
/ 21 апреля 2020

Ваш RegisterActivity должен выглядеть так, что RegisterActivity выполняет синтаксический анализ данных пользователя для MainActivity

/ * Клики пользователя Send Back в активности реестра * /

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 должна выглядеть так. MainActivity отвечает за получение данных. Эта строка кодов должна вызываться в вашем методе MainCctivity 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"/>

Я пытаясь обернуть голову вокруг того, что вы имели в виду под Main App и Register. Звучит так, как будто это два разных приложения или, возможно, два разных модуля проекта. Но если вы пытаетесь сказать, что это MainActivity и RegisterActivity, то вышеупомянутое решение должно решить вашу проблему.

Что вы сделали не так:

То, что вы намереваетесь пытаться разобрать в манифесте не было необходимости. Если я правильно понял, что вы пытаетесь достичь. То же самое касается MainActivity и RegisterActivity. Вы использовали неявное намерение вместо явного намерения. И при вызове findViewById этот дополнительный (EditText) не понадобился, потому что он избыточен. Подробнее о намерениях вы можете узнать this

Тем не менее, это руководство должно быть полезно всем, кто хочет анализировать данные из одного действия в другое.

...