簡體   English   中英

Android java音頻播放器在后台播放

[英]Android java audio player playing in background

我正在為 Android 移動應用程序創建一個音頻播放器,用 Java 語言編寫。 我正在努力向我的移動應用程序添加在后台播放音頻的可能性。 當我在播放器中播放音頻時返回菜單或最小化應用程序音頻停止。

我在網上搜索了解決方案,但在我的播放器中找不到如何做到這一點。

我會接受任何幫助。 非常感謝您的任何建議。

音頻播放器代碼:

package com.mc.englishlearn.audioplayer;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.database.Cursor;
import android.media.AudioAttributes;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.mc.englishlearn.R;

import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

 public class PlayerActivity extends AppCompatActivity {

 MediaPlayer mediaPlayer;
 Button play, replay, open;
 SeekBar seekBar;
 TextView title, elapse;
 String duration;
 ScheduledExecutorService timer;
 public static final int PICK_FILE =99;
 boolean isRepeat = false;

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

    play = (Button)findViewById(R.id.play);
    replay = (Button) findViewById(R.id.replay);
    open = (Button) findViewById(R.id.open);
    seekBar = (SeekBar) findViewById(R.id.seekBar);
    title = (TextView) findViewById(R.id.title);
    elapse = (TextView) findViewById(R.id.elapsed);

    //Otwieranie pliku dzwiękowego
                open.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                        intent.addCategory(Intent.CATEGORY_OPENABLE);
                        intent.setType("audio/*");
                        startActivityForResult(intent, PICK_FILE);

                    }
                });

                //odtwarzanie pliku
                play.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if(mediaPlayer != null){
                            if(mediaPlayer.isPlaying()){
                                mediaPlayer.pause();
                                play.setText("PLAY");
                                timer.shutdown();
                            }else{
                                mediaPlayer.start();
                                play.setText("PAUSE");

                                timer = Executors.newScheduledThreadPool(1);
                                timer.scheduleAtFixedRate(new Runnable() {
                                    @Override
                                    public void run() {
                                        if (mediaPlayer != null) {
                                            if (!seekBar.isPressed()) {
                                                seekBar.setProgress(mediaPlayer.getCurrentPosition());
                                            }
                                        }
                                    }
                                },10,10, TimeUnit.MILLISECONDS);
                            }
                        }
                    }
                });

                //linia dzwięku
                seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                    @Override
                    public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                        if (mediaPlayer != null){
                            int millis = mediaPlayer.getCurrentPosition();
                            long total_secs = TimeUnit.SECONDS.convert(millis, TimeUnit.MILLISECONDS);
                            long mins = TimeUnit.MINUTES.convert(total_secs, TimeUnit.SECONDS);
                long secs = total_secs - (mins*60);
                elapse.setText(mins + ":" + secs + " / " + duration);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if (mediaPlayer != null) {
                mediaPlayer.seekTo(seekBar.getProgress());
            }
        }
    });

    //Pętla
    replay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //repeat = false
            if(isRepeat){
                isRepeat = false;
                mediaPlayer.setLooping(false);
                Toast.makeText(PlayerActivity.this, "Repeat is OFF", Toast.LENGTH_SHORT).show();
            }else{
                isRepeat = true;
                mediaPlayer.setLooping(true);
                Toast.makeText(PlayerActivity.this, "Repeat is ON", Toast.LENGTH_SHORT).show();
            }

               //mediaPlayer.setLooping(true);
              // Toast.makeText(PlayerActivity.this, "Repeat if ON", Toast.LENGTH_SHORT).show();
        }
    });

    play.setEnabled(false);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_FILE && resultCode == RESULT_OK){
        if (data != null){
            Uri uri = data.getData();
            createMediaPlayer(uri);
        }
    }
}

//Stwórz odtwarzacz dzwiękowy
public void createMediaPlayer(Uri uri){
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioAttributes(
            new AudioAttributes.Builder()
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .build()
    );
    try {
        mediaPlayer.setDataSource(getApplicationContext(), uri);
        mediaPlayer.prepare();

        title.setText(getNameFromUri(uri));
        play.setEnabled(true);

        int millis = mediaPlayer.getDuration();
        long total_secs = TimeUnit.SECONDS.convert(millis, TimeUnit.MILLISECONDS);
        long mins = TimeUnit.MINUTES.convert(total_secs, TimeUnit.SECONDS);
        long secs = total_secs - (mins*60);
        duration = mins + ":" + secs;
        elapse.setText("00:00 / " + duration);
        seekBar.setMax(millis);
        seekBar.setProgress(0);

        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                releaseMediaPlayer();

            }
        });
    } catch (IOException e){
        title.setText(e.toString());
    }
}

