Get list of installed apps (package names) which accept a specific intent

moster67

Expert
Licensed User
Longtime User
Hi,

is there a way to get a list of installed apps (package names) which accept a specific intent?

For instance, I would like to get the package-names of all installed apps (on a phone/tablet) that can run or handle the following intent:

B4X:
Intent i = new Intent("android.intent.action.VIEW");
i.setDataAndType(uri, "video/*");
//uri is a hyper-link

This is similar to what Android does when you click on a video-file (for instance) and Android shows you a list of apps you can use for playing the video.

Thanks.
 
Last edited:

moster67

Expert
Licensed User
Longtime User
Thanks NJ.

The example you indicated gives a good idea what needs to be done however I am unsure how to get it right using the reflection-library:

I changed it slightly to fit my needs :

B4X:
Sub Activity_Create(FirstTime As Boolean)
    Dim in As Intent
    In.Initialize(In.ACTION_VIEW, "http://www.pocketjourney.com/downloads/pj/video/famous.3gp")
    In.SetType("video/*")
    Log(FindDefaultApp(in))
End Sub

Sub FindDefaultApp(In As Intent) As String
    Dim r As Reflector
    r.Target = r.GetContext
    Dim pm As Object
    pm = r.RunMethod("getPackageManager")
    r.Target = pm
    Dim mInfo As Object
    mInfo = r.RunMethod4("resolveActivity", Array As Object(In, 0), _
        Array As String("android.content.Intent", "java.lang.int"))
    If mInfo = Null Then Return "" 'no activity found
    r.Target = mInfo
    r.Target = r.GetField("activityInfo")
    r.Target = r.GetField("applicationInfo")
    Return r.GetField("packageName")
End Sub

but all it returns is the word "Android" :(

I tried it using the example in the other post i.e.

B4X:
Dim in As Intent
in.Initialize(in.ACTION_VIEW, "http://www.google.com")
Log(FindDefaultApp(in))

and expected to get various browsers such as as Chrome and others but it only returned one (default). Reading the documentation, it seems like resolveActivity only returns the default app in case of multiple choices. Therefore I am unsure if said code will work for me since I need to get all package-names of compatible apps. :confused:

It should be said that I don't know much about the inner workings of intents and so forth so I might be wrong.

:sign0163:
 
Upvote 0

moster67

Expert
Licensed User
Longtime User
:BangHead::BangHead:

I tried as suggested (forcing by using "in.WrapAsIntentChooser") but I get the word "Android" as a result.

I had a look at StackOverFlow and found a reply as this:

AFAIK there is no way to list all intents that a specific application can receive. However, you can get similar (albeit not as expansive) information by creating some intents yourself then using PackageManager's queryIntentActivities, queryIntentservices, and queryBroadcastReceivers to see what applications are installed that will react to that intent.

I had a look at official docs and found this:

public abstract List<ResolveInfo> queryIntentActivities (Intent intent, int flags)

Added in API level 1
Retrieve all activities that can be performed for the given intent.

Parameters
intent The desired intent as per resolveActivity().
flags Additional option flags. The most important is MATCH_DEFAULT_ONLY, to limit the resolution to only those activities that support the CATEGORY_DEFAULT.
Returns
A List<ResolveInfo> containing one entry for each matching Activity. These are ordered from best to worst match -- that is, the first item in the list is what is returned by resolveActivity(Intent, int). If there are no matching activities, an empty list is returned.
See Also
MATCH_DEFAULT_ONLY
GET_INTENT_FILTERS
GET_RESOLVED_FILTER

I tried to implement it but I couldn't get this to work although I think this might be the solution. :BangHead:

:sign0163:
 
Last edited:
Upvote 0

Rusty

Well-Known Member
Licensed User
Longtime User
I am trying to start an application from within my app using an intent.
How can I find the package name for the installed app I'm trying to start.
For example, I would like to start PDF viewer directly, such as MyLibrary or Adobe Reader. I do not want the user to have to select from a list of PDF viewers that are installed.

B4X:
Try
        Dim Intent1 As Intent
        Dim pm As PackageManager
        Intent1 = pm.GetApplicationIntent (com.package.tolaunch)
        StartActivity (Intent1)
    Catch
          ToastMessageShow ("Failed to launch app!  Is it installed?", True)
    End Try
I've grabbed the above code from the B4A site, but don't know what the package name is for either of the two applications mentioned.
How can I find the package names for these?
Thanks,
Rusty
 
Upvote 0

moster67

Expert
Licensed User
Longtime User
Hola...you are hijacking my thread :)

