簡體   English   中英

Android MediaPlayer return Prepare failed.: status=0x1 on device but running in emulator

[英]Android MediaPlayer return Prepare failed.: status=0x1 on device but runs in emulator

我正在嘗試通過MediaPlayer播放來自遠程http uri 的音頻流。 如果我嘗試在設備上播放.prepare()調用失敗並拋出 IO 異常,代碼似乎在模擬器音頻 stream 播放(但有一些噪音)中工作正常。 消息報告: status=0x1 我發現的唯一與此錯誤相關的文章是關於文件的讀/寫權限,我認為情況並非如此,其他一些與錯誤的調用序列(.setDataSource、.prepare()、.start())相關的文章也不是這應該是我的問題。

這是我正在使用的代碼:

public class MainActivity extends AppCompatActivity {
    public static final String KEY_ADDRESS = "address";
    private static final int REQUEST_INTERNET = 21;

    private ImageButton exit_button;
    private ImageButton stop_button;
    private ImageButton play_button;

    private MediaPlayer media_player;

    private String uri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        boolean _skip_init = false;

        int check_internet = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.INTERNET);

        if (check_internet != PackageManager.PERMISSION_GRANTED) {
            Log.i(getClass().getName(), "asking for internet access permission");
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.INTERNET},
                    REQUEST_INTERNET);

            _skip_init = true;
        }

        getSettings(this); // set uri 

        exit_button = findViewById(R.id.exit_button);
        play_button = findViewById(R.id.play_button);
        stop_button = findViewById(R.id.stop_button);

        exit_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        play_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //TODO: start play
                if(media_player!=null) {
                    media_player.start();
                    disablePlay();
                }
            }
        });

        stop_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //TODO: stop play
                if(media_player!=null){
                    media_player.stop();
                    media_player.reset();
                    initStreaming(uri);
                    enablePlay();
                }
            }
        });

        play_button.setEnabled(false);
        stop_button.setEnabled(false);
        play_button.setAlpha(0.5f);
        stop_button.setAlpha(0.5f);

        if(!_skip_init) {
            initMediaPlayer(this);
            initStreaming(uri);
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if ((requestCode == REQUEST_INTERNET) && (grantResults.length > 0)) {
            for (int i = 0; i < permissions.length; i++)
                if ((grantResults[i] == PackageManager.PERMISSION_GRANTED)) {
                    Log.i(getClass().getName(), permissions[i] + " permission granted");

                    if (Manifest.permission.INTERNET.equals(permissions[i])) {
                        initMediaPlayer(this);
                        initStreaming(uri);
                    }
                }
        }
    }

    private void initMediaPlayer(@NonNull final Context context) {
        media_player = new MediaPlayer();
        media_player.setAudioStreamType(AudioManager.STREAM_MUSIC);

        media_player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                Log.d(getClass().getName(), "onPreparedListener");
                play_button.setEnabled(true);
                play_button.setAlpha(1f);
            }
        });

        media_player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                Log.d(getClass().getName(), "onCompletionListener");
                Toast.makeText(context, getString(R.string.streaming_completed), Toast.LENGTH_LONG).show();
            }
        });
    }

    private void initStreaming(@NonNull final String uri) {
        new Thread(
            new Runnable() {
                @Override
                public void run() {
                    try {
                       media_player.setDataSource(uri);
                       media_player.prepareAsync();
                    } catch (Throwable e) {
                       Log.e(getClass().getName(), "Exception: " + e.getMessage());
                    }
                }
           }
       ).start();
    }

    @Override
    protected void onDestroy() {
        //TODO: stop and free resources?
        Log.d(getClass().getName(), "onDestroy");

        if(media_player!=null && media_player.isPlaying())
            media_player.stop();

        super.onDestroy();
    }

    private void enablePlay() {
        play_button.setEnabled(true);
        stop_button.setEnabled(false);
        play_button.setAlpha(1f);
        stop_button.setAlpha(0.5f);
    }

    private void disablePlay() {
        play_button.setEnabled(false);
        stop_button.setEnabled(true);
        play_button.setAlpha(0.5f);
        stop_button.setAlpha(1f);
    }
}

錯誤在哪里? 有可能修復它嗎?

為什么模擬器能夠無錯誤地運行它?

- - 更新 - -

使用.prepareAsync()相同錯誤

- - 更新 - -

在相同的硬件配置(三星 Galaxy S9 庫存)上,應用程序在通過 usb 鏈接上傳槽adb時使用簡單修復,一旦應用程序在發布版本中登錄,它就停止工作,我再次收到上面報告的相同錯誤代碼。 在華為 P30 等不同的硬件上它可以工作(作為簽名的 release.apk 安裝)。 這可以取決於防火牆規則嗎?

顯然,這個條目解決了這個問題:

android:usesCleartextTraffic="true"

AndroidManifest.xml文件(應用程序部分)中。

- 更新 -

實際上,問題是由一些異常的防火牆規則給出的,這些規則在給定數量的連續訪問后拒絕來自同一主機的連接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM