Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass Android intent to anyone but my own app?

I have a certain intent (NDEF_DISCOVERED), some of which I cannot handle correctly, so I want to redirect those to android's default nfc handler.

So i take the intent, setComponent(null), and then startActivity(intent)

But.. it always comes back to my app in an infinite loop of intent throwing.

Is there a way I can send off an intent to anyone but my app? Or send it to android's default nfc handler?

EDIT: So I used vikram's answer to query the packagemanager for possible activities to handle my intent, then looped thru and found the activity with the highest priority (who isn't me) and sent an explicit intent to them.

like image 236
ginsunuva Avatar asked Jul 25 '13 18:07

ginsunuva


People also ask

How do I send intent from one app to another?

Intent shareIntent = Intent. createChooser(sendIntent, null); startActivity(shareIntent); Optionally, you can add extras to include more information, such as email recipients ( EXTRA_EMAIL , EXTRA_CC , EXTRA_BCC ), the email subject ( EXTRA_SUBJECT ), and so on.

How can two different android applications interact?

Using intents even allows your app to start an activity that is contained in a separate app. An Intent can be explicit in order to start a specific component (a specific Activity instance) or implicit in order to start any component that can handle the intended action (such as "capture a photo").

Can an android app launch another app?

In android, we can lunch other applications using packing name. This example demonstrate about How to Launch an application from another application on Android. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project.


2 Answers

A custom chooser dialog/popup will be better for you in this case. Instead of launching an intent, use the PackageManager to queryIntentActivities(Intent, int). From the List<ResolveInfo> that queryIntentActivities(Intent, int) returns, filter out your own app using the packageName:

String packageName = "";
for(ResolveInfo resInfo : resolvedInfoList) {

    packageName = resInfo.activityInfo.applicationInfo.packageName;

    // Exclude `packageName` from the dialog/popup that you show

}

Edit 1:

The following code will create and show a PopupWindow whenever showList() is called. The xml layout file used to return popupView contains nothing but a LinearLayout(R.layout.some_popup_view):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/llPopup"
    android:orientation="vertical" >

</LinearLayout>

This code is just a simple demonstration. For it to be anything close to usable, you will probably need to add a ListView with a custom adapter to this PopupWindow. In the OnClickListener for the ListView, you will retrieve the package name of the Application that the user clicks on, and generate an intent to start that activity. As of now, the code only displays how to filter out your own application using a custom chooser. In the if block, replace "com.example.my.package.name" with your app's package name.

public void showList() { 

    View popupView = getLayoutInflater().inflate(R.layout.some_popup_view, null);

    PopupWindow popupWindow = new PopupWindow(popupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

    LinearLayout llPopup = (LinearLayout) popupView.findViewById(R.id.llPopup);

    PackageManager pm = getPackageManager();

    Intent intent = new Intent();

    // In my case, NfcAdapter.ACTION_NDEF_DISCOVERED was not returning anything
    //intent.setAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
    intent.setAction(NfcAdapter.ACTION_TECH_DISCOVERED);

    List<ResolveInfo> resolvedInfoList = pm.queryIntentActivities(intent, 0);

    String packageName = "";

    for(ResolveInfo resInfo : resolvedInfoList) {

        packageName = resInfo.activityInfo.applicationInfo.packageName;

        // Exclude `packageName` from the dialog/popup that you show
        if (!packageName.equals("com.example.my.package.name")) {

            TextView tv = new TextView(this);

            tv.setText(packageName);

            llPopup.addView(tv);
        }            

    }

    popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);
}
like image 181
Vikram Avatar answered Sep 18 '22 12:09

Vikram


there is also another option than to do a own chooser here ( different looking chooser might confuse the user )

public void rethrowIntentExcludingSelf() {
    final ComponentName component = new ComponentName(this, getClass());
    this.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

    final Intent intent = this.getIntent();
    intent.setComponent(null);
    this.startActivity(intent);
    new android.os.Handler().postDelayed(
            new Runnable() {
                @Override
                public void run() {
                    getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
                }
            },250);
}

I am using it - and it works fine - just do not like this magic constant 250 - but do not yet see another way.

like image 38
ligi Avatar answered Sep 17 '22 12:09

ligi