I'm developing a custom home screen launcher. As part of its functionality I would like to be able to show unread notification badges.
Instead of implementing my own API for this, I would like to hook onto existing standards. The most widely used is the one for Samsung's TouchWiz launcher.
It works through a ContentProvider with the authority com.sec.badge. Now, on Samsung devices, I can easily use a ContentObserver to observe changes to Samsung's ContentProvider and it works perfectly. However, on devices without an existing ContentProvider (i.e. non-Samsung devices) I would like to provide my own ContentProvider for this purpose. This also works perfectly to capture inserts from other apps.
However, when I roll my own ContentProvider I naturally get an INSTALL_FAILED_CONFLICTING_PROVIDER error when trying to install on Samsung devices.
I fully understand why this is happening since Android wants to avoid having conflicts in the providers.
What I would want help with is a workaround. Is it possible to somehow register my ContentProvider dynamically instead of declaring it in AndroidManifest.xml? That way, I could first check if the authority is already taken, and if so go with an Observer. Otherwise, register my own ContentProvider and go with that.
I realize that this might be bad practice but I don't really see any other way. Some apps (such as Facebook) also implement Sony's badge API that works through Broadcasts which avoids conflict, but not nearly as many existing apps use this process.
I've tried this:
ContentProvider test = new SamsungContentProviderSpoof();
ProviderInfo providerInfo = new ProviderInfo();
providerInfo.authority = "com.sec.badge";
providerInfo.enabled = true;
providerInfo.exported = true;
test.attachInfo(this, providerInfo);
but that obviously fails. I guess I need to somehow access some system ContentResolver and register myself there, but I don't know how.
I would like to hook onto existing standards
There are no existing standards. A few vendors have done their own thing, and that's it.
The most widely used is the one for Samsung's TouchWiz launcher.
Note that this mechanism is undocumented (AFAICT) and unsupported (outside of select Samsung partners).
Is it possible to somehow register my ContentProvider dynamically instead of declaring it in AndroidManifest.xml? That way, I could first check if the authority is already taken, and if so go with an Observer. Otherwise, register my own ContentProvider and go with that.
You are welcome to say that it is disabled (android:enabled="false") in the manifest, then conditionally enable it later using PackageManager and setComponentEnabledSetting(). You would know that you needed to do this by either trying to communicate with the existing provider (e.g., registering your observer) and getting an expected error, or by interrogating PackageManager to see if the provider exists.
However, not only will you need to claim that you are Samsung in terms of the provider, but also in terms of the custom permissions. That will break on the "L" Developer Preview, and probably going forward, for much the same reason that you ran into with the conflicting provider. At the present time, there is no workaround for this that I am aware of.
Related
There are apps (such as https://play.google.com/store/apps/details?id=com.teslacoilsw.launcher) that are free, but whose paid features can be enabled by buying another app (in this case, this one https://play.google.com/store/apps/details?id=com.teslacoilsw.launcher.prime)
How does this work?
My guess is that the free apps launches an explicit Intent and can detect if the app is present via a try/catch structure. The downside of this is that this could be easily circunvented by someone who creates an app with the same package name and specifies all possible Intent filters.
Is this how it works, or is it some other way?
There are various ways to do that. One way is to query a content provider which will be protected with a special permission.
I have released quite long ago on Github a library which helps doing this: Android Unlocker Library.
That's a good option if you are dealing with devices outside the Google ecosystem, however, from a developer experience, in-app purchases offer a much better user experience (and thus drive more sales) according to me.
The easiest way is to use startActivityForResult(...) from app A against an Activity of app B, that must be configured with an IntentFilter in order to be used from an outer app. Inside the B called activity you can also check who's calling with getCallingActivity(). You can find an example here.
Before starting the Activity, you can test that B is installed (using the PackageManager) or you can just start the activity and catch the Exception.
In the called Activity, you can check the signature of the calling package using the PackageManager.checkSignature(String,String) method. Pass the package name of A and B and if the signature matches, execute the logic.
I'm looking into porting some existing code to take Android M's new way of dealing with permissions into consideration. However the permission API needs to have an activity associated with it (for example the requestPermissions() method's first parameter is an activity).
So how should a service that needs to check if a permissions has been granted and request for permissions use this new API if the service doesn't have an activity?
Is it possible for the service to create a dummy invisible activity just for use with the permissions API? (if its possible I don't like the thought of doing that anyway though).
Or suppose its not a service but a model class that needs to perform a permissions check, in MVC a model shouldn't have any knowledge of the Vs and Cs and yet now either it has to in order to know which Activity to use with the permission API. Or potentially lots of code might have to migrate from model code into Activity code.
Any thoughts on how to migrate non activity based code that needs to check/prompt for permissions over to Android 6.0?
Update: I left out an important piece of information - this is code that is pre-installed (our company provides code that device manufacture's place in rom) and often may be run at device boot time and run in the background. Therefore the usual situation of a user being prompted for permission when they launch the app or later (and there therefore being an activity at that point) does not necessarily apply.
So how should a service that needs to check if a permissions has been granted and request for permissions use this new API if the service doesn't have an activity?
There is almost always an activity, except for pre-installed apps and plugins for other apps. Otherwise, your service is unlikely to ever run, as nothing will have used an explicit Intent to start up one of your app's components, so it will remain in the stopped state.
For the ~99.9% of Android apps that have an activity already, if the permissions are needed for the whole operation of the app, request them on first run. As Snild Dolkow notes, if the user later revokes the permission through Settings, you can detect that without an activity, then use other UI options (e.g., Notification, app widget) to let the user know that operation is suspended until they grant you the permissions again, which they would then do through your activity.
Is it possible for the service to create a dummy invisible activity just for use with the permissions API?
Presumably you can have a Theme.NoDisplay activity use requestPermissions(). However, from the user's standpoint, it will not make much sense, unless there's some alternative UI (app widget?) that they are interacting with. Popping up a permission dialog out of nowhere is unlikely to make you popular.
UPDATE 2019-06-15: Note that Android Q bans services popping up activities frmo the background. Please use a notification instead.
in MVC a model shouldn't have any knowledge of the Vs and Cs and yet now either it has to in order to know which Activity to use with the permission API
Do not touch the models until you have requested the permission, and gracefully fail if the permission is revoked. You already have to gracefully fail in other circumstances (out of disk space, no Internet connection, etc.), so a revoked permission should be handled in much the same way.
using this new 6.0 API seems like an recipe for bad design and tight coupling
You are welcome to your opinion. Based on what I have read, the Android engineers believe that asking the user for permissions is part of the user experience and is best handled at the UI layer as a result.
Again: the vast majority of Android apps will not have a problem with this, as they have a user interface. Apps that do not have a user interface and need dangerous permissions are in for some amount of rework.
this is code that is pre-installed (our company provides code that device manufacture's place in rom) and often may be run at device boot time
First, please understand that this is so far from normal that you can't even see normal from where you are due to the curvature of the Earth. :-) You can't really complain that Google did not optimize this particular scenario.
As I understand it, even system apps should be asking for runtime permissions. The Camera app did, for example, on the 6.0 preview. That being said, there's gotta be some database on the device somewhere that is tracking what has been granted, and presumably there is some way to pre-populate it. However, the user could still revoke it from Settings, presumably. But, the manufacturer could pull some stunts (e.g., messing with the Settings app) to possibly even preclude that scenario. I'd be looking in the same area as "how do I get it so my app cannot be force-stopped?" that device manufacturers can do.
Your alternatives would be to get rid of the dangerous permissions or to migrate your app off the SDK and into a standard Linux binary that would be run as part of the boot process and be put into a Linux user group that has access to the stuff that you need.
Ask for it when the user enables whatever feature your service provides. They'll be in one of your activities at the time. Yes, it means that your activities need knowledge of what permissions your services will require.
The service can always check for the permission by itself, though, since checkSelfPermission() is available in all Context instances. So you don't need an activity for that.
I guess an alternative would be to have your service post a notification saying "feature X requires you to approve more permissions". Actually, that may be a good idea regardless, in case the user goes into settings and revokes any permissions after the fact. That notification would then take the user to some activity with an "enable feature X" button/checkbox -- ask for the permission when that is selected.
You can send a notification. Look this library to manage the permissions: permission library
I am creating an app with a service, and I would like other apps to be able to interact with and extend it. I can think of two scenarios:
another app wants to interact with the service
someone develops a better version of the service that they would
like my app to use instead of my built-in service
Most of the things that I have read about actions say that you should name your action something like com.mycompany.appname.CUSTOM_ACTION. However, I do not think I should put the actions in my own namespace since other developers might want their apps to be able to receive them. Instead, I think they should give them a more public name, like intent.action.CUSTOM_ACTION.
Is there a convention for naming public actions? Is it ok that I name my actions like intent.action.CUSTOM_ACTION, or is that a no-no?
It's bad idea to give it generic names. It comes with your app and therefore you should stick to com.mycompany.appname.CUSTOM_ACTION namespace
openintents.org is a website that appears to allow developers to register intents that they want other applications to use.
I've built an app called xLancer (https://market.android.com/details?id=kz.jay.xlancer.activity) that retrieves job listings from Elance. Now i want to implement a feature that would remind me to bid on a project at a later time. Instead of reinventing the wheel i want to launch any external TODO/Task manager app. But now i am stuck, i don't know which URI or action should be specified, so far i've only used intents to call my internal activities by specifying class name explicitly.
So the question is: how can i know which URI/action should be specified?
Look here, I didn't see any Todo/Task intents there though....
I notice that (too) many applications on my Android phone require full internet access. In some cases, it seems like they just want to connect to some service. In other cases, it is clear they are phoning home. However, it seems like users have no easy way of checking which one is the case.
I realize that in the manifest permissions for Android there is a "android.permission.INTERNET", but is there a way to say "this application will only access some.domain.org", and maybe specify which protocols will be used, or something like that? Could the Android system enforce that somehow?
As far as I know, android.permission.INTERNET is the most specific you can get. I agree that it would be nice to be able to specify that my app only talked to an individual server, but in the end it wouldn't tell the user anything meaningful, since most protocols can be tunneled and proxied over most other ones with sufficient ingenuity.
The android UI devs decided to go with the broader permission rather than confusing regular users by displaying information that would not be functionally meaningful. As an alternative, you might consider including a note in either your application description or a popup immediately after installation that explains precisely how and why your application accesses the internet.
Edit:
You might be able to circumvent that permission altogether if you only wanted one-way messaging to the phone and did something excessively clever with C2DM. This would be a bad thing to do, however, and I haven't verified that it would actually work without that permission.