Android Activity 到 Service 类

标签 android android-layout android-intent android-emulator

我在下面有我的 Activity ,它使用一些帮助类播放 ShoutCastURL 流

代码:

import java.net.MalformedURLException;

import com.androidworkz.androidshoutcastlib.AndroidShoutcastLib;
import com.androidworkz.androidshoutcastlib.InvalidStreamURLException;
import com.androidworkz.androidshoutcastlib.Metadata;
import com.androidworkz.androidshoutcastlib.MetadataListener;

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class Player extends Activity implements OnCompletionListener,
OnPreparedListener, OnErrorListener, OnBufferingUpdateListener, MusicFocusable {

    private Boolean playState = false;  
    private String station = "http://38.101.195.5:9156";
    public static final float DUCK_VOLUME = 0.1f;
    private String artistName = null;
    private String trackName = null;

    private TextView artist;
    private TextView track;
    private TextView status;
    private Button play;

    enum AudioFocus {
        NoFocusNoDuck, // we don't have audio focus, and can't duck
        NoFocusCanDuck, // we don't have focus, but can play at a low volume
                        // ("ducking")
        Focused // we have full audio focus
    }

    private AudioFocus mAudioFocus = AudioFocus.NoFocusNoDuck;

    private MediaPlayer mPlayer = null;
    private AndroidShoutcastLib shoutcast;
    private AudioManager mAudioManager;
    AudioFocusHelper mAudioFocusHelper = null;

    Handler handler = new Handler();

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

        mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

        // create the Audio Focus Helper, if the Audio Focus feature is
        // available (SDK 8 or above)
        if (android.os.Build.VERSION.SDK_INT >= 8) {
            mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(),
                    this);
        }
        else {
            mAudioFocus = AudioFocus.Focused; // no focus feature, so we always "have" audio focus
        }

        status = (TextView) findViewById(R.id.status);

        artist = (TextView) findViewById(R.id.artist);
        artist.setSelected(true);

        track = (TextView) findViewById(R.id.track);
        track.setSelected(true);

        play = (Button) findViewById(R.id.play);

        play.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View btn) {
                if (!playState) {
                    play.setText("Pause");
                    handler.postDelayed(handlePlayRequest, 300);
                }
                else {
                    play.setText("Play");
                    status.setText("Press Play");
                    handler.postDelayed(handlePlayRequest, 300);
                }
            }

        });

        shoutcast = new AndroidShoutcastLib();

        try {
            shoutcast.setShoutcastUrl(station);
        } catch (InvalidStreamURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        shoutcast.setOnMetadataChangedListener(new MetadataListener(){

            @Override
            public void OnMetadataChanged(Metadata item) {
                artistName = item.artist;
                trackName = item.track;             
                updateMeta();
            }
        });

        setVolumeControlStream(AudioManager.STREAM_MUSIC);      
    }

    public void onDestroy() {
        super.onDestroy();

        shoutcast = null;
        handler.removeCallbacks(handlePlayRequest);
    }

    public void updateMeta() {
        handler.post(new Runnable() {
            @Override
            public void run() {
                // This gets executed on the UI thread so it can safely modify Views
                artist.setText(artistName);
                track.setText(trackName);
            }
        });
    }

    private final Runnable handlePlayRequest = new Runnable() {
        public void run() {
            if (playState) {
                Log.d("Player", "Stop Called");
                giveUpAudioFocus();
                mPlayer.stop();
                mPlayer.reset();
                mPlayer.release();
                shoutcast.stopStream();
                mPlayer = null;
                playState = false;
            }
            else {
                Log.d("Player", "Play Called");
                createMediaPlayer();
                getAudioFocus();

                try {
                    mPlayer.setDataSource(shoutcast.startStream());
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SecurityException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalStateException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InvalidStreamURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                mPlayer.prepareAsync();
            }
        }
    };

    private void createMediaPlayer() {
        mPlayer = new MediaPlayer();

        // Make sure the media player will acquire a wake-lock while
        // playing. If we don't do
        // that, the CPU might go to sleep while the song is playing,
        // causing playback to stop.
        //
        // Remember that to use this, we have to declare the
        // android.permission.WAKE_LOCK
        // permission in AndroidManifest.xml.
        mPlayer.setWakeMode(getApplicationContext(),
                PowerManager.PARTIAL_WAKE_LOCK);

        // we want the media player to notify us when it's ready preparing,
        // and when it's done
        // playing:
        mPlayer.setOnPreparedListener(this);
        mPlayer.setOnCompletionListener(this);
        mPlayer.setOnErrorListener(this);
    }

    private void startPlayer() {
        mPlayer.setVolume(1.0f, 1.0f);
        if (!mPlayer.isPlaying()) {
            Log.d("Player", "Starting Playback");
            mPlayer.start();
            playState = true;
            status.setText("Streaming");
        }               
    }

    private void getAudioFocus() {
        if (mAudioFocus != AudioFocus.Focused && mAudioFocusHelper != null
                && mAudioFocusHelper.requestFocus())
            mAudioFocus = AudioFocus.Focused;
    }

    private void giveUpAudioFocus() {
        if (mAudioFocus == AudioFocus.Focused && mAudioFocusHelper != null
                && mAudioFocusHelper.abandonFocus())
            mAudioFocus = AudioFocus.NoFocusNoDuck;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_player, menu);
        return true;
    }

    @Override
    public void onBufferingUpdate(MediaPlayer arg0, int arg1) {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        playState = false;
        handler.post(handlePlayRequest);
        return false;
    }

    @Override
    public void onPrepared(MediaPlayer arg0) {
        startPlayer();      
    }

    @Override
    public void onCompletion(MediaPlayer arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onGainedAudioFocus() {
        // TODO Auto-generated method stub

    }

    @Override
    public void onLostAudioFocus(boolean canDuck) {
        // TODO Auto-generated method stub

    }

}

