web-dev-qa-db-fra.com

MediaPlayer setDataSource a échoué avec status = 0x80000000 pour la sonnerie définie par le chemin de fichier sur 2.3.4

Le titre en dit le plus.

Mon application a joué des sonneries pointées par uri comme content://media/internal/audio/media/387 Ou content://media/external/audio/media/1655 (Pour les sonneries personnalisées sur SDcard je crois) en utilisant à la fois setDataSource(fileInfo) et setDataSource(mContext, Uri.parse(fileInfo)).

Dans chaque cas, j'ai reçu des journaux contenant des informations sur l'exception setDataSource failed.: status=0x80000000 Sur les téléphones utilisant Android 4.x (différentes versions).

Voyant que l'erreur ne se produit que pour les sonneries pointées par le contenu uri, mais pas pour les fichiers uniques pointés par le chemin, j'ai décidé d'utiliser également des chemins pour les sonneries qui ont résolu le problème sur les téléphones ci-dessus (tout en utilisant setDataSource(mContext, Uri.parse(fileInfo)))

Il a cependant commencé des problèmes sur les téléphones avec Android 2.3.4-2.3.6 (pas sur le mien 2.3.3 cependant):

  • J'ai reçu quelques journaux à l'exception: setDataSource failed.: status=0x80000000 Pour les fichiers avec des chemins comme /system/media/audio/ringtones/TwirlAway.ogg
  • J'ai également reçu un journal sur l'appel de méthode MediaPlayer.onErrorListener.onError(int what, int extra) avec what=1 Et extra=-2147483648, Qui, d'après ce que je sais, suggère que ce fichier est manquant ou qu'il est corrompu. Cependant je joue

    File file = new File(fileInfo);
    if (!file.exists())
    

vérifier dans une telle situation et il a retourné que le fichier existe - est-il corrompu alors? Très peu probable pour un fichier musical dans la mémoire interne.

Pour résumer:

  • fonctionne avec setDataSource("content://media/internal/audio/media/52")
  • lève une exception: setDataSource failed.: status=0x80000000 pour setDataSource(mContext, "/system/media/audio/ringtones/TwirlAway.ogg")

Fait intéressant, les premières lignes de la méthode setDataSource(Context context, Uri uri, Headers headers) qui est appelée par setDataSource(Context context, Uri uri) sont ( à partir de la source GrepCode pour 2.3.4 ):

 String scheme = uri.getScheme();
     if(scheme == null || scheme.equals("file")) {
         setDataSource(uri.getPath());
         return;
     }

Donc, après tout, cela échoue pour setDataSource("/system/media/audio/ringtones/TwirlAway.ogg"). J'ai suivi les sonneries des uris en utilisant:

private static String getRingtonePathFromContentUri(Context context,
        Uri contentUri) {

    String[] proj = { MediaStore.Audio.Media.DATA };
    Cursor ringtoneCursor = context.getContentResolver().query(contentUri,
            proj, null, null, null);
    ringtoneCursor.moveToFirst();
    return ringtoneCursor.getString(ringtoneCursor
            .getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
}

Des idées sur ce qui peut être à l'origine d'une erreur de lancement? Peut-être que ce sont des problèmes causés par le manque d'autorisations de lecture? Je suppose que le code source de la fonction native setDataSource (String path) aiderait beaucoup, mais je n'ai pas pu le trouver.

20
Koger

La réponse de Lorne ci-dessous a été très utile pour résoudre ce problème.

Pour toute autre personne aux prises avec ce problème, voici le code que j'utilise depuis plus de 6 mois avec des erreurs presque non signalées.

fileinfo peut être les deux ci-dessous (exemples):

/system/media/audio/alarms/Walk_in_the_forest.ogg

content://media/internal/audio/media/20

public static void setMediaPlayerDataSource(Context context,
        MediaPlayer mp, String fileInfo) throws Exception {

    if (fileInfo.startsWith("content://")) {
        try {
            Uri uri = Uri.parse(fileInfo);
            fileInfo = getRingtonePathFromContentUri(context, uri);
        } catch (Exception e) {
        }
    }

    try {
        if (Android.os.Build.VERSION.SDK_INT < Android.os.Build.VERSION_CODES.HONEYCOMB)
            try {
                setMediaPlayerDataSourcePreHoneyComb(context, mp, fileInfo);
            } catch (Exception e) {
                setMediaPlayerDataSourcePostHoneyComb(context, mp, fileInfo);
            }
        else
            setMediaPlayerDataSourcePostHoneyComb(context, mp, fileInfo);

    } catch (Exception e) {
        try {
            setMediaPlayerDataSourceUsingFileDescriptor(context, mp,
                    fileInfo);
        } catch (Exception ee) {
            String uri = getRingtoneUriFromPath(context, fileInfo);
            mp.reset();
            mp.setDataSource(uri);
        }
    }
}

private static void setMediaPlayerDataSourcePreHoneyComb(Context context,
        MediaPlayer mp, String fileInfo) throws Exception {
    mp.reset();
    mp.setDataSource(fileInfo);
}

private static void setMediaPlayerDataSourcePostHoneyComb(Context context,
        MediaPlayer mp, String fileInfo) throws Exception {
    mp.reset();
    mp.setDataSource(context, Uri.parse(Uri.encode(fileInfo)));
}

private static void setMediaPlayerDataSourceUsingFileDescriptor(
        Context context, MediaPlayer mp, String fileInfo) throws Exception {
    File file = new File(fileInfo);
    FileInputStream inputStream = new FileInputStream(file);
    mp.reset();
    mp.setDataSource(inputStream.getFD());
    inputStream.close();
}

private static String getRingtoneUriFromPath(Context context, String path) {
    Uri ringtonesUri = MediaStore.Audio.Media.getContentUriForPath(path);
    Cursor ringtoneCursor = context.getContentResolver().query(
            ringtonesUri, null,
            MediaStore.Audio.Media.DATA + "='" + path + "'", null, null);
    ringtoneCursor.moveToFirst();

    long id = ringtoneCursor.getLong(ringtoneCursor
            .getColumnIndex(MediaStore.Audio.Media._ID));
    ringtoneCursor.close();

    if (!ringtonesUri.toString().endsWith(String.valueOf(id))) {
        return ringtonesUri + "/" + id;
    }
    return ringtonesUri.toString();
}

public static String getRingtonePathFromContentUri(Context context,
        Uri contentUri) {
    String[] proj = { MediaStore.Audio.Media.DATA };
    Cursor ringtoneCursor = context.getContentResolver().query(contentUri,
            proj, null, null, null);
    ringtoneCursor.moveToFirst();

    String path = ringtoneCursor.getString(ringtoneCursor
            .getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));

    ringtoneCursor.close();
    return path;
}
11
Koger

