江科大安卓实验4 后台服务

实验介绍了如何在Android中使用Service实现音乐播放和计数功能。音乐服务利用MediaPlayer播放、暂停和停止音乐,而计数服务通过后台计数并在界面上更新。服务通过Intent接收操作指令,使用Binder进行Activity与Service间的通信。
摘要由CSDN通过智能技术生成

实验题目:后台服务

  • 实验目的

1)了解什么是Service;

2)掌握Service 中启动服务于绑定服务的区别;

3)通过Service 实现音乐播放的实时更新。

  • 实验内容

1)制作一个简单的音乐播放器,拥有播放,暂停,停止功能,播放res/raw文件夹中的mp3 资源文件。

2)、实现两个简单的按钮功能,一个是启动一个自定义的自动计数的Service,另一个是关闭该Service。

  • 程序设计思想(流程图,或算法思想或设计方案等)

这是一个Android应用程序,包含两个服务:音乐服务和计数服务。音乐服务允许用户播放,暂停和停止音乐,计数服务可以启动并停止计数器并在活动中显示当前计数。

音乐服务(MusicService)继承自Service类。它包含一个MediaPlayer对象,该对象用于播放音乐。该类重写了onCreate(),onStartCommand()和onDestroy()方法。onCreate()方法初始化MediaPlayer对象。onStartCommand()方法接收Intent对象,该对象包含指示要执行的操作的参数,例如播放,停止或暂停音乐。根据Intent中的参数,音乐服务执行相应的操作。onDestroy()方法停止MediaPlayer对象并释放相关资源。

计数服务(CountService)继承自Service类。它包含一个计数器和一个CountCallback接口。该类重写了onBind(),onStartCommand()和onDestroy()方法。onBind()方法返回一个Binder对象,该对象允许与服务进行通信。onStartCommand()方法接收Intent对象,该对象包含指示要执行的操作的参数,例如启动或停止计数器。根据Intent中的参数,计数服务执行相应的操作。onDestroy()方法停止计数器并释放相关资源。计数器使用一个线程不断增加计数器变量,同时在CountCallback接口上通知调用者新的计数器值。该计数器变量也可以在CountService类中通过调用getCount()方法获取。

MainActivity类是应用程序的主要活动。它显示了四个按钮,其中三个用于控制音乐服务,另一个用于控制计数服务。它还包括一个TextView,用于显示当前计数。在onCreate()方法中,MainActivity类创建了一个Intent对象,用于启动CountService。该类还使用bindService()方法绑定CountService,并在CountService的onServiceConnected()方法中设置CountCallback接口。每当计数器增加时,CountService通过该接口通知MainActivity类并更新计数器的文本视图。此外,MainActivity类还处理音乐服务的按钮点击事件。

  • 源代码(主要源代码)

CountService.java

package com.example.musicservice;

import android.app.Service;

import android.content.Intent;

import android.os.Binder;

import android.os.IBinder;

import android.util.Log;

import androidx.annotation.Nullable;

public class CountService extends Service {

    private int count = 0;

    private CountCallback countCallback;

    private final IBinder mBinder = new LocalBinder();

    private volatile boolean isRunning = false;

    public class LocalBinder extends Binder {

        CountService getService() {

            return CountService.this;

        }

    }

    public IBinder onBind(Intent intent) {

        return mBinder;

    }

    public void setCountCallback(CountCallback countCallback) {

        this.countCallback = countCallback;

    }

    @Override

    public int onStartCommand(Intent intent, int flags, int startId) {

        if (intent != null) {

            String action = intent.getStringExtra("action");

            if (action != null) {

                if (action.equals("start")) {

                    startCount();

                } else if (action.equals("stop")) {

                    stopCount();

                }

            }

        }

        return START_STICKY;

    }

    private void startCount() {

        if (!isRunning) {

            isRunning = true;

            new Thread(new Runnable() {

                @Override

                public void run() {

                    while (isRunning) {

                        count++;

                        Log.d("CountService", "count = " + count);

                        if (countCallback != null) {

                            countCallback.updateCount(count);

                        }

                        try {

                            Thread.sleep(1000);

                        } catch (InterruptedException e) {

                            e.printStackTrace();

                        }

                    }

                }

            }).start();

        }

    }

