Reputation: 371
I'm developing a simple Kiosk Mode application for Android 6.0. I have everything working on devices from Xiaomi, HTC, Lenovo, etc. but I can't get one feature working on any Samsung device.
The feature is automatic closing of every system system dialog using
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);
This is broadcasted from a Service.
On my other, non-samsung devices, everything works and all system dialogs closes, but on any Samsung device (S5, S6 edge, ...) this broadcast gets ignored and for example the app drawer stays opened.
I've observed that even using ADB to broadcast this intent, app drawer stays opened, but for example the shutdown device dialog gets closed if I broadcast this from adb.
Please note that this is not malicious action in context of this software, this is for client, that requires this feature and it is completely solicited.
I've done research on Samsung Knox, but we would have to obtain their license for using the Knox Standard SDK and that is not something that is in the scope of this project.
So my question is: Do you have any idea how to make this work (closing the app drawer with ACTION_CLOSE_SYSTEM_DIALOGS intent) on samsung devices with Knox installed?
Thanks.
Upvotes: 11
Views: 1312
Reputation: 900
The problem with the most commonly found solution is that dialogs are totally different window, so you need to override the onWindowsFocusChanged on them as well. That can lead to a lot of work, plus the menu also open the same flaw to call the power menu.
The best solution I found is to implement a service to close the system dialogs when a long press of the power key is detected. I tested on couple of LG devices (Android 5.1.1 and 6.0) and calling this from a service was working just fine:
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
But on Samsung tablets (Android 5.1.1) it did not work, after trying few different solutions with no luck. I finally got it working when send an intent to an activity and make the activity send the broadcast:
Add this to your manifest:
<service
android:name="com.mypackage.services.PowerButtonService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.SYSTEM_ALERT_WINDOW"
android:stopWithTask="true"/>
<activity
android:name="com.mypackage.activities.CloseSystemDialogActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="CloseSystemDialogActivity.ACTION_CLOSE_DIALOGS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
The service:
public class PowerButtonService extends Service {
private View view;
private WindowManager windowManager;
@Override
public void onCreate() {
super.onCreate();
LinearLayout linearLayout = new LinearLayout(getApplicationContext()) {
@SuppressWarnings("unused")
public void onCloseSystemDialogs(String reason) {
if ("globalactions".equals(reason)) {
final Intent intent = new Intent(CloseSystemDialogActivity.ACTION_CLOSE_DIALOGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
};
linearLayout.setFocusable(true);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(100, 100, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
params.gravity = Gravity.START | Gravity.CENTER_VERTICAL;
view = LayoutInflater.from(this).inflate(R.layout.empty, linearLayout);
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
windowManager.addView(view, params);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
// VERY IMPORTANT
windowManager.removeView(view);
}
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
return START_STICKY;
}
}
Dummy activity:
public class CloseSystemDialogActivity extends Activity {
public static final String ACTION_CLOSE_DIALOGS = "CloseSystemDialogActivity.ACTION_CLOSE_DIALOGS";
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
finish();
}
}
Notice that you NEED to START and STOP the service otherwise when your application is not running (out of kiosk mode) you might not be able to call the power menu if you need to.
Upvotes: 0
Reputation: 783
Try doing it like this :
@Override
public void onWindowFocusChanged(boolean focus) {
super.onWindowFocusChanged(focus);
if (! focus) {
Intent close= new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(close);
}
}
Upvotes: 3