How do I programmatically dismiss a crash dialog? - android

I'm building a DPC (Device Policy Controller), and one of the issues I'm seeing is that while the Play Store and Play Services are being updated, the Google Contact Sync service crashes -- leaving the typical crash dialog on the screen. Since part of the idea of the initial set up process is to have as little user interaction as possible, how can I dismiss this dialog programmatically (since I seem to be pretty much guaranteed that this will happen)?
I've tried dismissing system dialogs...
ctx.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
... but that doesn't seem to do the trick.
Since this is a DPC, anything that requires device ownership/administration is fine.
edit: Usually I have no UI on screen at the time, so if one is necessary please do mention it. Also, preferably the solution should work on at least 6.0+, if not 4.0+.

Try to do it onWindowsFocusChanged method like this for example :
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (!hasFocus) {
Intent ctx= new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(ctx);
}
}
I'm not sure about app crash Dialog but maybe it'll help you

AppErrorDialog can be dismissed by broadcasting ACTION_CLOSE_SYSTEM_DIALOGS if Android version is N.
ctx.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
However, AppErrorDialog won't be displayed if phone is locked.
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
&& mLockScreenShown != LOCK_SCREEN_SHOWN;
} // ActivityManagerService

Please try this code.
try {
Class ActivityManagerNative = Class.forName("android.app.ActivityManagerNative");
Class IActivityManager = Class.forName("android.app.IActivityManager");
Method getDefault = ActivityManagerNative.getMethod("getDefault", null);
Object am = IActivityManager.cast(getDefault.invoke(ActivityManagerNative, null));
Method closeSystemDialogs = am.getClass().getMethod("closeSystemDialogs", String.class);
closeSystemDialogs.invoke(am, "DPC close");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}

Related

Settings.canDrawOverlays is returning false even after turning the permission on from settings

I am trying billow Code from this answer to check if the permission is enabled. but it is returning false even when the permission is enabled from the settings.
public static boolean canDrawOverlayViews(Context con){
if(Build.VERSION.SDK_INT< Build.VERSION_CODES.LOLLIPOP){return true;}
try {
return Settings.canDrawOverlays(con);
}
catch(NoSuchMethodError e){
return canDrawOverlaysUsingReflection(con);
}
}
public static boolean canDrawOverlaysUsingReflection(Context context) {
try {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Class clazz = AppOpsManager.class;
Method dispatchMethod = clazz.getMethod("checkOp", new Class[] { int.class, int.class, String.class });
//AppOpsManager.OP_SYSTEM_ALERT_WINDOW = 24
int mode = (Integer) dispatchMethod.invoke(manager, new Object[] { 24, Binder.getCallingUid(), context.getApplicationContext().getPackageName() });
return AppOpsManager.MODE_ALLOWED == mode;
} catch (Exception e) { return false; }
}
Recently I've also faced the same issue and got the following workaround .
Referenced from
https://code.google.com/p/android/issues/detail?id=198671#c7
public boolean getWindoOverLayAddedOrNot2() {
String sClassName = "android.provider.Settings";
try {
Class classToInvestigate = Class.forName(sClassName);
if (context == null)
context = activity;
Method method = classToInvestigate.getDeclaredMethod("isCallingPackageAllowedToDrawOverlays", Context.class, int.class, String.class, boolean.class);
Object value = method.invoke(null, context, Process.myUid(), context.getPackageName(), false);
Log.i("Tag", value.toString());
// Dynamically do stuff with this class
// List constructors, fields, methods, etc.
} catch (ClassNotFoundException e) {
// Class not found!
} catch (Exception e) {
// Unknown exception
e.printStackTrace();
}
return false;
}
does the check involves the device admin?
I have encountered this problem when disabling device admin, I have checked this permission in the DeviceAdminReceiver->onDisabled() and on some devices, and canDrawOverlays returned false, despite the fact i had the permission.
The above answer helped sometimes but not all the time. the thing that did work is Thread.sleep before the check.
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// some exception here
}
The minimal time that worked for me was 20 millis. than canDrawOverlays returned true
Note: this is not a good practice however this is the only thing that worked for me
Based on BennyP's answer, I've made a Runnable run the required code after 500ms and that worked very well. The feedback is a bit delayed, but the user won't even notice the delay.
This is the code I've added to my onResume()
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(!Settings.canDrawOverlays(ControllerActivity.this)){
//Handle overlay permission not given here
}
else{
//Handle overlay permission given here
}
}
}, 500);
Hope it helps!
I tried restarting the activity after the user accessed the setting . This is code :
public static void restartActivity(Activity act){
Intent intent = getIntent();
finish();
startActivity(intent);
}
First of all, I am really very surprised with this strange behaviour of
Settings.canDrawOverlays(this);
I also faced the same issue with its usage, it was returning false even if the permission is already assigned.
What I noticed that, I was using this check in my onStart() method, where it was creating this wired behavior. To resolve this, I searched over internet and no result was there that can satisfy me and the one I can use.
Solution
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Log.e("Overlay Permission", "" + Settings.canDrawOverlays(this));
if (!Settings.canDrawOverlays(this)) {
MyPreferences.saveBoolean(HomeScreen.this, "showOverlayPermissionDialog", true);
} else {
MyPreferences.saveBoolean(HomeScreen.this, "showOverlayPermissionDialog", false);
}
}
I did something lake this, in my onCreate(). Here I saved the values accordingly in my SharedPreferences, and according to these Shared Preference values, I created a check for showing an overlay dialog in my onStart(). This worked fine!
You can try this solution, and mark this answer useful if your problem is solved.
Thanks