    private void stopCount() {

        Log.d("CountService", "stop!!!!!!!!");

        isRunning = false;

    }

    public interface CountCallback {

        void updateCount(int count);

    }

    @Override

    public void onDestroy() {

        super.onDestroy();

        Log.d("CountService", "onDestroy()");

    }

}

MainActivity.java

package com.example.musicservice;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;

import android.content.Intent;

import android.content.ServiceConnection;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

import android.os.IBinder;

import android.content.Context;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, CountService.CountCallback {

    private Button btn_main_play;

    private Button btn_main_stop;

    private Button btn_main_pause;

    private Button btn_main_exit;

    private Button btn_count_start;

    private Button btn_count_stop;

    private CountService countService;

    private TextView tvCount;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        //获取4个按钮

        btn_main_play = findViewById(R.id.btn_main_play);

        btn_main_stop = findViewById(R.id.btn_main_stop);

        btn_main_pause = findViewById(R.id.btn_main_pause);

        btn_main_exit = findViewById(R.id.btn_main_exit);

        btn_main_play.setOnClickListener(this);

        btn_main_stop.setOnClickListener(this);

        btn_main_pause.setOnClickListener(this);

        btn_main_exit.setOnClickListener(this);

        btn_count_start = findViewById(R.id.btn_count_start);

        btn_count_stop = findViewById(R.id.btn_count_stop);

        tvCount=findViewById(R.id.tvCount);

        Intent intentCount = new Intent(this, CountService.class);

        btn_count_start.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                intentCount.putExtra("action", "start");

                startService(intentCount);

            }

        });

        btn_count_stop.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                intentCount.putExtra("action", "stop");

                startService(intentCount);

                stopService(intentCount);

            }

        });

        Intent intentCount2 = new Intent(this, CountService.class);

        startService(intentCount2);

        bindService(intentCount2, new ServiceConnection() {

            @Override

            public void onServiceConnected(ComponentName name, IBinder service) {

                CountService.LocalBinder binder = (CountService.LocalBinder) service;

                countService = binder.getService();

                countService.setCountCallback(MainActivity.this);

            }

            @Override

            public void onServiceDisconnected(ComponentName name) {

                countService = null;

            }

        }, Context.BIND_AUTO_CREATE);

    }

    @Override

    public void onClick(View v) {

        //新建intent,传入不同的操作,通过intent的参数来判断是什么操作

        Intent intent = new Intent(this,MusicService.class);

        //判断点击了哪个按钮

        //music

        if(v== btn_main_play){

            //播放

            intent.putExtra("action","play");

            //启动服务

            startService(intent);

        }else if(v == btn_main_stop){

            //停止播放

            intent.putExtra("action","stop");

            //启动服务

            startService(intent);

        }else if(v == btn_main_pause){

            //暂停音乐

            intent.putExtra("action","pause");

            //启动服务

            startService(intent);

        }else if(v ==btn_main_exit ){

            //停止音乐--停止服务

            stopService(intent);

            finish();

        }

        //count

    }

    @Override

    public void updateCount(int count) {

        runOnUiThread(new Runnable() {

            @Override

            public void run() {

                tvCount.setText("计数: " + count);

            }

        });

    }

}

MusicService.java

package com.example.musicservice;

import android.app.Service;

import android.content.Intent;

import android.media.MediaPlayer;

import android.os.IBinder;

import androidx.annotation.Nullable;

/*//播放

MediaPlayer player = MediaPlayer.create(context, R.raw.tmp);

player.start()

//暂停(再播放当前继续)

player.pause()

//停止(再播放重头开始)

player.stop();

player.reset();

player.release();*/

public class MusicService  extends Service {

    private MediaPlayer player;

    @Nullable

    @Override

    public IBinder onBind(Intent intent) {

        return null;

    }