@SuppressLint("Range")
public String getNameFromUri(Uri uri){
    String fileName = "";
    Cursor cursor = null;
    cursor = getContentResolver().query(uri, new String[]{
            MediaStore.Images.ImageColumns.DISPLAY_NAME
    }, null, null, null);
    if (cursor != null && cursor.moveToFirst()) {
        fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME));
    }
    if (cursor != null) {
        cursor.close();
    }
    return fileName;
}

@Override
protected void onDestroy() {
    super.onDestroy();
    releaseMediaPlayer();
}

public void releaseMediaPlayer(){
    if (timer != null) {
        timer.shutdown();
    }
    if (mediaPlayer != null) {
        mediaPlayer.release();
        mediaPlayer = null;
    }
    play.setEnabled(false);
    elapse.setText("TITLE");
    elapse.setText("00:00 / 00:00");
    seekBar.setMax(100);
    seekBar.setProgress(0);
}
}

xml文件代碼:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<SeekBar
    android:id="@+id/seekBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toTopOf="@+id/guideline3"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@+id/guideline2" />

<TextView
    android:id="@+id/title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="195dp"
    android:layout_marginTop="178dp"
    android:layout_marginEnd="216dp"
    app:layout_constraintBottom_toTopOf="@+id/guideline4"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.0" />

<TextView
    android:id="@+id/elapsed"
    android:layout_width="74dp"
    android:layout_height="34dp"
    android:layout_marginStart="177dp"
    android:layout_marginEnd="196dp"
    android:text="00-00"
    app:layout_constraintBottom_toTopOf="@+id/guideline2"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.25"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@+id/guideline4"
    app:layout_constraintVertical_bias="0.625" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_begin="271dp" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_begin="339dp" />

<LinearLayout
    android:id="@+id/linearLayout"
    android:layout_width="93dp"
    android:layout_height="108dp"
    android:layout_marginStart="160dp"
    android:layout_marginEnd="158dp"
    android:layout_marginBottom="118dp"
    android:orientation="vertical"
    app:layout_constraintBottom_toTopOf="@+id/replay"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@+id/guideline3">

    <Button
        android:id="@+id/play"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:backgroundTint="@color/green"
        android:text="|>" />

    <Button
        android:id="@+id/open"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Otwórz plik" />
</LinearLayout>

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_begin="213dp" />

<Button
    android:id="@+id/replay"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="powtórz"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@+id/guideline5" />

<Button
    android:id="@+id/start"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="72dp"
    android:text="start"
    app:layout_constraintBottom_toBottomOf="@+id/end"
    app:layout_constraintEnd_toStartOf="@+id/guideline8"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@+id/guideline5" />

<Button
    android:id="@+id/end"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="80dp"
    android:text="koniec"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="1.0"
    app:layout_constraintStart_toStartOf="@+id/guideline8"
    app:layout_constraintTop_toTopOf="@+id/guideline5" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_begin="515dp" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline8"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_begin="205dp" />

</androidx.constraintlayout.widget.ConstraintLayout>

使用Service並在那里實現所有Media Player邏輯,例如:

public class MyService extends Service implements MediaPlayer.OnPreparedListener {
        private static final String ACTION_PLAY = "com.example.action.PLAY";
        MediaPlayer mediaPlayer = null;

        public int onStartCommand(Intent intent, int flags, int startId) {
            ...
            if (intent.getAction().equals(ACTION_PLAY)) {
                mediaPlayer = ... // initialize it here
                mediaPlayer.setOnPreparedListener(this);
                mediaPlayer.prepareAsync(); // prepare async to not block main thread
            }
        }

        /** Called when MediaPlayer is ready */
        public void onPrepared(MediaPlayer player) {
            player.start();
        }
    }

然后從您的Main Activity啟動服務,如下所示:

Context context = getApplicationContext();
Intent intent = new Intent(...); // Build the intent for the service
context.startForegroundService(intent);

暫無
暫無

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

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