Pinning Multiple Files To Home Screen In Oreo - android

My app which pins multiple files at once on the home screen used to work pretty fine till Nougat. But Google changed internals in Oreo so those old methods of pinning shortcuts don't work but a new ShortcutManager class has been introduced. Read here.
Now even if I try, I can't pin multiple shortcuts at once using this class. I apply a loop and calls the defined method to requestPinShortcuts but it only accepts only one shortcut and ignores others. So I wonder if I missed something in the documentation. Is there some way out?

Document:ShortcutManager
It's up to the launcher to decide how to handle previous pending requests when
the same package calls this API multiple times in a row. One possible strategy
is to ignore any previous requests.
If adding pin shortcuts in loop, launcher may only accept 1st or latest request. It depends on devices. So the question is going to how launcher recognize different request window. It is recognize by different foreground component. If different foreground components sending request, launcher accept all requests. Even it is almost send in the same time.
Some launchers may not show dialog to ask if user agree adding shortcuts. Some launcher show dialog. Even you sends multiple requests, user may not have enough time to agree all your requests.

Related

How do I issue conversation notifications on Android 11, if I already have published 5 shortcuts?

According to “People and conversations”, one of the prerequisites for a conversation notification on Android 11 is the following:
The notification is associated with a valid long-lived dynamic or cached sharing shortcut. The notification can set this association by calling setShortcutId() or setShortcutInfo().
But I can only have 5 shortcuts. Does this mean that I can't make conversations notifications for more than 5 people?
It appears that you can actually publish more than 5 shortcuts. You can make notifications which would rank lower than all others by setting rank to a high number, and publish them using shortcutManager.pushDynamicShortcut().
In case you don't have any launcher shortcuts, the above action will create one. If you don't want that, it's recommended to... simply remove the shortcut you just created:
Q: Will my shortcuts appear in the long press app launcher context menu?
A: They can depending on their rank, but if you prefer not having shortcuts appear on launcher you can remove the shortcut with ShortcutManager#removeDynamicShortcuts() or #removeAllDynamicShortcuts() after sending the notification. You can also rank other app shortcuts with higher ranking, so only those dynamic shortcuts appear on launcher.
Some thoughts follow below. It appears that shortcuts on a regular phone will appear in three places:
launcher— either by long pressing app icon, or pinned;
direct share;
conversation notifications.
These shortcuts all come from the same pool. It makes sense, but as there is only a single rank for every shortcut this means that the launcher list and the direct share list are the same. This is something you might not want; you might be sharing more to one conversation but opening another one more often. In my app, I solved this in the following way:
I maintain statistics of when the user shares to a contact / opens a chat with a contact
Whenever the list of top used/top shared contacts change, I update the shortcut using shortcutManager.pushDynamicShortcut(); if a shortcut with the same id already exists, it is updated. I use the old details from shortcutManager.getShortcuts().
depending on whether a shortcut becomes or ceases to become a direct share target, I set or unset a category
specifying rank allows reordering shortcuts in the launcher
Whenever I need to push a notification, I check if I already have a shortcut for the conversation. If not, I simply create a new one with a rank of 10000.
This allows having completely different launcher & direct share shortcuts, and to publish many a conversation notification.
Some random observations:
Adding a shortcut id to a conversation notification also adds its icon to the notification, even if you don't set one explicitly.
shortcutManager.maxShortcutCountPerActivity actually returns 15 (!) on my device (LineageOS), even though the launcher & direct share only show the regular 4 icons.
If you update a shortcut name and/or icon, most of the time it will instantly update in launcher. This includes pinned shortcuts.
Use IconCompat.createWithAdaptiveBitmap() to create icons that work well for various icon shapes. The system will keep a hold of the image, you don't need to keep it. See the documentation for that method.
There are two other methods to be aware of:
IconCompat.createWithAdaptiveBitmapContentUri() is the same as the above but will work with content URIs. This is good for creating Person for notifications, as this allows not keeping the icons in memory. However, there is seemingly no way to pass URI permissions to shortcut manager, so this method can't be used. (Please correct me if I'm wrong here!)
Edit: if you cancel the notification after inline (direct) reply, the system might decide to add your reply to it instead of actually cancelling it. Apparently it might lose URI permissions at this point. Calling this workaround on URIs seems to be helping:
fun Uri.grantReadPermissionToSystem() {
applicationContext.grantUriPermission("com.android.systemui", this,
Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
IconCompat.createWithData() creates memory efficient icons from compressed image data (PNG/JPEG). It's not adaptive, however. And, icons made with it don't work with ShortcutManager at all.
Also don't forget to check out the readme of the People sample app.

scroll android programmatically in all applications

I created a background service on android and I have two buttons which appear on the top of the screen all the time. I want to use these two buttons like scroll down and scroll up. But these two buttons should work on any kind of applications like Instagram, Facebook, Twitter and so. So, it means it should work in all applications that use scrolling.
I search a week on internet but I could not find any solutions.
This is not possible, sorry. Something like this would require your Service to have access to the Views of the applications and this would be a huge security breach, because you could read values from them and so on.
You could achieve this with a custom button code broadcast (so basically your buttons would act as physical buttons on the device) but this would most probably require you to have system-level permissions and some level of cooperation with the OEMs.
Android Activity class has a method called dispatchKeyEvent(), which could let you simulate the key input (with some limitations) but this is not present in the Service class.
Sadly this is not something you can do in Android. Typically you should not be able to touch views with a background service, the point of a background service is that you do some work in it (for example upload files to your web server or get some data). You CAN send a signal from a service once you're finished doing work to tell an app that something needs to happen, however the app needs to be specifically coded to respond to this broadcasted event.
If you wanted to do this with an app that you have developed, that can be achieved by using the onReceive method of say a BroadcastReceiver, however you cannot specifically define the behaviour of other apps as this would represent a security breach in Android.

Android global mutex?

I have a series of Android apps, and I need to coordinate their execution. On any given device, there can be any one of those apps installed, or any two of them installed, or any three of them, or any four, and so on. All of those apps can do one specific thing, and they all will try to do that thing from time to time. Now here's the problem: at any instant, at most one of those apps should be allowed to do that thing. If any one app is doing that thing, none of the other apps should be doing it; they should either wait for their turn, or simply pass. In other words, I need a global mutex or critical section mechanism on Android. In addition, I want to avoid NDK, if possible. What should I do?
You might have to give a bit more detail to get a more specific answer. But from what I understand it sounds like you could use BroadcastReceiver in each application that listens for an action to get broadcast and takes it as sign that it needs to either wait, or cancel it's action. Then inside each application whenever you are going to start your action you broadcast an intent with the action string something like `com.your.packagename.ACTION_STARTING_THE_THING. All of the other apps that are installed (if any) will receive this intent and can act upon it accordingly.

Is it safe to use Intent.FLAG_ACTIVITY_MULTIPLE_TASK?

Background
Let's take the next sceneraio:
the user uses an app X which has multiple activities (like the gmail app).
after navigating the app X a bit, he goes to your app.
in your app, you need to start this X app using an intent, to go to a specific activity within it.
now the user goes to this specific activity on the app X.
the user presses the back button, hoping to go back to your app instead of staying on the app X.
another similar scenario:
the user navigates on your app between activities.
your app went to the background (using the home button, for example).
your app shows a notification that once clicked, it will open a specific activity of your app.
the user clicks on the notification and goes to the specific activity of your app.
the user presses the back button, hoping to return to the app that was shown before clicking on the notification, instead of going to the previous activity on your app that was shown the last time it left it.
It seems that the last step on both scenarios isn't the default behavior.
This is why I've searched what is the best combination of flags for this purpose.
The problem
It seems that the only flag that can achieve the behavior i've described is Intent.FLAG_ACTIVITY_MULTIPLE_TASK (together with Intent.FLAG_ACTIVITY_NEW_TASK).
According to the android API, however, this flag isn't recommended for normal use:
Do not use this flag unless you are implementing your own top-level
application launcher.
...
Because the default system does not include
graphical task management, you should not use this flag unless you
provide some way for a user to return back to the tasks you have
launched.
This information seems as confusing as the rest of the descriptions about intents.
There are other intents flags that I've seen, like Intent.FLAG_ACTIVITY_CLEAR_TASK that achieve a similar result, but they have weird behaviors and/or they use high API
The question
Is it safe to use this flag? Are there any good alternatives to it?
What is the danger of using this flag and what is the meaning of the description on the API of using it?
In your first scenario, if your app needs to start an activity of another app, it can just start this activity within the same task as your application. There is no reason to use any special Intent flags for this (you don't need FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_MULTIPLE_TASK). In step 5 of your scenario, the user will return to your application (because BACK just takes him to the previous activity in the current task). This is the standard, default behaviour.
In your second scenario, my first response is "that isn't the standard behaviour". That means that users probably won't expect to be able to go back to the task that they were doing prior to clicking on the notification. However, if you really want to implement this, then I would suggest that you create a special Activity that is launched from the notification and this special Activity should have a different taskAffinity than the rest of the Activities in your application. In this case, when the special Activity is launched from the notification, it will not bring your application's task to the foreground. It will just create a new task containing just the special Activity. When the special Activity is showing, the user can press the BACK key and this will return him to the task that he was working on prior to clicking on your notification.
In general you should NOT use FLAG_ACTIVITY_MULTIPLE_TASK. The main reason is that if you have several tasks containing your application (or parts of it), it is pretty much impossible for the user to return to a specific one. There is no way to provide different launch icons or different application names (for the different tasks)(, so that the user will see multiple tasks in the "recent tasks" list, but will not be able to tell which one is which. You will have a hard time cleaning up what you are doing and you will just make more problems than you can deal with. There are about a million side effects of using this flag and for general applicaitons there is just no need to do it.

Start application when Content provider is changed

I want my application to start when someone modifies a content provider. A setting to be specific. The settings framework calls "notify" when a value is set.
If my app was started I would use registerContentObserver() I guess, but is is not started.
Can define some intent-filter in my manifest that wakes up my application. A back up plan would be to have a service running all the time that has registered a listener, but that seems like a wast or resources.
Thanks, Ola
This isn't directly supported by the Android device because starting an app every time a ContentProvider's data changes is a path to really killing your battery. To do the query, you'd need to do it in a service, which as you said is understandably undesirable.
Secondly, starting an intent is a user action. Android really doesn't support allowing an application to start all on its own without user request... Doing so would be impolite! What if your user was doing something important and then your app pops up on top? Remember the user is in control, not you. Instead of starting an application, consider placing a Status Bar Notification so the user can deal with it when it's convenient for them.

Categories

Resources