    /*

    * 通过传进来的intent来判断播放--暂停--停止

    *  @Override

    public void onClick(View v) {

        //新建intent,传入不同的操作,通过intent的参数来判断是什么操作

        Intent intent = new Intent(this,MusicService.class);

        //判断点击了哪个按钮

        if(v== btn_main_play){

            //播放

            intent.putExtra("action","play");

            //启动服务

            startService(intent);

        }else if(v == btn_main_stop){

            //停止播放

            intent.putExtra("action","stop");

            //启动服务

            startService(intent);

        }else if(v == btn_main_pause){

            //暂停音乐

            intent.putExtra("action","pause");

            //启动服务

            startService(intent);

        }else if(v ==btn_main_exit ){

            //停止音乐--停止服务

            stopService(intent);

            finish();

        }

    }

    * */

    @Override

    public int onStartCommand(Intent intent, int flags, int startId) {

        String action = intent.getStringExtra("action");

        if("play".equals(action)){

            palayMusic();

        }else if("pause".equals(action)){

            pauseMusic();

        }else if("stop".equals(action)){

            stopMusic();

        }

        return super.onStartCommand(intent, flags, startId);

    }

    //停止播放

    private void stopMusic() {

        if(player!=null){

            player.stop();//停止

            player.reset();//重置

            player.release();//释放资源

            player = null;//赋空

        }

    }

    /*暂停播放*/

    private void pauseMusic() {

        if(player!=null && player.isPlaying()){

            player.pause();

        }

    }

    //播放音乐

    private void palayMusic() {

        if(player == null){

            player = MediaPlayer.create(this, R.raw.water_hander);

        }

        player.start();

    }

    //activity退出时,停止音乐

    @Override

    public void onDestroy() {

        super.onDestroy();

        stopMusic();

    }

}

activity.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"

    tools:context=".MainActivity">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:orientation="vertical"

        tools:ignore="MissingConstraints">

        <TextView

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="音乐播放器"

            ></TextView>

        <Button

            android:id="@+id/btn_main_play"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:text="play" />

        <Button

            android:id="@+id/btn_main_stop"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:text="stop" />

        <Button

            android:id="@+id/btn_main_pause"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:text="pause" />

        <Button

            android:id="@+id/btn_main_exit"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:text="exit" />

        <TextView

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="计数器"

            ></TextView>

        <Button

            android:id="@+id/btn_count_start"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="Start Count" />

        <Button

            android:id="@+id/btn_count_stop"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="Stop Count" />

        <TextView

            android:id="@+id/tvCount"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="计数: "

            android:textSize="48sp" />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

  • 测试与运行
  1. 在调试程序的过程中遇到什么问题,是如何解决的?

添加服务连接状态的判断

在 MainActivity 中使用 countService 时,应该添加服务连接状态的判断,以避免空指针异常。可以在 CountService 中添加一个 isConnected() 方法,用于检查服务是否连接。

在 MainActivity 中使用 CountService 的回调方法时,应该先检查 countService 是否为空

当服务未连接时,countService 会为空,因此在使用 CountService 的回调方法时,应该先检查 countService 是否为空,以避免空指针异常。可以在 MainActivity 中添加一个 isCountServiceConnected() 方法,用于检查服务是否连接。

测试数据及运行结果。(无测试数据的,直接记录运行结果)

这个程序集合了音乐播放器和计数器,可以播放音乐停止暂停和退出,有一个整数计数器 count,它每秒自增 1。

运行截图:

 

  • 总结

这个实验主要分为两部分:音乐播放器和计数器应用程序。在音乐播放器应用程序中,通过使用Service类创建一个后台服务,可以在后台播放音乐。Service类可以被启动并运行在后台,即使应用程序的Activity已经退出,Service仍可以继续运行。

在本实验中,创建了一个Media Player Service,该服务通过使用MediaPlayer类播放音乐文件。在该服务中,定义了多个方法来操作音乐播放器,例如开始、暂停、停止和跳转到指定时间等。使用Intent可以将这些操作从Activity发送到服务,以控制音乐播放器的状态。

在计数器应用程序中,同样使用了Service类来创建一个后台服务,该服务可以在后台计数。这个服务还实现了一个Binder类,以允许Activity与服务之间进行通信。

在本实验中,通过创建一个Counter Service和一个Counter Binder类,可以在服务中计数,并通过Binder类提供方法来允许Activity对计数器进行增加、减少和获取计数器值等操作。这些方法可以通过Intent发送到服务来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值