I use this to open app from package name
startActivity(getPackageManager().getLaunchIntentForPackage("packagename"));
Many apps in android cannot be opened, because they are system package, not apps. These packages are not openable
e.g.
V/sys﹕ 0000000100010000011111001000101 : com.android.keychain : true : Key Chain
V/sys﹕ 0000000000000000000000000000001 : com.android.keychain : true : Key Chain
^
^
^
Log.v("sys", String.format("%31s", Integer.toBinaryString(pkgInfo.applicationInfo.flags)).replace(' ', '0') +" : "+ pkgInfo.packageName+" : "+(((pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ? true:false)+" : "+pkgInfo.applicationInfo.loadLabel(pm).toString());
Log.v("sys", String.format("%31s", Integer.toBinaryString(ApplicationInfo.FLAG_SYSTEM)).replace(' ', '0') +" : "+ pkgInfo.packageName+" : "+(((pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ? true:false)+" : "+pkgInfo.applicationInfo.loadLabel(pm).toString());
I use this method to filter out all systempackage
private boolean isSystemPackage(PackageInfo pkgInfo)
{
Log.v("sys", String.format("%31s", Integer.toBinaryString(pkgInfo.applicationInfo.flags)).replace(' ', '0') +" : "+ pkgInfo.packageName+" : "+(((pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ? true:false)+" : "+pkgInfo.applicationInfo.loadLabel(pm).toString());
Log.v("sys", String.format("%31s", Integer.toBinaryString(ApplicationInfo.FLAG_SYSTEM)).replace(' ', '0') +" : "+ pkgInfo.packageName+" : "+(((pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ? true:false)+" : "+pkgInfo.applicationInfo.loadLabel(pm).toString());
return ((pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ? true:false;
}
But this method cannot help me to determine which package is not system apps.
For example
this is whatsapp in LG g pro 2
V/sys﹕ 0000000110010000011111001000100 : com.whatsapp : false : WhatsApp
V/sys﹕ 0000000000000000000000000000001 : com.whatsapp : false : WhatsApp
this is in Note4
V/sys﹕ 0000000110010000011111011000101 : com.whatsapp : true : WhatsApp
V/sys﹕ 0000000000000000000000000000001 : com.whatsapp : true : WhatsApp
This is a special case, I don't understand why whatsapp in some device is system package
Another example
V/sys﹕ 0000000110110001011111011000101 : com.google.android.apps.plus : true : Google+
V/sys﹕ 0000000000000000000000000000001 : com.google.android.apps.plus : true : Google+
I know google+ is installed by default, so it is a system package, but it is in App Drawer.
So I think FLAG_SYSTEM that is not suitable to get all apps in android
How to get all apps which in App Drawer?
Update:
Now I use this way to get all apps
final Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resolveInfoList = pm.queryIntentActivities(intent, 0);
PackageManager pm = getPackageManager();
for(ResolveInfo ri : resolveInfoList)
{
String appName=ri.activityInfo.loadLabel(pm).toString();
Drawable icon=ri.loadIcon(pm);
Log.v("sys",ri.activityInfo.packageName +":" + appName);
}
But some information is still incorrect
Use the way, I can get correct app name, correct icon drawable and almost all of correct package name.
Package names still have some wrong.
For example, this is some output of above program
V/sys﹕ com.android.contacts:Contacts
V/sys﹕ com.android.contacts:Phone <<<<wrong
V/sys﹕ com.google.android.apps.plus:Photos <<<<wrong
V/sys﹕ com.google.android.apps.plus:Google+
You can see the package name is wrong, so my app will open wrong app (But the drawable icon is correct)
I have looked the source code of FAST launcher, org.ligi.fast.model.AppInfo. Our way to get package name is same.
How can I get the correct package name in this way?
I also tried
ri.resolvePackageName
ri.activityInfo.parentActivityName
ri.activityInfo.processName
But no one is work, some may make my app crash.
You can do it this way:
final Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
final List<ResolveInfo> resolveInfoList = ctx.getPackageManager().queryIntentActivities(mainIntent, 0);
for more details you might look into the source of this launcher:
https://github.com/ligi/FAST
Activities that want to be visible in the launcher have to specify a specific intent-filter.
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
You can use this with PackageManager to get a list of activities that can be launched.
List<ResolveInfo> list = packageManager.queryIntentActivities(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER), 0);
Related
i am writing an android application that showing all installed applications and apps permissions. I am writing this app. using kotlin. Is there any way to get all installed applications from package manager I AM NOT USING JAVA.
You can do something like this:
val packages = packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
for (packageInfo in packages) {
Log.d(TAG, "Package name:" + packageInfo.packageName)
}
You can also check this article to check how it works in Android 11:
https://proandroiddev.com/how-to-get-users-installed-apps-in-android-11-b4a4d2754286
val mainIntent = Intent(Intent.ACTION_MAIN, null)
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER)
val pkgAppsList = context.packageManager.queryIntentActivities(mainIntent, 0)
Using the below snippet you can get details of the installed app on a device
val packages: List<ApplicationInfo> =
pm.getInstalledApplications(PackageManager.GET_META_DATA)
for (packageInfo in packages) {
Log.d(
"log",
"Installed package :" + packageInfo.packageName
)
Log.d("log", "Source dir : " + packageInfo.sourceDir)
Log.d(
"log",
"Launch Activity :" + pm.getLaunchIntentForPackage(packageInfo.packageName)
)
}
This is already answered the question here in java. I just convert that into kotlin in IDE
Code->Convert java file to Kotlin
It works fine
I want to show all messaging apps installed by user in it's phone. The list I am expecting is like, WhatsApp, Facebook messenger, Viber, Slack, Skype, WeChat etc (If any installed). So, far I have tried getting all apps in Phone through this code:
val pm: PackageManager = context!!.packageManager
val i = Intent(Intent.ACTION_MAIN)
i.addCategory(Intent.CATEGORY_LAUNCHER)
val lst = pm.queryIntentActivities(i, 0)
for (resolveInfo in lst) {
Log.d(
"Test",
"New Launcher Found: " + resolveInfo.activityInfo.packageName
)
This only gives me Slack app but not other messaging apps. I have a feeling it has something to do with MIME types as mentioned in Google docs.
text/*, senders will often send text/plain, text/rtf, text/html, text/json
image/*, senders will often send image/jpg, image/png, image/gif
video/*, senders will often send video/mp4, video/3gp
but I don't know how to use this info. Any help would be appreciated. TIA!
add ACTION_SENDTOas action parameter while creating your intent and you should see the list of apps capable of handling messages/sms etc.
val intent = Intent(Intent.ACTION_SENDTO)
// get list of activities that can handle this type of intent
val lst = pm.queryIntentActivities(intent, 0)
Here pack name refers to - apps package name
fun appinstalled(){
var app_names = mutableListOf<String>()
val app_package = mutableListOf<String>()
val packagelist: MutableList<PackageInfo> = packageManager.getInstalledPackages(0)
var appname : String
var packname : String
for (i in packagelist.indices) {
val packageinfo : PackageInfo= packagelist[i]
appname=packageinfo.applicationInfo.loadLabel(packageManager).toString()
packname=packageinfo.packageName
app.add(appname)
app-package.add(packname)
}
this will the list of app installed in the user device as well as their package name . After this attach these list to the Listview and their adpater and all done.
Background
Apps use Intents to open other apps, sometimes with specialized Intents.
One example is this Intent, to choose a contact from WhatsApp:
val WHATSAPP_PACKAGE_NAME = "com.whatsapp"
val whatsAppPickIntent = Intent(Intent.ACTION_PICK).setPackage(WHATSAPP_PACKAGE_NAME)
This works fine in general. Same goes for when you wish to launch the app:
val launchIntent=packageManager.getLaunchIntentForPackage(WHATSAPP_PACKAGE_NAME)
The problem
Recently I was informed of a relatively new feature, allowing the user to have multiple instances of the same app. It might be available on other devices, but on OnePlus devices it's called "parallel apps". Here's an example of 2 instances of WhatsApp, each is assigned to a different phone number :
Thing is, this can break how Intents work with a single instance of the app. Now the Intent doesn't know for which app to go to. The launcher show 2 icons now for WhatsApp:
If you choose to launch WhatsApp via the normal launcher icon (the left one), it shows this dialog:
Works fine, but if you choose to use the picker intent, you still get this dialog, but when you choose an item, from the dialog, it doesn't let you really do anything with it (opens and closes the app), while showing a toast "The file format is not supported".
What I've tried
Since I don't have the device, I tried to read about it over the Internet, but I only found user-related information, such as these:
https://www.androidpolice.com/2017/08/04/new-oneplus-33t-open-beta-adds-parallel-app-support-run-multiple-instances-app/
https://www.techrepublic.com/article/how-to-run-cloned-versions-of-apps-with-oneplus-parallel-apps/
I've decided to try to investigate it further, by sending an APK to the person who told me about it, trying to see if the next code will work any different:
val whatsAppPickIntent = Intent(Intent.ACTION_PICK).setPackage(WHATSAPP_PACKAGE_NAME)
val queryIntentActivities: List<ResolveInfo> = packageManager.queryIntentActivities(whatsAppPickIntent, 0)
button2.setOnClickListener {
intent = Intent(Intent.ACTION_PICK)
val resolveInfo = queryIntentActivities[0]
toast("number of possible choices:" + queryIntentActivities.size)
intent.component = ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name)
startActivity(intent)
}
The toast that will be shown tells that I have only one thing that can handle the intent, and indeed when I use it, I get the same dialog for choosing which instance of it to use. And like in the original Intent, it fails with the same toast.
EDIT: Later I tried the next thing: I asked to show what are the ResolveInfo properties, before and after enabling the feature, by using this code:
val launchIntent = packageManager.getLaunchIntentForPackage(WHATSAPP_PACKAGE_NAME)
val whatsAppPickIntent = Intent(Intent.ACTION_PICK).setPackage(WHATSAPP_PACKAGE_NAME)
var queryIntentActivities: List<ResolveInfo> = packageManager.queryIntentActivities(whatsAppPickIntent, 0)
var sb = StringBuilder()
queryIntentActivities[0].dump(object : Printer {
override fun println(x: String?) {
if (x != null)
sb.append(x)
}
}, "")
val pickResult = "pick result:packageName:\"" + queryIntentActivities[0].activityInfo.packageName + "\" name:\"" + queryIntentActivities[0].activityInfo.name + "\"\n\n" + "extended:" + sb.toString()
sb = StringBuilder()
queryIntentActivities = packageManager.queryIntentActivities(launchIntent, 0)
queryIntentActivities[0].dump(object : Printer {
override fun println(x: String?) {
if (x != null)
sb.append(x)
}
}, "")
val launchResult = "launch result:packageName:\"" + queryIntentActivities[0].activityInfo.packageName + "\" name:\"" + queryIntentActivities[0].activityInfo.name + "\"\n\n" + "extended:" + sb.toString()
val body = pickResult + "\n\n" + launchResult
val emailIntent = Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", "", null))
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "whatsApp investigation")
emailIntent.putExtra(Intent.EXTRA_TEXT, body)
startActivity(Intent.createChooser(emailIntent, "Send email..."))
The result is that both are the same, as if everything is fine. Here's the result when it's turned on/off (exact same thing) :
pick result:packageName:"com.whatsapp" name:"com.whatsapp.ContactPicker"
extended:priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=falseActivityInfo: name=com.whatsapp.ContactPicker packageName=com.whatsapp enabled=true exported=true directBootAware=false taskAffinity=com.whatsapp targetActivity=null persistableMode=PERSIST_ROOT_ONLY launchMode=0 flags=0x3 theme=0x7f110173 screenOrientation=-1 configChanges=0xfb3 softInputMode=0x0 lockTaskLaunchMode=LOCK_TASK_LAUNCH_MODE_DEFAULT resizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ApplicationInfo: name=com.whatsapp.AppShell packageName=com.whatsapp labelRes=0x7f100473 nonLocalizedLabel=null icon=0x7f080c15 banner=0x0 className=com.whatsapp.AppShell processName=com.whatsapp taskAffinity=com.whatsapp uid=10099 flags=0x3 privateFlags=0x1010 theme=0x7f110164 requiresSmallestWidthDp=0 compatibleWidthLimitDp=0 largestWidthLimitDp=0 sourceDir=/data/app/com.whatsapp-NaKTLVhiNTh4zEGhFdkxrg==/base.apk seinfo=default:targetSdkVersion=26 seinfoUser=:complete dataDir=/data/user/0/com.whatsapp deviceProtectedDataDir=/data/user_de/0/com.whatsapp credentialProtectedDataDir=/data/user/0/com.whatsapp enabled=true minSdkVersion=15 targetSdkVersion=26 versionCode=452238 targetSandboxVersion=1 supportsRtl=true fullBackupContent=true category=4
launch result:packageName:"com.whatsapp" name:"com.whatsapp.Main"
extended:priority=0 preferredOrder=0 match=0x0 specificIndex=-1 isDefault=falseActivityInfo: name=com.whatsapp.Main packageName=com.whatsapp labelRes=0x7f10044c nonLocalizedLabel=null icon=0x0 banner=0x0 enabled=true exported=true directBootAware=false taskAffinity=com.whatsapp targetActivity=null persistableMode=PERSIST_ROOT_ONLY launchMode=0 flags=0x3 theme=0x0 screenOrientation=-1 configChanges=0xfb3 softInputMode=0x0 lockTaskLaunchMode=LOCK_TASK_LAUNCH_MODE_DEFAULT resizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ApplicationInfo: name=com.whatsapp.AppShell packageName=com.whatsapp labelRes=0x7f100473 nonLocalizedLabel=null icon=0x7f080c15 banner=0x0 className=com.whatsapp.AppShell processName=com.whatsapp taskAffinity=com.whatsapp uid=10099 flags=0x3 privateFlags=0x1010 theme=0x7f110164 requiresSmallestWidthDp=0 compatibleWidthLimitDp=0 largestWidthLimitDp=0 sourceDir=/data/app/com.whatsapp-NaKTLVhiNTh4zEGhFdkxrg==/base.apk seinfo=default:targetSdkVersion=26 seinfoUser=:complete dataDir=/data/user/0/com.whatsapp deviceProtectedDataDir=/data/user_de/0/com.whatsapp credentialProtectedDataDir=/data/user/0/com.whatsapp enabled=true minSdkVersion=15 targetSdkVersion=26 versionCode=452238 targetSandboxVersion=1 supportsRtl=true fullBackupContent=true category=4
So I wanted to check on something else: Try to put a widget-shortcut of WhatsApp (called "whatsApp chat"), that requires you to choose a contact, when this feature is turned on.
Turns out, it can't handle it well. It asks which app to create the widget to: the original or the clone. If you choose the original, all is fine. If you choose the clone, it adds the widget all fine and well, but when clicking on it, it goes to the main window of the app instead of going to the person.
The questions
How can I differentiate between the main instance and the "cloned" one? I mean, how can an Intent be directed to a single instance (the main one) of the targeted app? I ask this about both of the Intents I've presented (launch and picker).
How does this feature even work? Where does the private data of each instance gets saved now? Does each of them have a process, with a different name?
Do other devices of other OEMs have this feature? Does it work there the same way as here ?
Why do we see the toast message, if the user chose the app to target to? Is it maybe a buggy feature, that will work only for launch-intents?
Is there at least a way to know that a given app (given a package name of it) has this feature enabled for it?
I have the method below. It gets all the apps on a device and looks for particular ones by name: Hangouts, Skype, Viber, WhatsApp. All 4 are installed on a Motorola Droid MAXX running Android 4.4.4. and a Samsung SM-T530NU with 5.0.2.
On both devices, it does not find Hangouts. Any ideas why this is?
Output:
com.skype.raider/.Main m=0x108000} Intent filter: null
com.viber.voip/.WelcomeActivity m=0x108000} Intent filter: null
com.whatsapp/.Main m=0x108000} Intent filter: null
I removed the if condition and list all the apps and search by hand (so to speak). I saw nothing about hangouts, hang, ho, ...
public static List<ResolveInfo> getAllInstalledApps(Context context) {
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> appsList = context.getPackageManager().queryIntentActivities(mainIntent, 0);
for (ResolveInfo resolveInfo : appsList) {
String infoString = resolveInfo.toString();
if (infoString.contains("hangouts") ||
infoString.contains("skype") ||
infoString.contains("viber") ||
infoString.contains("whatsapp")) {
Log.i("getAllInstalledApps", resolveInfo.toString() + " Intent filter: " + resolveInfo.filter);
}
}
return appsList;
}
The app package name for Hangouts is actually com.google.android.talk. You should be looking for that. A tip for looking for package names is to go to the URL of the product page. It's part of the id query in the URL. For example, the URL for Google Hangouts is:
https://play.google.com/store/apps/details?id=com.google.android.talk
I am trying to develop an android application where i have the following requirement. Is there any way through code, i can get the list of apps installed on devices in debug mode.
Thanks in advance.
EDIT - I tried the following code.
PackageManager pm = getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (int i=0; i < packages.size(); i++)
{
if ((packages.get(i).flags & ApplicationInfo.FLAG_SYSTEM) == 1)
{
//This is for System applications
}
else
{
boolean isDebuggable = (0 != ( getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE ) );
if((pm.getLaunchIntentForPackage(packages.get(i).packageName)!=null) && (isDebuggable = true) )
{
// Only For Apps with debug mode set true, this line should get executed
// But this does not happens
}
}
}
Here you go,
Intent main = new Intent(Intent.ACTION_MAIN, null);
main.addCategory(Intent.CATEGORY_LAUNCHER);
List pkgAppsList = context.getPackageManager().queryIntentActivities( main, 0);
This should give you enough information in order to kick off an application.
I tried various methods but as per my understanding, we cannot get the list of apps in debug mode seperately.
By using the flags, we can only get for the app which has this code and not other apps running on device.
Thanks anyways. If anybody has a different thought, please let me know.
From Justin's answer
Kotlin
val allIntent = Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER)
val allApps = packageManager.queryIntentActivities(allIntent, 0)
val debugApps = arrayListOf<ActivityInfo>()
allApps.forEach {
val appInfo = (packageManager.getApplicationInfo(
it.activityInfo.packageName,
0
))
if (0 != appInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) {
debugApps.add(it.activityInfo)
}
}
debugApps.forEach {
Log.d("debugApps", it.packageName)
}
It is possible to get all the apps that are in debug mode.
In my device, I get all the apps that I've installed using Android studio.