Robotium testcase

I have a Robotium test case and It should be like
UI Application starts uploading data to server
User swaps to some other application on the device
uploading operation is running at the background
user comes to the main UI application
How to keep track of uploading the data at background? can we use multithreading for this?
try {
mSolo.clickOnMenuItem("UPLOAD");
mSolo.sleep(1000);
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
mSolo.waitForActivity(Settings.ACTION_APPLICATION_SETTINGS);
mSolo.goBack();
mSolo.assertCurrentActivity("main",
UIActivity.class);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Is this code correct? If not suggest me a modification or correct code.
Help is always appreciated,
Thanks
You cannot interact with other applications unless you signed the third party application with your own key (see black box testing).
But what you can is pressing Home, Back and starting Intents. The following code is untested but hopefully gives you an idea:
try {
mSolo.clickOnMenuItem("UPLOAD"); // start upload
mSolo.sleep(1000);
mSolo.goBack(); // leave app
...
Intent intent = new Intent("com.company.another.app.SomeActivity");
startActivity(inent); // start another app
...
// option one: get app context and use it for access on preferences, etc.
Context context = this.getInstrumentation().getTargetContext().getApplicationContext();
// option two: wait for logs that you write while uploading
solo.waitForLogMessage("Upload completed");
...
Intent intent = new Intent("com.myapp.MyMainUIActivity");
startActivity(inent); // start own Main Activity again
...
} catch (Exception e) {
e.printStackTrace();
}
So you could use log messages, preferences or any other methods of your app in order to follow up the upload progress.
You cannot leave your application and run it again with Instrumentation. This part is not correct:
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
Why do you create new instrumentation? You can simply run:
getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
by the way, solo.goBack() just does it, so it doesn't make sense to call it with instrumentation. I would simply rewrite it to:
try {
mSolo.clickOnMenuItem("UPLOAD");
mSolo.sleep(1000);
mSolo.goBack();
assertTrue(mSolo.waitForActivity(Settings.ACTION_APPLICATION_SETTINGS));
mSolo.goBack();
mSolo.assertCurrentActivity("main", UIActivity.class);
} catch (Exception e) {
e.printStackTrace();
}

Keeping Wifi-Direct Turned on AOSP devices

My friend and I are developing an app that streams synchronized music between android devices using wifi-direct. Our issue is that while the app works fairly well once phones are connected, it takes some doing to get phones to connect because on all AOSP devices it appears that wifi direct is only turned on upon entering the wifi direct menu (and immediately closed upon exiting). This makes in-application connection rather difficult. We were wondering if there is any way to turn on wifi direct from the code and keep it on (if anyone could refer us to a detailed description of how to do this using Reflection that would be fantastic).
Thanks! Here is our current code:
public class Reflector {
static Method turnOnICS;
static Method turnOnJB;
static Method turnOffICS;
public static void turnOnP2P(WifiP2pManager m, Channel c) {
//Log.v("button", "turnOnP2P");
if (android.os.Build.VERSION.SDK_INT == 14 || android.os.Build.VERSION.SDK_INT == 15) {
//Log.v("version", "Version is ICS");
try {
turnOnICS = WifiP2pManager.class.getDeclaredMethod("enableP2p",WifiP2pManager.Channel.class);
turnOnICS.setAccessible(true);
turnOnICS.invoke(m, c);
} catch (NoSuchMethodException e) {
Log.v("ics_error", "ICS enableP2p() not found");
} catch (Exception e) {
Log.v("ics_error", "turnOnICS invocation failure");
}
} else if (android.os.Build.VERSION.SDK_INT == 16 || android.os.Build.VERSION.SDK_INT == 17) {
//Log.v("version", "Version is JB");
try {
turnOnJB = NsdManager.class.getDeclaredMethod("setEnabled", boolean.class);
turnOnJB.setAccessible(true);
turnOnJB.invoke(NsdManager.class, true);
//must feed it an nsdmanager, but none exists in wifidirectactivity
Log.v("nsd", "problem");
} catch (NoSuchMethodException e) {
Log.v("jb_error", "JB setEnabled() not found");
} catch (Exception e) {
Log.v("jb_error", "turnOnJB invocation failure");
e.printStackTrace();
}
}
}
public static void turnOffP2P(WifiP2pManager m, Channel c) {
//Log.v("button", "turnOffP2P");
if (android.os.Build.VERSION.SDK_INT == 14 || android.os.Build.VERSION.SDK_INT == 15) {
//Log.v("version", "Version is ICS");
try {
turnOffICS = WifiP2pManager.class.getDeclaredMethod("disableP2p", WifiP2pManager.Channel.class);
turnOffICS.setAccessible(true);
turnOffICS.invoke(m, c);
} catch (NoSuchMethodException e) {
Log.v("ics_error", "ICS disableP2P() not found");
} catch (Exception e) {
Log.v("ics_error", "turnOffICS invocation failure");
}
}
}
public static void printAll(){
Method[] list = WifiP2pManager.class.getDeclaredMethods();
for(Method m : list){
Log.v("tag",m.getName());
}
}
}
Thank you for asking this question... it's been a question we've been wrestling with as we add WiFi Direct features to our app.
After looking through the settings on several phones from different manufacturers, and reading pages like this and this (which admittedly are not very precise in the details, but it's the best we could find), we've come to the conclusion that there's no need to separately turn on WiFi Direct per se: it's enabled whenever WiFi is enabled. So, at most, your app would need to turn on WiFi.
However, WiFi Direct scanning (and visibility to being scanned) is what you initiate by going to the WiFi Direct settings page.
Leaving that page may stop the scanning (though 3rd-party apps can and do initiate their own scanning), but should not disable WiFi Direct. That would make no sense at all... as you say, that would make it difficult (impossible) for apps to use WiFi Direct, but apps do use it successfully. What did you see that made it seem like WiFi Direct was being disabled when you left that settings page?

Try Catch method for open bluetooth function

I made a simple android appication for connect with bluetooth serial device and I want to add closeBT if android not connected maybe the device is out of range because crash.
How do I do this? This code is correct?
protected void onStart() {
super.onStart();
findBT(); //Check if bluettoth enable and paired devices
try {
openBT(); //open sockets,streams
} catch (IOException e) {
e.printStackTrace();
closeBT();
}
}
Try-catch is not for the application logic! It is for doing stuff when something went wrong! You want to use an if-else here, like
if (findBT() != null) { // I don't know what findBT does, but maybe it returns BT-devices
try {
openBT(); //open sockets,streams
} catch (IOException e) {
e.printStackTrace();
// inform the user that a connection could not be established or something similar
}
} else {
// inform the user, that no BT-device was found.
}
you want to use closeBT() for instance when the user or your application decides to disconnect the BT-devices.

How to use the hide methods in API?

I have seen some hide methods in
/** #hide */
public void setDiscoverableTimeout(int timeout) {
if (getState() != STATE_ON) return;
try {
mService.setDiscoverableTimeout(timeout);
} catch (RemoteException e) {Log.e(TAG, "", e);}
}
I want to use the above method but still not aware that how can I use this method in my program so that my app should be always in discoverable mode?
you can use reflections, i have been using it. The only flip side is it may be google doesn't provide any guarantee for it.

Categories

Resources