You could probably use the code indicated by NJDude since it will give you the default app.

Use this intent instead to find the default-app for PDF-files:

B4X:
Dim i As Intent
i.Initialize(i.ACTION_VIEW,"/mnt/sdcard/Data/DailyProd.pdf")
i.SetType("application/pdf")
 
Upvote 0

Rusty

Well-Known Member
Licensed User
Longtime User
Sorry, I thought it was relevant to the discussion. :)
thanks for the suggestion.
 
Upvote 0

moster67

Expert
Licensed User
Longtime User
success

I couldn't get it to work with reflection so I did a library instead. If anyone is interested, here is the source:

B4X:
package test.b4a.utility;

import java.util.List;
import android.content.Context;
import android.content.Intent;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.BA;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import anywheresoftware.b4a.BA;

@BA.ShortName("myutilities")
@Version(1.08F)

public class myutilities {
   
   
 public anywheresoftware.b4a.objects.collections.List GetPackageInfo(BA ba,Intent myintent)
 {
   anywheresoftware.b4a.objects.collections.List PackageList = new anywheresoftware.b4a.objects.collections.List();
   Context mycontext = BA.applicationContext;
   PackageList.Initialize();

   Intent externalintent= new Intent(myintent);
   PackageManager packman = mycontext.getPackageManager();
   List<ResolveInfo> list = packman.queryIntentActivities(externalintent, 0);
   if (list.size() > 0 ){
      for (int i = 0; i < list.size(); i++) {
        ResolveInfo info = (ResolveInfo)list.get(i);
        CharSequence AppName = info.loadLabel(packman);
       String[] packageinfo = { info.activityInfo.packageName, AppName.toString() };
        PackageList.Add(packageinfo);
   }
   }
   return PackageList;
 }
 
}

Then you can use it from B4A as follows:

B4X:
Sub Activity_Create(FirstTime As Boolean)
    Dim in As Intent
    In.Initialize(In.ACTION_VIEW, "http://www.pocketjourney.com/downloads/pj/video/famous.3gp")
    In.SetType("video/*")
    FindApps(in)
End Sub

Sub FindApps(In As Intent) As String
    Dim testing As myutilities

   Dim mylist As List
   mylist.Initialize
   mylist=testing.GetPackageInfo(In)
   
   If mylist.Size=0 Then
      Log("nothing found")
      Return
   End If
   
   For i=0 To mylist.Size -1
      Dim info() As String
      info = mylist.Get(i)
      Log("Package-name: " &  info(0))
      Log("appname: " &  info(1))
   Next
End Sub

In this way, I can get a list of installed apps which are able to handle a specific intent. I can let users select the app they want from a list/spinner and then launch it.

I am still curious though how I could obtain the same thing using Reflection (if possible) - it would surely be a better solution. :BangHead:
 
Last edited:
Upvote 0

INALAMBRIK

Member
Licensed User
Longtime User
Great

Hi Moster67. Your library works great, it solved me a big issue. I modified a little to retrieve just the packages with an ACTION_MAIN intent filter.

B4X:
/*
      * Get a list of applications that have an ACTION_MAIN intent filter
      */
     public anywheresoftware.b4a.objects.collections.List GetPackageInfo(BA ba)
     {
       anywheresoftware.b4a.objects.collections.List PackageList = new anywheresoftware.b4a.objects.collections.List();
       Context mycontext = BA.applicationContext;
       PackageList.Initialize();
       
       PackageManager packman = mycontext.getPackageManager();
       Intent intent = new Intent(Intent.ACTION_MAIN, null);
       intent.addCategory(Intent.CATEGORY_LAUNCHER);
       List<ResolveInfo> list = packman.queryIntentActivities(intent, PackageManager.PERMISSION_GRANTED);
       if (list.size() > 0 ){
           for (int i = 0; i < list.size(); i++) {
             ResolveInfo info = (ResolveInfo)list.get(i);
             CharSequence AppName = info.loadLabel(packman);
            String[] packageinfo = { info.activityInfo.packageName, AppName.toString() };
             PackageList.Add(packageinfo);
       }
       }
       return PackageList;
     }

Thanks,
 
Upvote 0
Top