Par sticky, j'entends une fenêtre qui ne se ferme pas en appelant l'intention du lanceur ( intent.addCategory (Intent.CATEGORY_HOME ).
Auparavant, cela était fait avec WindowManager. LayoutParams.TYPE_PHONE , mais ce type est désormais obsolète et lève une exception sur l'API 28:
WindowManager $ BadTokenException ... autorisation refusée pour le type de fenêtre 2002
Le comportement est toujours possible puisque Messenger de Facebook le fait avec son chat "Heads", basé sur l'hypothèse que Facebook n'obtient pas les autorisations d'application système car il est pré-installé sur beaucoup de roms. p>
L'utilisation de WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY ne fonctionne pas (c'est-à-dire que le fait d'appuyer sur le bouton d'accueil masque également la fenêtre de superposition).
Modifier : La question est de savoir comment avoir une fenêtre de superposition qui ne soit pas supprimée lorsque l'utilisateur clique sur le bouton d'accueil / appelle l'intention du lanceur. Ce n'est pas le cas pour TYPE_APPLICATION_OVERLAY , c'était le cas pour TYPE_PHONE mais c'est obsolète.
Edit 2: Apparemment ceci fonctionne pour certaines personnes, voici le code que j'exécute:
class MyClass {
var params: WindowManager.LayoutParams = WindowManager.LayoutParams(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
else WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT
).apply {
windowAnimations = android.R.style.Animation_Dialog
gravity = Gravity.CENTER or Gravity.CENTER
x = 0
y = 0
}
var windowManager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
init {
val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
rootView = layoutInflater.inflate(R.layout.view_overlay, null)
windowManager.addView(rootView, params)
}
}
3 Réponses :
Dans Manifest , ajoutez l'autorisation
<service
android:name=".MyWidget"
android:enabled="true"
android:exported="false"/>
Dans l'activité du lanceur, vous devriez demander des canDrawOverlays Permissions`
//Inflate the floating view layout
mFloatingView =
LayoutInflater.from(this).inflate(R.layout.layout_floating_widget, null);
int LAYOUT_TYPE;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_PHONE;
}
//Add the view to the window.
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG ,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
//Specify the view position
params.gravity = Gravity.TOP | Gravity.LEFT; //Initially view will be added to top-left corner
params.x = 0;
params.y = 100;
//Add the view to the window
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mWindowManager.addView(mFloatingView, params);
Ensuite, dans votre service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
!Settings.canDrawOverlays(this)) {
//If the draw over permission is not available open the settings screen
//to grant the permission.
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, CODE_DRAW_OVER_OTHER_APP_PERMISSION);
} else {
initializeView();
}
Cela ne sera pas ignoré lorsque l'utilisateur appuiera sur la touche Accueil . P >
Assurez-vous que votre widget flottant est défini comme service sinon il ne pourra pas survivre en cas de problème de mémoire faible / de changement de configuration.
Enregistrez également le service dans le manifeste
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
J'ai essayé cela sur l'API 28 et cela ne fonctionne pas, c'est-à-dire qu'il est rejeté lorsque vous appuyez sur Accueil
J'ai essayé ceci sur Oreo et Pie, ça marche toujours pour moi. Veuillez poster votre code
Cela ne fonctionne pas pour le bouton d'accueil logiciel. Par exemple, des appareils à pixels.
@ user2511882 Je l'avais testé sur Pixel et POCO F1, fonctionnant toujours
L'ajout de android: enabled = "true" et android: exports = "false" au service ne fonctionne pas
Réf: https://developer.android.com/reference /android/view/WindowManager.LayoutParams.html
TYPE_PHONE if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, APP_PERMISSION_REQUEST);
}
else
{
//start service
}
Cette constante était obsolète au niveau de l'API 26 strong>.
pour les applications non système. Utilisez plutôt TYPE_APPLICATION_OVERLAY.
Type de fenêtre: téléphone. Ce sont des fenêtres non applicatives permettant une interaction de l'utilisateur avec le téléphone (en particulier les appels entrants). Ces fenêtres sont normalement placées au-dessus de toutes les applications, mais derrière la barre d'état. Dans les systèmes multi-utilisateurs s'affiche sur toutes les fenêtres des utilisateurs.
TYPE_APPLICATION_OVERLAY <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> //...other stuff <service android:name=".serviceClass" android:enabled="true" android:exported="false"/>
Type de fenêtre: les fenêtres de superposition d'application sont affichées au-dessus de toutes les fenêtres d'activité ( types entre FIRST_APPLICATION_WINDOW et LAST_APPLICATION_WINDOW ) mais en dessous des fenêtres système critiques comme la barre d'état ou l'IME.
Le système peut changer la position, la taille ou la visibilité de ces fenêtres à tout moment pour réduire l'encombrement visuel de l'utilisateur et également gérer les ressources.
Nécessite l'autorisation Manifest.permission.SYSTEM_ALERT_WINDOW .
//if device is Oreo or latter if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
//or else
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);
Ce n'est pas différent de ce que j'ai.
@JohnSardinha avez-vous essayé ce code? et si cela ne fonctionne pas, laissez-moi voir bcz j'ai une application qui s'exécute sur playstore avec ce code
Je l'ai essayé, cela n'a pas fonctionné, quelle version de sdk ciblez-vous?
compileSdkVersion 28 minSdkVersion 19 targetSdkVersion 28
Lorsque votre superposition est affichée et que vous appuyez sur le bouton d'accueil, cela ne ferme pas votre superposition?
j'utilise le service pour ajouter un widget à l'écran
@JohnSardinha première fois que j'ai suivi cet exemple journaldev.com/14673/android-floating-widget < / a> puis j'ai modifié comme ovr requiment
Oui, votre application fonctionne bien, comment obtenir la permission de dessiner sur d'autres applications par défaut?
actuellement, je n'ai pas de code source parce que je suis à la maison, donc je vous suggère d'utiliser ce journaldev. com / 14673 / android-floating-widget et modifiez-le au fur et à mesure de votre utilisation.
J'ai essayé votre code et cela n'a pas fonctionné, je pourrais peut-être identifier ce qui est différent du code complet? Si vous l'avez ouvert bien sûr
Solution: ne gonflez pas votre superposition directement sur d'autres applications.
Normalement, l'utilisation de TYPE_APPLICATION_OVERLAY se comporte toujours comme TYPE_PHONE , le problème avec mon cas était que j'affichais ma vue ( windowManager.addView (rootView, params) ) lorsqu'une activité d'une autre application était au premier plan et qu'Android associe la vue à l'activité de premier plan actuelle, donc lorsque l'utilisateur quitte cette activité (en appuyant sur le bouton d'accueil par exemple), le système tue également la superposition depuis mon application. Une solution pour moi était très spécifique, je n'ai pas de solution générale mais avec cette information devrait aider les gens à en trouver une.
L'utilisateur doit accorder la permission de «dessiner sur d'autres applications» par application. C'est à l'implémentation de la ROM de mettre en place des exceptions comme l'octroi par défaut à Messenger. Vous pouvez vérifier rapidement si elle est accordée pour votre application en utilisant
Settings.canDrawOverlays ().@ManojPerumarath 28
Dupliquer: stackoverflow.com/questions/46208897/...
Hé, essayez ma réponse mise à jour
@Maxouille Je n'obtiens pas l'erreur "permission refusée", ni aucune erreur, ce n'est pas la même question que ça.
Ce problème se produit-il uniquement sur des appareils spécifiques?
canDrawOverlaysdoit être activé, si possible partager un GitHub de cette partie spécifique@ManojPerumarath essaiera votre solution mise à jour plus tard dans la journée! J'ai essayé sur mon appareil et sur 2 émulateurs, je ne pense pas que ce soit spécifique à l'appareil.