J'essaie de créer une vue qui se situe au-dessus des autres applications:
WindowManager.LayoutParams paramsDirectorView = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
J'ai regardé dans d'autres réponses et trouvé les choses suivantes pour "dessiner sur des applications":
J'obtiens toujours l'erreur "- autorisation refusée pour le type de fenêtre 2038". A partir de maintenant, j'utilise TYPE_PHONE et cela fonctionne, mais il est déconseillé et dit d'utiliser TYPE_APPLICATION_OVERLAY. Quelqu'un peut-il faire un suivi sur cette question en tant que réponse TYPE_PHONE n'est pas vraiment une résolution, mais une solution «correctif» déconseillée dans Android O.
Je cours sur Android 7.1.2
Android.view.WindowManager $ BadTokenException: impossible d'ajouter une fenêtre Android.view.ViewRootImpl$W@1f47e89 - autorisation refusée pour la fenêtre tapez 2038 à Android.app.ActivityThread.handleServiceArgs (ActivityThread.Java:3344) sur Android.app.ActivityThread.-wrap21 (ActivityThread.Java) sur Android.app.ActivityThread $ H.handleMessage (ActivityThread.Java:1583) sur Android.os.Handler.dispatchMessage (Handler.Java:102) sur Android.os.Looper.loop (Looper.Java:154) à l'adresse Android.app.ActivityThread.main (ActivityThread.Java:6121) à Java.lang.reflect.Method.invoke (Méthode native) à com.Android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.Java:889) sur com.Android.internal.os.ZygoteInit.main (ZygoteInit.Java:779) Caused par: Android.view.WindowManager $ BadTokenException: impossible d’ajouter une fenêtre Android.view.ViewRootImpl$W@1f47e89 - autorisation refusée pour la fenêtre tapez 2038 sur Android.view.ViewRootImpl.setView (ViewRootImpl.Java:703) à Android.view.WindowManagerGlobal.addView (WindowManagerGlobal.Java:342) sur Android.view.WindowManagerImpl.addView (WindowManagerImpl.Java:93) à HeadService.TwoViewManager. (TwoViewManager.Java:99) à HeadService.UIHeadService.onStartCommand (UIHeadService.Java:65) à Android.app.ActivityThread.handleServiceArgs (ActivityThread.Java:3327) sur Android.app.ActivityThread.-wrap21 (ActivityThread.Java) sur Android.app.ActivityThread $ H.handleMessage (ActivityThread.Java:1583) sur Android.os.Handler.dispatchMessage (Handler.Java:102) sur Android.os.Looper.loop (Looper.Java:154) à l'adresse Android.app.ActivityThread.main (ActivityThread.Java:6121) à Java.lang.reflect.Method.invoke (Méthode native) à com.Android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.Java:889) sur com.Android.internal.os.ZygoteInit.main (ZygoteInit.Java:779)
J'ai eu exactement le même problème. Je suppose que vous devriez différencier la cible (avant et après Oreo)
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
<uses-permission Android:name="Android.permission.SYSTEM_ALERT_WINDOW" />
J'ai eu exactement le même problème en classe de service (avant et après Marshmallow).
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 1234);
}
} else {
startService(new Intent(SplashActivity.this,
CheckServicesForApps.class));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1234) {
startService(new Intent(SplashActivity.this,
CheckServicesForApps.class));
}
}
public class CheckServicesForApps extends Service {
private Context context = null;
@Override
public void onCreate() {
super.onCreate();
ImageView imageView = new ImageView(context);
imageView.setVisibility(View.GONE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
//here is all the science of params
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager. LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.TRANSLUCENT
);
windowManager.addView(imageView, params);
hand=new Handler();
} catch (Exception e) {
hand=new Handler();
e.printStackTrace();
}
}else{
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.CENTER;
params.x = ((getApplicationContext().getResources().getDisplayMetrics().widthPixels) / 2);
params.y = ((getApplicationContext().getResources().getDisplayMetrics().heightPixels) / 2);
windowManager.addView(imageView, params);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
/* We want this service to continue running until it is explicitly
* stopped, so return sticky.
*/
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
if (imageView != null) {
try {
windowManager.removeView(imageView);
} catch (Exception e) {
e.printStackTrace();
}
}
/**** added to fix the bug of view not attached to window manager ****/
}
}
Avez-vous demandé une autorisation d'exécution en appelant l'intention suivante?
private void requestOverlayPermission() {
if (Android.os.Build.VERSION.SDK_INT < Android.os.Build.VERSION_CODES.M) {
return;
}
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
myIntent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(myIntent, APP_PERMISSIONS);
}
Puis dans onActivityResult () , vérifiez si Settings.canDrawOverlays (this) est à true, sinon demandez à nouveau l'autorisation en appelant la méthode ci-dessus.
Source SYSTEM_ALERT_WINDOW String SYSTEM_ALERT_WINDOW Permet à une application de créer des fenêtres en utilisant le type TYPE_APPLICATION_OVERLAY, affiché en haut de toutes les autres applications. Très peu d'applications devraient utiliser cette autorisation. ces fenêtres sont conçues pour une interaction au niveau du système avec l'utilisateur.
Remarque: si l'API de l'application cible de niveau 23 ou supérieur, l'utilisateur de l'application doit explicitement accorder cette autorisation à l'application via un écran de gestion des autorisations. L'application demande l'approbation de l'utilisateur en envoyant une intention avec l'action ACTION_MANAGE_OVERLAY_PERMISSION. L'application peut vérifier si elle dispose de cette autorisation en appelant Settings.canDrawOverlays ().
Essayez de changer WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
en WindowManager.LayoutParams.TYPE_PHONE
?