【问题标题】:Android - Play sound from assets without android.permission.WRITE_EXTERNAL_STORAGEAndroid - 从没有 android.permission.WRITE_EXTERNAL_STORAGE 的资产中播放声音
【发布时间】:2014-02-26 14:52:08
【问题描述】:

对于我们用 Adob​​e AIR 编写的游戏,我们希望游戏中的声音之一是当我们在 Android 上显示本地通知或推送通知时的通知声音。

目前我们有一个我们不太满意的解决方案,如下所示,因为它需要额外的 Android 权限,我们认为这是不必要的。基本上,您传递资产路径,例如“audio/core/reward.mp3”,它位于根“assets”文件夹中,然后在 Android 端,它将该文件拉出到 InputStream 中,将其写入文件在外部存储上,Android 的 MediaPlayer 从那里播放。

显然,当您在 Android 上播放文件时,AIR 肯定不会这样做,因为您不需要“WRITE_EXTERNAL_STORAGE”来播放声音,因此对于我们的情况,当应用程序当前未在运行时,而是Push Notification 进来了,我怎么能播放这个在 AS3 端打包和使用的文件?

推荐的做法是,

    MediaPlayer m = new MediaPlayer();
    AssetFileDescriptor afd = context.getAssets().openFd(soundPath);
    m.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
    m.prepare();
    m.setVolume(1f, 1f);
    m.start();
    playSound = false;

但这不适用于错误

 java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed

所以我需要做不喜欢的方法,

public static void HandleMessage(Context context, CharSequence title, CharSequence message, String soundPath)
{
    log("HandleMessage (message: '" + message + "', title: '" + title +"', icon: " + Extension.getIcon(context) + ", class: " + Extension.getEntryClass(context));
    long when = System.currentTimeMillis();

    NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    Intent notificationIntent = new Intent(context, Extension.getEntryClass(context));

    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(context)
        .setContentText(message)
        .setContentIntent(contentIntent)
        .setTicker(message)
        .setSmallIcon(Extension.getIcon(context))
        .setWhen(when)
        .setAutoCancel(true)
        .setVibrate(new long[] { 1000, 400 })
        .build();

    Boolean playSound = true;
    if(null != soundPath && "" != soundPath)
    {
        try {
            MediaPlayer m = new MediaPlayer();
            String newPath = checkWriteFile(context, soundPath);
            log(newPath);
            if(null != newPath)
            {
                m.setDataSource(newPath);
                m.prepare();
                m.setVolume(1f, 1f);
                m.start();
                playSound = false;
            }
        } catch (IOException e) {
            log(e.getLocalizedMessage());
            e.printStackTrace();
        }
    }
    if(playSound)
    {
        notification.sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    }

    nm.notify(NotifId, notification);

    NotifId++;
}

public static String checkWriteFile(Context context, String relPath)
{
    Boolean exists = false;
    String newPath = null;
    String fullPath = Environment.getExternalStorageDirectory().getPath() + "/" + context.getPackageName() + "/temp/" + relPath;
    int index = fullPath.lastIndexOf("/") + 1;
    String file = fullPath.substring(index);
    String path = fullPath.substring(0, index);
    log(relPath + ", " + fullPath + ", " + (new File(fullPath)).exists());

    if (!(new File(fullPath)).exists()) {
        try {
            byte[] buffer = null;
            InputStream fIn = context.getAssets().open(relPath);
            log("InputStream: " + fIn);

            int size=0;

            try {
                size = fIn.available();
                buffer = new byte[size];
                fIn.read(buffer);
                fIn.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            exists = (new File(path)).exists();
            if (!exists) {
                new File(path).mkdirs();
            }

            FileOutputStream save;
            try {
                save = new FileOutputStream(path + file);
                save.write(buffer);
                save.flush();
                save.close();
                newPath = fullPath;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        catch (Exception e) {
            log(e.getLocalizedMessage());
            e.printStackTrace();
        }
    }
    else {
        newPath = fullPath;
    }

    return newPath;
}

【问题讨论】:

  • 您可以将其提取到内部存储而不是外部存储。
  • @njzk2 我的话,我感觉多么愚蠢!请将此添加为答案,我会接受。非常感谢。

标签: android actionscript-3 audio air


【解决方案1】:

如果您想避免android.permission.WRITE_EXTERNAL_STORAGE,您可以将文件提取到内部存储而不是外部存储。

String fullPath = Environment.getExternalStorageDirectory() (...)

可以替换为

String fullPath = context.getFilesDir() (...)

【讨论】:

  • 因为这是一个很小的文件,如果在任何阶段删除它都可以,我实际上是用 getCacheDir() 代替。再次感谢您的帮助和指点,非常感谢。
猜你喜欢
  • 2012-06-13
  • 2015-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多