I'm trying to list all apps in android device with queryIntentActivities method but the list doesn't return all the apps , It returns only three of them. Here is my code:
PackageManager packageManager = getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> allApps = packageManager.queryIntentActivities(intent, 0);
for (ResolveInfo ri : allApps) {
Log.d("Labels", String.valueOf(ri.loadLabel(packageManager)));
}
is there anyone now why it returns only 3 applications ?
You are most likely trying to do this on Android 11. Make sure you add the <uses-permission android:name"android.permission.QUERY_ALL_PACKAGES"> permission to the AndroidManifest.xml file.
While I haven't tested this aspect of R DP2 yet, it appears that your
app now can't find out what other apps are installed, on a general
basis. The cited example is queryIntentActivities(), but to make this
really work you would need to seriously lobotomize PackageManager. You
can whitelist certain packages and certain structures
to try to get by this for certain use cases. And, this is where the
mysterious QUERY_ALL_PACKAGES permission seen in DP1 comes into play —
this permission removes these new restrictions. Given the "look for
Google Play to provide guidelines for apps that need this permission"
caveat, it is safest to assume that if you try using it, eventually
you will be banned from the Play Store by a bot.
Related
I'm trying to get every launchable applications in my device using this method:
apps = new ArrayList<>();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> availableActivities = manager.queryIntentActivities(intent, 0);
for(ResolveInfo ri:availableActivities){
AppDetail app = new AppDetail();
app.label = ri.loadLabel(manager);
app.name = ri.activityInfo.packageName;
app.icon = ri.activityInfo.loadIcon(manager);
apps.add(app);
}
I tried to print the label and package name of those application and found this:
Contacts com.sonyericsson.android.socialphonebook
Phone com.sonyericsson.android.socialphonebook
They have different app label yet the same package name. When I tried to open the apps, both of them open Contact app.
Is there any way to differentiate them? Or did I use a wrong method to get list of application?
queryIntentActivities retrieves all activities that can be performed for the given intent. So it can returns activites info with same package name.
I believe that Phone and Contacts are the same Contact app.
Two different icons can be created for the same program, one for each different activity. This makes sense, since the MAIN/LAUNCHER intent filter essentially tells android that the activity is the app's starting activity. So if you add this filter to two activities it will give you two icons for the same app to enter different activities. Nothing in android's intent filter model forces each app to have one and only one starting activity.
I've integrated some library from the third party into my android app.
They use background service with the location, but it caused java.lang.IllegalStateException error since Android 8 has updated the background location limits.
I've tried to add the following lines to avoid the error but it fails:
if(Build.VERSION.SDK_INT <= 25) { // below Android 8.0
PushAd.startPush(activity);
}else{
PushAd.disablePush(activity);
}
dependencies {
implementation 'com.adlocus:library:3.5.7#aar'
}
Can I delete or remove the library, or stop the service in the main activity programmatically?
[Solved]
I discovered a possible solution to solve the problem, we can use PackageManager to enable/disable a Service/Receiver/Activity from third party library.
ComponentName component = new ComponentName(context, MyReceiver.class);
context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED , PackageManager.DONT_KILL_APP);
Thanks Varun's answer.
Can I delete or remove the library... programmatically?
No.
Can I... stop the service in the main activity programmatically?
Possibly. Ask the developers of the library.
I've tried to add the following lines to avoid the error but it fails
Nobody knows what "it fails" means. Contact the developers of the library and ask them how to use it with Android 8.0+ devices.
I discovered a possible solution to solve this problem, we can use PackageManager to enable/disable a Service/Receiver/Activity from third party library.
ComponentName component = new ComponentName(context, MyReceiver.class);
context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED , PackageManager.DONT_KILL_APP);
Thanks Varun's answer.
Because I want to make sure the MediaStore has the latest information without having to reboot I'd like to trigger the MediaScanner using the popular way I found on SO
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())));
This works fine on my Samsung S2 w/ICS but not on my Nexus 7 w/JellyBean. Logcat shows this on my Nexus 7:
WARN/ActivityManager(480): Permission denied: checkComponentPermission() owningUid=10014
WARN/BroadcastQueue(480): Permission Denial: broadcasting Intent { act=android.intent.action.MEDIA_MOUNTED dat=file:///storage/emulated/0 flg=0x10 } from com.example.foo.bar (pid=17488, uid=10046) is not exported from uid 10014 due to receiver com.android.providers.downloads/.DownloadReceiver
INFO/ActivityManager(480): Start proc com.google.android.music:main for broadcast com.google.android.music/.store.MediaStoreImportService$Receiver: pid=17858 uid=10038 gids={50038, 3003, 1015, 1028}
INFO/MusicStore(17858): Database version: 50
INFO/MediaStoreImporter(17858): Update: incremental Added music: 0 Updated music: 0 Deleted music: 0 Created playlists: 0 Updated playlists: 0 Deleted playlists: 0 Inserted playlist items: 0 Deleted playlist items: 0 Removed orphaned playlist items: 0
The last line sounds encouraging in theory, but the values are always 0 even after new files had been pushed to the SD card (via adb push). On my older device (S2) it does remount the SD card.
I've added the following permissions to my AndroidManifest.xml but it behaves the same as without those permissions:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Any ideas/alternatives?
Edit 1:
Note that I don't know any file paths of new or modified or deleted files. I just want to make sure the MediaStore is up-to-date.
Here's the sample code based on CommonsWare's answer:
MediaScannerConnection.scanFile(activity, new String[]{path}, null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(final String path, final Uri uri) {
Log.i(TAG, String.format("Scanned path %s -> URI = %s", path, uri.toString()));
}
});
Even though in most of the cases, where one knows the files to be added/updated/etc. to the MediaStore, one should follow CommonsWare's answer, I wanted to post the my solution where I need to do it the rough way because I don't know the file paths. I use this mostly for testing/demoing:
Uri uri = Uri.fromFile(Environment.getExternalStorageDirectory());
activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, uri));
BTW, no permissions are necessary for either solution.
using the popular way I found on SO
Faking ACTION_MEDIA_MOUNTED broadcasts has never been an appropriate solution IMHO.
Any ideas/alternatives?
Use MediaScannerConnection, such as via its scanFile() static method.
My answer is a little late, but it might help those, who save a new file, and would like to extend the media store by just that file on Android Kitkat: On Android Kitkat the intent ACTION_MEDIA_MOUNTED is blocked for non-system apps (I think, because scanning the whole filesystem is pretty expensive). But it is still possible to use the intent ACTION_MEDIA_SCANNER_SCAN_FILE to add a file to the media store:
File f = new File(path to the file you would like to add to the media store ...);
try {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(f);
mediaScanIntent.setData(uri);
sendBroadcast(mediaScanIntent);
} catch(Exception e) {
...
}
How would I implement expansion packs on the market? Like if I wanted users to be able to purchase more images, how would I do that and also have the main app recognize and load those images? Are there any tutorials you can point me to? I searched using Google but didn't find anything very specific and beginner friendly. Most were in regards to in app billing but that's not what I'm looking for.
You can use PackageManager to look for your expansion packs. The exact way in which you would identify your expansion packs depends on how you're going to use them.
For example, if your expansion packs are runnable in some way - i.e., they all have a main activity - then you'd probably have a custom intent action, and you'd use PackageManager.queryIntentActivities() to give you a list of installed activities that can handle that action.
If these expansion packs are providing just resources and not code, you can choose to either have a "dummy" component that you can identify by intent as detailed above - even if you have no intent of ever running it - or you can look for another approach. For example, if no one but you will be making these expansion packs, you may simply identify them by package name.
PackageManager pm = getPackageManager();
List<PackageInfo> packages = pm.getInstalledPackages();
for(PackageInfo package : packages) {
if(package.packageName.startWith("com.myapp.extension.") {
// found an extension package!
handleExtensionPackage(package);
}
}
If you need to load a resource from an extension package, you'll need to create a context for that package, look up the resource identifier, and then load the resource.
Context extensionContext = createPackageContext(package.packageName, 0);
Resources extensionResources = extensionContext.getResources();
int r_drawable_pic = extensionResources.getIdentifier("drawable/pic", null, package.packageName);
Drawable remotePic = extensionResources.getDrawable(r_drawable_pic);
I'm planning on doing a application for Android 2.1 that changes song every minute (through what I hope exists in Android, "next") for the application using the audio device atm.
So if I have Spotify running in background already, playing music, can I through my program change to the next track?
Let me know if I was unclear about anything.
Thanks in advance!
I know this is a bit old question, but it took me some time searching something other then what is mentioned here.
There is a workaround - broadcasting media button action. There is one catch - receiver can recognize if the broadcast was from system or from another app, so they can ignore the non-system broadcasts.
Intent i = new Intent(Intent.ACTION_MEDIA_BUTTON);
synchronized (this) {
i.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT));
sendOrderedBroadcast(i, null);
i.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT));
sendOrderedBroadcast(i, null);
}
There's no universal audio transport API for music applications, so you'd need to see if the music applications you're targeting publicly expose service bindings or intents. If not, you won't be able to do this.
Just posted a relevant answer here
Using the AudioManager's dispatchMediaKeyEvent() method with a defined KeyEvent worked for me using the latest SDK.
The system music homescreen widget sends this intent for the built-in music player:
final ComponentName serviceName = new ComponentName(context,
MediaPlaybackService.class);
intent = new Intent(MediaPlaybackService.NEXT_ACTION);
intent.setComponent(serviceName);
pendingIntent = PendingIntent.getService(context,
0 /* no requestCode */, intent, 0 /* no flags */);
views.setOnClickPendingIntent(R.id.control_next, pendingIntent);
But it looks like this might take some hackery to implement outside packages in the music app itself because the MediaPlaybackService only accepts explicit Intents and isn't accessible from the outside. This thread seems to indicate it's possible with a bit of hackery, though.
But even then, as Roman said, not every music player will respect that Intent. You'll have to check with Spotify/Pandora/Last.fm themselves and see if they have any available intents to bind like that.
Looks that it's possible to use AudioManager to inject media keys.
Here is a snippet from another question
this.mAudioManager = (AudioManager) this.context.getSystemService(Context.AUDIO_SERVICE);
long eventtime = SystemClock.uptimeMillis();
KeyEvent downEvent = new KeyEvent(eventtime, eventtime, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT, 0);
mAudioManager.dispatchMediaKeyEvent(downEvent);
KeyEvent upEvent = new KeyEvent(eventtime, eventtime, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT, 0);
mAudioManager.dispatchMediaKeyEvent(upEvent);
The same way you can inject PlayPause button and some others.
I've tested it within a background service controlling Youtube and it worked for Android 6