Le comportement de setDataSource(String path) a été modifié en raison d'une correction de bogue dans Android 4.1.1. Dans 4.1.1 ou version ultérieure, vous devez utiliser un chemin local (sans Cependant, sur les versions 4.0.4 et antérieures, vous deviez utiliser un URI (par exemple avec le protocole file: //).

Voici un extrait de code incomplet qui devrait illustrer la solution:

// as of 4.1.1 (JELLY_BEAN) we need to use a local path (without protocol)
// on 4.0.4 and earlier we needed a URI (with file:// protocol)
final String cachedFile = Android.os.Build.VERSION.SDK_INT >= 16 // Android.os.Build.VERSION_CODES.JELLY_BEAN
                        ? getCacheFilePath(file)
                        : getCacheFileUri(file);


// for the purpose of this example 
// assume cacheFolder is a String and getCacheFile returns a String

public String getCacheFilePath(String file) {
    return cacheFolder + getCacheFile(file);
}

public String getCacheFileUri(String file) {
    return "file://" + cacheFolder + getCacheFile(file);
}
4
Lorne Laliberte

Cela peut se produire en raison du format de fichier que vous essayez de lire ou de compresser. Je compressais un fichier mp4 qui fonctionne bien, mais lorsque j'ai compressé un fichier mov, l'application s'est bloquée, ce qui a provoqué l'échec de setDataSource.

1
VIVEK CHOUDHARY

Vous devez définir explicitement la longueur de votre fichier. Utilisez la méthode surchargée:
AssetFileDescriptor afd = ctx.getAssets().openFd([your asset name]); mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());

1
Subtle Fox

J'ai eu la même erreur lorsque j'essayais de lire un fichier .wav. Faisons un exemple:

 private void start_player(){
// create raw folder inside the res folder if not present
MediaPlayer mPlayer = MediaPlayer.create(activity, R.raw.your_wave_audio_file);
        mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mPlayer.setOnCompletionListener(new OnCompletionListener() {

            @Override
            public void onCompletion(MediaPlayer mp) {
                mp.release();
               // Your Stuff
            }
        });  
         mPlayer.start();
     }
    }

J'ai aussi eu l'erreur status = 0x80000000. Dans mon cas, la solution a été de ré-encoder le fichier audio (par exemple en PCM 16 bits pour un fichier .wav) et tout a fonctionné comme prévu.

0
Dennis Allert
MediaPlayer mPlayer = MediaPlayer.create(activity, R.raw.your_wave_audio_file);
    mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

Vous ne pouvez pas le faire, car prepare a été appelé dans la fonction create, vous ne pouvez donc pas changer le type de flux audio après.

Le code ci-dessous fonctionne bien pour moi:

sMediaPlayer = new MediaPlayer();
sMediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
AssetFileDescriptor assetFileDescriptor = context.getResources().
         openRawResourceFd(R.raw.cool_song);

 if(assetFileDescriptor == null) return;

 try {
    sMediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(),
                               assetFileDescriptor.getStartOffset(), 
                               assetFileDescriptor.getLength());
    assetFileDescriptor.close();

    sMediaPlayer.setOnCompletionListener(new OnCompletionListener() {           
        @Override
        public void onCompletion(MediaPlayer mp) {
            if(sMediaPlayer != null){
                sMediaPlayer.release();
                sMediaPlayer = null;
            }
        }
    });

    sMediaPlayer.setOnPreparedListener(new OnPreparedListener() {               
        @Override
        public void onPrepared(MediaPlayer mp) {
            sMediaPlayer.start();                   
        }
    });
    sMediaPlayer.prepare();

} catch (IllegalArgumentException e) {
    HelpFunctions.showLog("ERROR = " + e);
} catch (IllegalStateException e) {
    HelpFunctions.showLog("ERROR = " + e);
} catch (IOException e) {
    HelpFunctions.showLog("ERROR = " + e);
}
0
Taras Okunev