J'utilise le code ci-dessous pour récupérer le fond d'écran d'écran de verrouillage Android sur un téléphone Android 8.1:
WallpaperManager manager = WallpaperManager.getInstance(getActivity());
ParcelFileDescriptor pfd = manager.getWallpaperFile(WallpaperManager.FLAG_LOCK);
if (pfd == null) // pfd is always null for FLAG_LOCK, why?
return;
Bitmap lockScreenWallpaper = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
// ...
J'ai accordé la permission READ_EXTERNAL_STORAGE
et défini un fond d'écran de verrouillage au préalable.
J'ai lancé la démo sur un vrai téléphone et j'ai trouvé que la pfd
est toujours nulle pour FLAG_LOCK
. S'il vous plaît aider à résoudre le problème, merci.
Je trouve la réponse moi-même, j'espère que cela pourra aider les autres avec la même question.
La documentation officielle de getWallpaperFile dit: If no lock-specific wallpaper has been configured for the given user, then this method will return null when requesting FLAG_LOCK rather than returning the system wallpaper's image file.
La description est vague, du moins pas assez claire, ça veut dire quoi? Si vous définissez une photo comme écran de verrouillage et comme papier peint de l'écran d'accueil, les deux partagent le même fichier, puis en appelant
ParcelFileDescriptor pfd = wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_LOCK);
pfd
sera toujours null, vous devriez alors obtenir le fond d'écran de verrouillage:
if (pfd == null)
pfd = wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_SYSTEM);
vous obtiendrez la variable non nulle pfd
. C'est le cas no lock-specific wallpaper has been configured.
Au contraire, lock-specific wallpaper has been configured
si vous définissez directement une photo comme fond d'écran d'écran de verrouillage, wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_SYSTEM)
renvoie une valeur non nulle.
C'est donc le code que j'utilise pour récupérer le fond d'écran de l'écran de verrouillage:
/**
* please check permission outside
* @return Bitmap or Drawable
*/
public static Object getLockScreenWallpaper(Context context)
{
WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
if (Build.VERSION.SDK_INT >= 24)
{
ParcelFileDescriptor pfd = wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_LOCK);
if (pfd == null)
pfd = wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_SYSTEM);
if (pfd != null)
{
final Bitmap result = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
try
{
pfd.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return result;
}
}
return wallpaperManager.getDrawable();
}
N'oubliez pas d'ajouter READ_EXTERNAL_STORAGE
dans le fichier manifeste et d'accordez-le à l'extérieur.
Le code que j'ai testé est similaire au vôtre. Je l'ai testé sur Samsung A5 et LG Nexus 5X.
MainActivity.Java
import Android.Manifest;
import Android.annotation.SuppressLint;
import Android.app.WallpaperManager;
import Android.content.pm.PackageManager;
import Android.graphics.Bitmap;
import Android.graphics.BitmapFactory;
import Android.os.Build;
import Android.os.Bundle;
import Android.os.ParcelFileDescriptor;
import Android.support.v4.app.ActivityCompat;
import Android.support.v4.content.ContextCompat;
import Android.support.v7.app.AppCompatActivity;
import Android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
public static final int REQUEST_CODE_EXTERNAL_STORAGE = 5;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
permission = Manifest.permission.READ_EXTERNAL_STORAGE;
}
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{permission}, REQUEST_CODE_EXTERNAL_STORAGE);
} else {
retrieveLockScreenWallpaper();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_EXTERNAL_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
retrieveLockScreenWallpaper();
}
}
}
}
@SuppressLint("MissingPermission")
private void retrieveLockScreenWallpaper() {
if (Android.os.Build.VERSION.SDK_INT >= Android.os.Build.VERSION_CODES.N) {
WallpaperManager manager = WallpaperManager.getInstance(getApplicationContext());
ParcelFileDescriptor descriptor = manager.getWallpaperFile(WallpaperManager.FLAG_LOCK);
if (descriptor != null) {
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor());
((ImageView) findViewById(R.id.imageView)).setImageBitmap(bitmap);
}
}
}
}
manifest.xml
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="aminography.com.lockscreenapplication">
<uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />
<application
...
</application>
</manifest>
.
Résultat sur LGE Nexus 5X (Android 8.1.0, API 27):
Si aucun papier peint spécifique à un verrou n'a été configuré pour l'utilisateur donné, cette méthode retournera la valeur null lors de la demande de FLAG_LOCK plutôt que de retourner le fichier image du papier peint du système.
Êtes-vous sûr de disposer d'un fond d'écran valide pour l'écran de verrouillage défini pour l'utilisateur actuel?
/**
* Get an open, readable file descriptor to the given wallpaper image file.
* The caller is responsible for closing the file descriptor when done ingesting the file.
*
* <p>If no lock-specific wallpaper has been configured for the given user, then
* this method will return {@code null} when requesting {@link #FLAG_LOCK} rather than
* returning the system wallpaper's image file.
*
* @param which The wallpaper whose image file is to be retrieved. Must be a single
* defined kind of wallpaper, either {@link #FLAG_SYSTEM} or
* {@link #FLAG_LOCK}.
*
* @see #FLAG_LOCK
* @see #FLAG_SYSTEM
*/
public ParcelFileDescriptor getWallpaperFile(@SetWallpaperFlags int which) {
return getWallpaperFile(which, mContext.getUserId());
}
Il existe une fonction similaire dans WallpaperManager openDefaultWallpaper, à savoir que si vous voulez un papier peint LOCK-SCREEN, vous obtenez toujours la valeur null, car, conformément au code, les papiers peints à verrouillage par défaut ne sont pas encore pris en charge.
Donc, dans votre cas, vous n'avez peut-être pas défini le fond d'écran de l'écran verrouillé… .. Juste pour tester, télécharger une application de fond d'écran et essayer de définir un fond d'écran, puis utilisez votre code précédent pour l'obtenir.
/**
* Open stream representing the default static image wallpaper.
*
* If the device defines no default wallpaper of the requested kind,
* {@code null} is returned.
*
* @hide
*/
public static InputStream openDefaultWallpaper(Context context, @SetWallpaperFlags int which) {
final String whichProp;
final int defaultResId;
if (which == FLAG_LOCK) {
/* Factory-default lock wallpapers are not yet supported
whichProp = PROP_LOCK_WALLPAPER;
defaultResId = com.Android.internal.R.drawable.default_lock_wallpaper;
*/
return null;
}
Vous pouvez vérifier le code à l’adresse: http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/Java/Android/app/WallpaperManager.Java#openDefaultWallpaper