When application is in background and screen is locked,I'm unable to start activity, there is no exception or warning, onCreate() is just not called. I've been struggling against this problem for while, and I think I've finally found the source of it.
There is a line in logs:
D/com.android.server.am.ExtraActivityManagerService: MIUILOG- Permission Denied Activity KeyguardLocked: Intent { flg=0x14010000 cmp=com.trueconf.videochat/com.trueconf.gui.activities.Call (has extras) } pkg : com.trueconf.videochat uid : 10634
Is this why I can't start an activity? Also, how do I solve this, should I disable keyguard or something?
This is a special permission on MIUI that has to be enabled for apps.
You can find it in
Settings
Manage Apps
YOUR APP
Other permissions
Show on Lock screen
User must enable this manually. As far as I know, the best you can do is to guide the user to this settings menu directly by launching an intent (and probably showing some explainer text prior to this).
Intent looks like this
startActivity(new Intent("miui.intent.action.APP_PERM_EDITOR").putExtra("extra_pkgname", getPackageName()))
Make sure to try catch it as it can throw exceptions if activity can't be started (e.g. the device actually is not running MIUI or the intent is somehow not valid on the particular device/version)
Related
Use case
during a phone call, User opened some apps and the inCall UI goes behind the APP UI.I need to bring it back using adb command
What i did ?
I used below command
adb shell am start --activity-brought-to-front -n com.google.android.dialer/com.android.incallui.InCallActivity
Which resulted in error
Security exception: Permission Denial: starting Intent { flg=0x10400000 cmp=com.
google.android.dialer/com.android.incallui.InCallActivity } from null (pid=12862
, uid=2000) not exported from uid 10102
java.lang.SecurityException: Permission Denial: starting Intent { flg=0x10400000
cmp=com.google.android.dialer/com.android.incallui.InCallActivity } from null (
pid=12862, uid=2000) not exported from uid 10102
at com.android.server.am.ActivityStackSupervisor.checkStartAnyActivityPe
Is there any way to acheive the desired result using adb?
The InCallActivity activity can't be launched from other applications including launching via am start as the android:exported element of InCallActivity is set to false.
android:exported
This element sets whether the activity can be launched by components of other applications - "true" if it can be, and "false" if
not. If "false", the activity can be launched only by components of
the same application or applications with the same user ID.
If you are using intent filters, you should not set this element "false". If you do so, and an app tries to call the activity, system
throws an ActivityNotFoundException. Instead, you should prevent other
apps from calling the activity by not setting intent filters for it.
If you do not have intent filters, the default value for this element is "false". If you set the element "true", the activity is
accessible to any app that knows its exact class name, but does not
resolve when the system tries to match an implicit intent.
This attribute is not the only way to limit an activity's exposure to other applications. You can also use a permission to limit the
external entities that can invoke the activity (see the permission
attribute).
I'm having troubles opening system DND preferences from my App so that user can create or edit Automatic Time rule.
Current situation
Our app already has a similar feature which disables App-notification LED, sound and vibration for some specific time period (for example between 10pm-8am) and is applied app-wide. As of Android Oreo, our feature doesn't work anymore because of Notification Channels. The only solution is, as far as I understand, to create in System preferences Automatic Time rule which is then applied system-wide.
What I want to do?
Just to redirect Oreo user from my app to System preferences ie. Do Not Disturb preferences in order to add or edit Time rule.
The problem
There is no specific Intent which opens Do Not Disturb preferences. The closest one I could find was Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS which leads me to this Preference screen. I also found action which I exactly need, but as you can see, it is hidden by annotation.
Does this mean there is no way to open this Preference screen and I should use another approach?
I also had this question for a long time, now I finally found the solution that works for me:
Java
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.Settings$ZenModeSettingsActivity"));
startActivity(intent);
Kotlin
val intent = Intent()
intent.component = ComponentName("com.android.settings", "com.android.settings.Settings\$ZenModeSettingsActivity")
startActivity(intent)
If you take a look at the AndroidManifest.xml for the Settings app you can see that there is an Activity Settings$ZenModeSettingsActivity (as mentioned by #cyb3rko in https://stackoverflow.com/a/63713587/467650) already from Android 5.0.
To send the user to the "Do not disturb" screen you can use the action android.settings.ZEN_MODE_SETTINGS like this:
try {
startActivity(new Intent("android.settings.ZEN_MODE_SETTINGS"));
} catch (ActivityNotFoundException e) {
// TODO: Handle activity not found
}
I would expect the intent filter to be even more stable than the class name.
I'm sure I'm overlooking something in the Settings class documentation. What Intent can open the Settings app in the "Do not disturb" section?
I expected it to be the ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS action, but that is only for the screen which lists which apps have requested DND access.
Update
Looking at the AndroidManifest.xml for the Settings app there is an Activity Settings$ZenModeSettingsActivity already from Android 5.0.
To send the user to the "Do not disturb" screen you can use the action android.settings.ZEN_MODE_SETTINGS like this:
try {
startActivity(new Intent("android.settings.ZEN_MODE_SETTINGS"));
} catch (ActivityNotFoundException e) {
// TODO: Handle activity not found
}
Original answer
It looks like there are no screens in the Settings app (at least on Android 6+7) where you can enable/disable DND. It seems like this is only available through the settings tile (and can be disabled in the dialog when changing the volume).
I have a Samsung S6 (Android 6.0.1) which has this screen, but this is probably some custom Samsung changes. The screen is represented by the class com.android.settings.Settings$ZenModeDNDSettingsActivity which can be started by any app. This might be of help for some people out there.
AndroidManifest.xml for Settings app for Android 6+7:
https://android.googlesource.com/platform/packages/apps/Settings/+/android-6.0.1_r68/AndroidManifest.xml
https://android.googlesource.com/platform/packages/apps/Settings/+/android-7.0.0_r6/AndroidManifest.xml
You have to use the following Intent: ACTION_VOICE_CONTROL_DO_NOT_DISTURB_MODE and then pass a boolean through EXTRA_DO_NOT_DISTURB_MODE_ENABLED.
Make note that the documentation specifies the following: This intent MUST be started using startVoiceActivity.
Im having trouble getting this to work, hereĀ“s a quick overview of the idea.
First, I cant change the logic behind this, it was a specific requirement from the customer, I realize that with any tool such as AnyCut it could be bypassed but that doesnt matter really.
My customer offers a suite of apps, the idea is that all applications bellonging to the suite would be launched from a "Dashboard app", so that I only show the Dashboard app in the main launcher and not all app icons.
Lets take two Apps to get the idea solved. The Dashboard App (A) and the Recieving App (B).
I want to establish an intent filter (I think) on app B so that whenever I go into app A, and click the app B icon the app will be either launched or started from where it let of (brought to front).
Is this even possible? If so, how can I do it? I managed to get it to launch by specifically launching one activity in the app using:
Intent i = new Intent();
i.setClassName("PACKAGE_NAME","SPECIFIC_CLASS");
startActivity(i);
But that isnt the behaviour that I want, as it always starts app B in the same spot.
Thanx in advance,
Stefano
Edit: Added some new information. I was taking a look at the DDMS.
If I launch the application from scratch through the main Android launcher the intent is exactly the same as when I leave the home button pressed and then only bring the app to front, what ever activity im in. So I was trying to reproduce, unsucsesfully until now, this intent.
INFO/ActivityManager(1292): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.package/.uiPackage.Activity}
This is how AnyCut does it
Intent { act=android.intent.action.VIEW flg=0x10000000 cmp=com.example.package/.uiPackage.Activity bnds=[125,242][235,360]}
Any idea how I could go about creating that exact same intent? I cant even find that flag in the Intent API.
Figured it out, this is how I did it.
Intent i = new Intent();
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setAction("android.intent.action.VIEW");
i.setComponent(ComponentName.unflattenFromString("com.example.package/com.example.package.activityName"));
startActivity(i);
I'm not quite sure I'm following the expected results you want to see, but the following would launch the app from the dashboard and remove the dashboard from the activity stack leaving the selected app running:
Intent i = new Intent();
i.setClassName("PACKAGE_NAME","SPECIFIC_CLASS");
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
I believe this should start the app as if you were starting any other app.
Please add more information on your logic if this is not what you are looking for.
I think that when you switch activities android's default action is to sort of pause or hold the activity in its state the user left it in last. I know there is a way to make it so that the state is not saved when switching activities but I cant remember it off the top of my head.
i tried coding it, i tried solving it with google and stackoverflow, nothing found :=) so hopefully someone else has a better idea, im not sure if i get everything right:
i have 2 applications: ad (main app) / adfree-pro (just license starts ad app without ads ;P)
so the problem is, i want to have a pro version (with pro icon) in the launcher, which starts the normal-ad app, which is (the normal ad-app) not in the launcher.
i tried removing the ad-app from the launcher (which due to my research should JUST remove it from the launcher)
pkgMgr.setComponentEnabledSetting(new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".Main"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
which results to: the icons in the launcher are correct ;) BUT the application can't be found on the phone, launched, started, even not with a launcher pro activity shortcut. it seems to be there (shortcuts can be created) but i crashes with an activity exception when i try to launch it.
02-18 14:38:59.237: ERROR/AndroidRuntime(9941): Caused by: android.content.ActivityNotFoundException: Unable to find explicit activity class {PACKAGE_NAME/PACKAGE_NAME.Main}; have you declared this activity in your AndroidManifest.xml?
which doesnt seem to belong (the error message)
it looks like there has happened more to the application than just simply removed the entry in the launcher.
thanks a lot guys,
every workaround for this situation appreciated :)
best regards :)
You can't have app installed and hide it's launcher icon. The way I'm addressing it with my application which works similar to yours that I don't try to fight icons but instead the app can be launched using ether icon. Obviously you don't have to do in the main (free) app and the code that launches app from your pro icon will look something like the following:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
// check if main app is installed. If yes then start it
if (appExists()) {
Log.d(TAG, "Started main app from Pro");
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("myapp://com.myapp.main"));
startActivity(intent);
finish();
} else {
// display view with link back to Market
onAppNotExists();
}
}
It's up to you to implement appExists() which is probably some sort of license check
Of course, alternatively you can develop your app's common code as library project and then distribute it in 2 flavors without duplicating the code
BUT the application can't be found on the phone, launched, started,
even not with a launcher pro activity shortcut.
Not application, but activity.
So, if your LAUNCHER activity is BaseActivity, you may create something like BaseFakeActivity (don't forget to set it as LAUNCHER in your manifest instead of your BaseActivity) and which only function is to start your BaseActivity and then finish() itself.
Now you may hide your BaseFakeActivity but you'll still be possible to interact with your BaseActivity.
P.S.: Don't forget to test your app's behaviour after doing things this way ;)