当我在 ForeGround 中播放 Stream 时,上述代码运行良好,

但我的要求是也在后台播放流(我的代码应该播放流,如果用户也在与其他应用程序交互)

为此,我为上述 Activity 创建了一个服务类

这是代码:

Activity :
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class Player extends Activity implements OnClickListener {

    private Boolean playState = false;
    public static final float DUCK_VOLUME = 0.1f;
    private String artistName = null;
    private String trackName = null;

    private TextView artist;
    private TextView track;
    private TextView status;
    private Button play;

    Intent playbackServiceIntent;

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

        // create the Audio Focus Helper, if the Audio Focus feature is
        // available (SDK 8 or above)

        status = (TextView) findViewById(R.id.status);

        artist = (TextView) findViewById(R.id.artist);
        artist.setSelected(true);

        track = (TextView) findViewById(R.id.track);
        track.setSelected(true);

        play = (Button) findViewById(R.id.play);

        play.setOnClickListener(this);

        playbackServiceIntent = new Intent(this, BackGroundService.class);

    }

    @Override
    public void onClick(View v) {
        if (v == play) {
            startService(playbackServiceIntent);
            Log.d("hi>>>>>", "gjgj");
            finish();
        }
    }

}

服务等级:
import com.androidworkz.androidshoutcastlib.AndroidShoutcastLib;
import com.androidworkz.androidshoutcastlib.InvalidStreamURLException;

import android.app.Service;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.util.Log;

