We recently migrated our Device Policy App(MDM) to support android 12 and would like to open our MDM dpc app after initial setup wizard is complete. This was working fine till android 11 until android 12 updates came out. We are handling GET_PROVISIONING_MODE and ADMIN_POLICY_COMPLIANCE but PROVISIONING_SUCCESSFUL is never called.
This is our code in Manifest for PROVISIONING_SUCCESSFUL :
<activity
android:name=".pages.ProvisioningSuccessActivity"
android:exported="true"
android:theme="#android:style/Theme.NoDisplay"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<intent-filter>
<action android:name="android.app.action.PROVISIONING_SUCCESSFUL"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
We are calling setResult(RESULT_FIRST_USER, intent); on receive of ADMIN_POLICY_COMPLIANCE intent.
Can anyone please help us with this?
Starting with Android 12 the PROVISIONING_SUCCESSFUL intent is only sent when
Provisioning does not happen within the initial setup wizard (e.g. when the end-user installs and starts the DPC app which then triggers provisioning through ACTION_PROVISION_MANAGED_PROFILE) or
No activity for the ADMIN_POLICY_COMPLIANCE activity action can be resolved
See here for the corresponding source code.
So in your case you have to replace the intent filter for PROVISIONING_SUCCESSFUL of your ProvisioningSuccessActivity with an intent filter for ADMIN_POLICY_COMPLIANCE.
Background Information
The ADMIN_POLICY_COMPLIANCE intent has already been introduced in Android 10, together with GET_PROVISIONING_MODE. Since then, it is the recommended intent for DPCs, to extend the initial setup wizard with a compliance screen and enforce initial policy settings:
DPCs must use this new Intent instead of listening for the ACTION_PROFILE_PROVISIONING_COMPLETE broadcast.
(source).
Until Android 12 this change didn't affect existing DPC implementations, that only supported fully managed provisioning. DPCs that also wanted to make use of the new working profiles, already had to switch to the new intents with Android 10.
With the deprecation of ACTION_PROVISION_MANAGED_DEVICE, fully managed provisioning can now only be triggered by the setup wizard. DPC implementations that support only fully managed provisioning have to switch now also to the new intents.
The ACTION_PROFILE_PROVISIONING_COMPLETE broadcast and the PROVISIONING_SUCCESSFUL intent are now only sent, when provisioning is triggered outside of the setup wizard. E.g. when a user installs and starts a DPC app, which triggers provisioning of a working profile through ACTION_PROVISION_MANAGED_PROFILE.
Related
This question targets Android for work.
I have written an app including a DevicePolicyController following this guide. The controller creates a managed profile for my Android device.
I added an app to that profile which is called FooApp.
Now I can see two icons of FooApp in my launcher, one with work badge and one without.
I also have an app BarApp, which is only in the primary profile.
How do I get the launch intent for the work version of FooApp in BarApp? (Start the work version of FooApp from within BarApp)
I can't use CrossProfileApps as I am on API 23.
The Solution I came up with cannot happen without the users consent. Maybe there will be a better one in the future. But here is mine:
I added the following intent filter for FooActivity in the Manifest of FooApp.
<intent-filter>
<action android:name="com.example.FooApp.ACTION_HOMELAUNCHER"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Then I added a crossProfileIntentfilter for my work profile (put the following code in the profile administration app currently running in the work profile).
DevicePolicyManager manager =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName componentName = BasicDeviceAdminReceiver.getComponentName(context);
IntentFilter filterin = new IntentFilter("com.example.FooApp.ACTION_HOMELAUNCHER");
manager.addCrossProfileIntentFilter(componentName, filterin, DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
In the end, when I want to launch the App in the work profile, I fire the ACTION_HOMELAUNCHER intent from BarApp and then the user can select, whether he wants to lauch the work profile version or the normal version of FooApp.
Feel free to improve upon this answer.
As per changes in Android Lollipop, reference :
StackOverflow Question
Cheese factory blog
I expect that when I start an activity of other application from my application, it should open in a new task even if the behavior is default (launchmode is standard). So, I made 2 test apps to verify the same behavior. But surpirisingly, the other app always opens up in my app's task, if there's no launchmode specified. I've tested this on Xiaomi Redmi Note 3 (5.1.1), Marshmallow emulator (x86), and the behavior is same for both. I'd appreciate some help on this, and also a link for reference from Android developer's site.
Some code :
Launching app :
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
startActivity(intent);
break;
App to be launched :
<activity android:name="com.android.sample.launchdemo.ActivityB">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
On a button click from launching app, the intent is fired and activity B successfully opens up, but in the same task. Thanks in advance for any help/suggestions.
After looking through the documentation, the feeling I have is that standard mode works the same way as it did before Android 5.0 (Lollipop). The cheese factory blog post was the only one that specified that action and even in my own experience standard launch modes have opened an activity in the same task it was sent in (unless intent flags were passed through). Someone correct me if I am wrong but it is not specified in Android documentation that standard mode would open a new task. From the Android documentation:
"standard" (the default mode): The system creates a new instance of the activity in the task from which it was started and routes the intent to it. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances. See full documentation
For what you are looking for, when firing off the Intent, the only way to guarantee a new task is use the flag FLAG_ACTIVITY_NEW_TASK. You can set this by calling either intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK) or intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) (the latter is for chaining flags together because that method will return the intent).
After doing more research, the only change (relating to this) that appears to be made in Android 5.0 Lollipop is that the recent apps screen can show multiple instances of an activity.
In previous releases, the recents screen could only display only one task for each app that the user interacted with most recently. Now your app can open more tasks as needed for additional concurrent activities for documents. This feature facilitates multitasking by letting users quickly switch between individual activities and documents from the recents screen, with a consistent switching experience across all apps. Examples of such concurrent tasks might include open tabs in a web browser app, documents in a productivity app, concurrent matches in a game, or chats in a messaging app.
To me this seems like the only change relating and the post (cheesefactory and SO) have documentLaunchMode set to create new tasks for each activity (which very well could be the case considering the cheesefactory had a "Gallery" app). Documentation on concurrent documents and documentLaunchMode. documentLaunchMode and the flag FLAG_ACTIVITY_NEW_TASK can be configured to do similar things documentLaunchMode is preferred.
I've found the documentation below.
https://developer.android.com/guide/components/activities/recents.html
=> when the user is using their browser, and they tap Share > Gmail. The Gmail app's Compose screen appears. Tapping the Recents button at that time reveals Chrome and Gmail running as separate tasks. In lower versions of Android, all of the activities appear as a single task, making the Back button the only means of navigation. Figure 2 shows how the Recents screen looks in Android 5.0 and higher, versus lower versions of the platform. The image on the left screen for Android 5.0 and higher, and the image on the right shows how it appears in lower versions of Android.
and refer to the following link.
Lollipop: making my activity stay in the task that launched the share intent
=> By default, launchMode of myfirstapp.MainActivity is "standard" and any intent flags weren't set.
But after myfirstapp.MainActivity is started through share action of Album, the intent flag contains FLAG_ACTIVITY_MULTIPLE_TASK, FLAG_ACTIVITY_NEW_DOCUMENT.
When an activity is started through share, an activity which contains share in its Toolbar just sets Intent to its ShareActionProvider, and then ShareActionProvider starts an activity with this Intent - in this case, myfirstapp.MainActivity.
So I think that from Lollipop, the system begins a new task for the activity from a different app whose launchMode is "standard" only when the activity is started through share action.
I am building an app that is designed to run continuously. Furthermore, the user is locked into the app (via the pinning feature) when it is being used. When the app has not detected user interaction for a while, it unpins itself, calls the Android dream service, and displays a screensaver of sorts. When the user taps the device, it 'wakes up', goes to the main screen, and repins itself.
I need my app to auto-update. However, given the circumstances, I have had difficulty in doing so. It simply does not seem to update, or according to one of my colleagues, updated but closed the app.
Is there a way for the app to detect, download, and install an update while running, and then, if necessary, relaunch itself? What would be the best approach?
Thanks much.
Is there a way for the app to detect, download, and install an update while running
This is handled for you by google play store. An app is killed when it is going to be upgraded to a new version so the installation of the new version is smooth and data is not corrupted.
if necessary, relaunch itself?
If you want to keep running (or rather, restart the app) after an upgrade, yes you have to do some additional stuff.
A way that I use is this:
Put in manifest:
<receiver android:name=".receivers.AppUpgraded">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
public class AppUpgraded extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
// your app was just upgraded, restart stuff etc.
}
}
Note there is also a action.PACKAGE_REPLACED which will trigger for ANY app that is upgraded. You're likely only interested in the upgrade of your own app, so use action.MY_PACKAGE_REPLACED.
In Android, if I send an intent from my app using implicit intent, and there are two services which have a matching intent filter, which service will get invoked ?
I know for activities, the user will be asked a choice through a pop up window. How does Android make the decision in case of services ?
Thanks.
Quoting myself:
In addition, what happens if there are two (or more) services installed on the device that claim to support the same <intent-filter>, but have different package names? You might think that this would fail on install, as happens with providers with duplicate authorities. Alas, it does not. Instead, once again, the first one in “wins”.
So, if we have BadService and GoodService, both responding to the same <intent-filter>, and a client app tries to communicate to GoodService via the explicit Intent matching that <intent-filter>, it might actually be communicating with BadService, simply because BadService was installed first. The user is oblivious to this.
Moral of this story: don't use implicit Intents with services.
They will look to the priority :
<intent-filter android:icon="drawable resource"
android:label="string resource"
android:priority="integer" >
. . .
</intent-filter>
I arrived here because I am using Braze (was appboy) to deliver FCM messages to my app using their AppboyFirebaseMessagingService class. I now need to deliver custom events coming from my backend to my app. At first I thought I should build a new service and add it to the AndroidManifest next to the Braze service. Turns out that won't work as described by #CommonsWare.
What does work is to make a new MyFirebaseMessagingService class that is a subclass of AppboyFirebaseMessagingService and mention the MyFirebaseMessagingService in the AndroidManifest. This way both classes will see all messages. I'll have to add logic to filter for just my messages and ignore the Braze messages.
In my Application I am not having any UI part, so I need to start a Service as soon as the Applicaton gets installed on the Device. I saw many links from which the answer was that its not possible but I guess it is surely possible. Just have a look at PlanB Application on the Android Market that does fulfil my requirement. Below is my Manifest file how I tried, but the Service was not called at all. So, let me know what is the best possible way to start a Service when the Application gets Installed.
UPDATE
I also tried using android.intent.action.PACKAGE_ADDED it works fine for detecting the Package for the other Applications but not for itself.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.auto.start"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:icon="#drawable/ic_launcher" >
<service android:name=".MyService">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</service>
<receiver android:name=".BootUpReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.PACKAGE_INSTALL" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
</application>
</manifest>
Fortunately, Plan B does not work on Android 3.1+, as tested on a XOOM and a Galaxy Nexus.
What Plan B does is exploit a security hole that could be used by drive-by malware, which is specifically why Android prevents it from happening anymore.
UPDATE
To clarify: As inazaruk posted and I put into comments on other answers, all applications, upon installation, are placed in a "stopped" state. This is the same state that the application winds up in after the user force-stops the app from the Settings application. While in this "stopped" state, the application will not run for any reason, except by a manual launch of an activity. Notably, no BroadcastReceviers will be invoked, regardless of the event for which they have registered, until the user runs the app manually.
This block covers the Plan B scenario of remote-install-and-run, which they were taking advantage of previously. After all, with that, anyone with a hacked Google account would be at risk of having their device infected, hands-free as it were.
So, when the OP says:
I need to start a Service as soon as the Applicaton gets installed on the Device
the OP will be unsuccessful and will need to redesign the application to avoid this purported "need".
Applications installed on the /system partition are not subject to being placed into the "stopped" state after installation. If you have root, you can do,
$ adb root
$ adb remount
$ adb push your.apk /system/app
And it can immediately receive broadcast intents. This certainly doesn't provide a general purpose solution, but i wanted to mention it for completeness.
EDIT: Keep in mind that different versions of Android locate system APKs in different places. For example, Android 8 puts them under /system/app//.apk. Shell into your device and poke around and follow the same scheme used for other system APKs.
I agree with CommonsWare's answer to question: How to start android service on installation. In other words, you can't automatically start your service after you've just been installed.
One more thing about newer Android platforms: if you don't have UI at all, you'll have trouble starting your service even when using BOOT_COMPLETE intent on Android 3.1+.
That's because all installed applications are in stopped state. In this state applications will not receive ANY broadcast notifications.
In order to activate your application some other application (or user) needs to start your service or activity, or content provider. The usual workflow is when user clicks on your application's icon.
I've written a detailed explanations about this in my blog post.
Plan B does this launch by listening to the events which happen in the system. It uses a receiver which literally listenes to hundreds of events hoping that some of them will eventually fire up. So this is how you can do it. Otherwise, there are no built-in means to launch the application as soon as it gets installed.
I'm not sure what your constraints/purpose is, but if you can install another application that has an activity you can have it send an intent with the flag FLAG_INCLUDE_STOPPED_PACKAGES.
This will use your application for the intent resolution, even though it's in a stopped state. If the action of the intent matches one of your filters, it will also bring the package out of the stopped state.
I don't think so You can start service immediately after installed your application on device,
The application must first be invoked by the user through some sort of Activity.The only things you have to register some Broadcast Receiver with appropriate intents in manifest which invoke you service when something is happening on device but this remaing to Android 3.1 version.
EDIT:
After Android 3.1+ onwards you can not use any Broadcast for starting your application, because all application remains in inactive state after completion of device boot and to launch the application the user have to invoke it.(By touching the app icon).
As stated by CommonsWare in the answer to this question (which I suppose you have all ready seen, but chose to ignore) starting a Service on install is not possible - it is simply not a thing that is implemented into the platform.
Starting it automaticly at the next boot is however possible.
As stated in the Technical Details for PlanB:
Plan B will attempt to launch as soon as it downloads, but in some cases you will need to send an SMS to get it started.
My guess is that on a rooted phone you might be able to start the Service on install - but there's no guarantee that the phone is rooted, which is why PlanB will require recieving a text in some cases because that can be registered by the IntentFilter of the app and then used to start the Service.
there is an app on google play Android Lost which invoke the registration service for google push messages via an incoming sms without launching the app even once for version 3.0+.
Perhaps the best way to accomplish this (and now I'm speaking to the specific intent of the OP, a program that gets installed in order to retrieve a stolen phone, not the general question) is social engineering, not software engineering.
So, an icon with text like "Password List" or "My Bank Accounts" which suddenly appeared on the home screen would undoubtedly be clicked on. Look at the success of all sorts of other phishing, and here you would be targeting a thief, who's already motivated to continue nefarious activity. Let the thief start it for you. :)
HEY I think using a BroadcastRecivier to automatically start the app on restart of device hence it will automatically start on device start.Hope this will help