public class BackGroundService extends Service implements OnCompletionListener,
        OnPreparedListener, OnErrorListener, OnBufferingUpdateListener,
        MusicFocusable {
    private Boolean playState = false;
    private String station = "http://38.101.195.5:9156";
    public static final float DUCK_VOLUME = 0.1f;
    Runnable handlePlayRequest;

    enum AudioFocus {
        NoFocusNoDuck, // we don't have audio focus, and can't duck
        NoFocusCanDuck, // we don't have focus, but can play at a low volume
                        // ("ducking")
        Focused // we have full audio focus
    }

    private AudioFocus mAudioFocus = AudioFocus.NoFocusNoDuck;

    private MediaPlayer mPlayer = null;
    private AndroidShoutcastLib shoutcast;
    private AudioManager mAudioManager;
    AudioFocusHelper mAudioFocusHelper = null;

    Handler handler = new Handler();

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("onStartCommand>>>", "onStartCommand");

        mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

        // create the Audio Focus Helper, if the Audio Focus feature is
        // available (SDK 8 or above)
        if (android.os.Build.VERSION.SDK_INT >= 8) {
            mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(),
                    this);
        } else {
            mAudioFocus = AudioFocus.Focused; // no focus feature, so we always
                                                // "have" audio focus
        }
        shoutcast = new AndroidShoutcastLib();

        try {
            Log.d("Station>>>", station);

            shoutcast.setShoutcastUrl(station);

        } catch (InvalidStreamURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        new BackgroundSound().execute();

        return START_STICKY;
    }

    public void onDestroy() {
        Log.d("onDestroy>>>", "onDestroy");

        if (mPlayer.isPlaying()) {
            mPlayer.stop();
        }
        mPlayer.release();
    }

    @Override
    public void onGainedAudioFocus() {
        // TODO Auto-generated method stub

    }

    @Override
    public void onLostAudioFocus(boolean canDuck) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onBufferingUpdate(MediaPlayer arg0, int arg1) {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void onPrepared(MediaPlayer arg0) {
        // TODO Auto-generated method stub
        mPlayer.start();
    }

    private void giveUpAudioFocus() {
        if (mAudioFocus == AudioFocus.Focused && mAudioFocusHelper != null
                && mAudioFocusHelper.abandonFocus())
            mAudioFocus = AudioFocus.NoFocusNoDuck;
    }

    @Override
    public void onCompletion(MediaPlayer arg0) {
        // TODO Auto-generated method stub
        stopSelf();
    }

    private void getAudioFocus() {
        if (mAudioFocus != AudioFocus.Focused && mAudioFocusHelper != null
                && mAudioFocusHelper.requestFocus())
            mAudioFocus = AudioFocus.Focused;
    }

    private void createMediaPlayer() {
        mPlayer = new MediaPlayer();

        // Make sure the media player will acquire a wake-lock while
        // playing. If we don't do
        // that, the CPU might go to sleep while the song is playing,
        // causing playback to stop.
        //
        // Remember that to use this, we have to declare the
        // android.permission.WAKE_LOCK
        // permission in AndroidManifest.xml.
        mPlayer.setWakeMode(getApplicationContext(),
                PowerManager.PARTIAL_WAKE_LOCK);

        // we want the media player to notify us when it's ready preparing,
        // and when it's done
        // playing:
        mPlayer.setOnPreparedListener(this);
        mPlayer.setOnCompletionListener(this);
        mPlayer.setOnErrorListener(this);
    }

    private class BackgroundSound extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            Log.d("doInBackground>>>", "doInBackground");

            Log.d("run>>>", "run");

            if (playState) {
                Log.d("Player", "Stop Called");
                giveUpAudioFocus();
                mPlayer.stop();
                mPlayer.reset();
                mPlayer.release();
                shoutcast.stopStream();
                mPlayer = null;
                playState = false;
            } else {
                Log.d("Player", "Play Called");
                createMediaPlayer();
                getAudioFocus();

                try {
                    mPlayer.setDataSource(shoutcast.startStream());
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SecurityException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalStateException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InvalidStreamURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                mPlayer.prepareAsync();
            }

            return null;
        }
    }

}

当我执行上面的服务类时,我可以播放流,但是当控制来到服务类时,我的布局消失了

一件事,我想知道,我从 Activity 到服务的转换是否正确?

任何人都可以建议我正确的代码吗?

最佳答案

如果您只想为您的应用播放背景音乐,请在从您的应用启动的线程中播放它/使用 AsyncTask 类为您播放。

服务的概念是在后台运行;根据背景,含义通常是您的应用程序 UI 是 不可见 .确实,它可以像您一样使用(如果您记得停止它),但它是不对的,并且它消耗了您不应该使用的资源。

如果要在 Activity 的后台执行任务,请使用 AsyncTask。

顺便说一下, onStart 已被弃用。当您确实使用服务时,请实现 onStartCommand。

更新:

我认为这段代码对你有用。添加这个类(包含在您的 Activity 类中)。

        public class BackgroundSound extends AsyncTask<Void, Void, Void> {
          @Override
        protected Void doInBackground(Void... params) {
        MediaPlayer player = MediaPlayer.create(YourActivity.this, R.raw.test_cbr); 
        player.setLooping(true); // Set looping 
        player.setVolume(100,100); 
        player.start(); 
        return null;
             }
         }


现在,为了控制音乐,保存您的 BackgroundSound 对象而不是匿名创建它。在您的 Activity 中将其声明为一个字段:

        BackgroundSound mBackgroundSound = new BackgroundSound();


在您的 Activity 的 onResume 方法上,启动它:

         public void onResume() {
           super.onResume();
            mBackgroundSound.execute(null);
           }


在您的 Activity 的 onPause 方法上,停止它:

         public void onPause() {
           super.onPause();
            mBackgroundSound.cancel(true);
                 }


这将起作用。

关于Android Activity 到 Service 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16355920/

相关文章:

在 ListView 快速删除问题中键入时进行 Android EditText 搜索

使用 retrolambda 构建的 Android 会忽略源代码更改

android - 如何为 Android 应用程序创建 TikTok/Musical.ly 的功能?

android - 在android中制作中心长TextView

android - 根据 Intent 给定的标识符向 Activity 添加不同的 fragment

java - 您通过 Intent/bundle 发送多少数据到其他 Activity/fragment ?

javascript - Android 上的 IFA 等效项以及如何从浏览器/javascript 访问它

android - 无法 setprop - avc 被拒绝?

android - 如何在所有 Activity 中访问抽屉导航?

android - ACTION_SEND - 共享与光盘上不同文件名的文件