实验三 广播和服务

2022-07-28,,

实验广播和服务

  • 1. 创建广播接受组件:SmsReceiver.java
    • 1.1 创建一个类SmsReceiver继承类BroadcastReceiver
    • 1.2 注册广播接受程序
  • 2. 添加音乐服务文件MyAudioService.java
    • 2.1 创建一个类MyAudioService继承类Service
    • 2.2 添加音乐文件
    • 2.3 服务注册
  • 3. 主界面程序:MainActivity
    • 3.1 界面布局
    • 3.2 短信权限注册
    • 3.3 设置按钮逻辑
  • 4.实验结果
  • 5 优化及代码仓库地址

首先确定实验目的:

编写广播接收者程序,当收到短信时,对短信广播做出响应:app会启动音乐播放服务。
顺便,写一个按钮,当收到短信广播时,由不可点击切换为可点击,点击按钮,就可以停止音乐播放。

1. 创建广播接受组件:SmsReceiver.java

1.1 创建一个类SmsReceiver继承类BroadcastReceiver

当接收到广播时,执行重写的onReceive()方法

/*
    本广播接收者程序分别调用了应用的主Activity程序和播放音乐的服务程序
*/
public class SmsReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        Intent serviceIntent = new Intent(context, MyAudioService.class);
        //在广播组件里,通过上下文对象启动音乐播放服务组件
        context.startService(serviceIntent);

        //新建调用Activity组件的意图
        Intent activityIntent = new Intent(context, MainActivity.class);
        activityIntent.putExtra("iscast", true);  //携带数据
        //新建栈用来存放被启动的Activity(当已经存在时,只做移动处理)
        activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //在广播组件里,通过上下文对象启动Activity组件
        context.startActivity(activityIntent);
    }
}

而这个广播接收组件是接收谁发出的广播呢?

1.2 注册广播接受程序

在manifests中的application标签内添加receiver标签
name绑定类,intent-filter过滤请求触发广播

        <receiver
            android:name=".SmsReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>

注意其中的intent-filter标签,里面的配置就是用于过滤其中指定的请求,这里的action标签就是用于过滤出短信消息触发广播。

当手机收到短信时,系统发出一个广播,这里receiver所绑定的SmsReceiver类接受到广播,然后执行onReceive()函数。

2. 添加音乐服务文件MyAudioService.java

我们想要收到广播时,播放音乐,那么我们得添加一个音乐服务

2.1 创建一个类MyAudioService继承类Service

public class MyAudioService extends Service {
    MediaPlayer mediaPlayer;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onCreate() {
        mediaPlayer  = MediaPlayer.create(this, R.raw.liyue);//创建音乐服务。播放R.raw中的音乐liyue
        mediaPlayer.start();//开始服务
    }
    @Override
    public void onDestroy() {
        mediaPlayer.stop();
    }
}

2.2 添加音乐文件

然后在广播中执行这个音乐服务程序

        Intent serviceIntent = new Intent(context, MyAudioService.class);
        //在广播组件里,通过上下文对象启动音乐播放服务组件
        context.startService(serviceIntent);

2.3 服务注册

同时注册服务到manifests,在manifests中的application标签内添加service 标签,绑定服务类MyAudioService

        <service android:name=".MyAudioService">
        </service>

3. 主界面程序:MainActivity

3.1 界面布局

只需要一个按钮,我们先进行页面布局,添加一个button即可

3.2 短信权限注册

然后我们要接受短信,得在manifest手工添加注册短信接收权限

<uses-permission android:name="android.permission.RECEIVE_SMS"/>

而在主界面程序MainActivity需要写检测短信权限(属于危险权限)及请求申请本权限的代码:

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String[]{"android.permission.RECEIVE_SMS"},1);
        }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case 1:
                if(grantResults[0]!=PackageManager.PERMISSION_GRANTED){
                    Toast.makeText(this, "未授权,无法实现预定的功能!", Toast.LENGTH_SHORT).show();
                    finish();
                }else{
                    Toast.makeText(this, "请发一条短信验证...", Toast.LENGTH_SHORT).show();
                }
        }
    }
}

3.3 设置按钮逻辑

当未收到短信时打开mainactivity,isCast=false,按钮不可用(不可点击)

当收到短信时,SmsReceiver收到广播,触发onReceive()函数,启动音乐播放服务组件MyAudioService类。并且使用Intent的putExtra()方法,将一个键值对 iscast : true 传给mainactivity,并且再次启动MainActivity,这时iscast=true,按钮可用。

这时点击按钮,触发按钮的监听事件,停止音乐服务。

public class MainActivity extends AppCompatActivity {

    private Button btnStop;
    private boolean isCast; //是否为广播激活

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String[]{"android.permission.RECEIVE_SMS"},1);
        }
        btnStop=findViewById(R.id.btnStop);
        Intent intent = getIntent(); //获取广播意图对象
        isCast = intent.getBooleanExtra("iscast", false);  //默认值为false
        btnStop.setEnabled(isCast);   //设置停止按钮可用和单击监听
        if(isCast) Toast.makeText(this, "正在播放音乐...", Toast.LENGTH_SHORT).show();
        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v){
                //显式服务调用意图(非绑定式)
                Intent intent=new Intent(MainActivity.this, MyAudioService.class);
                //在Activity组件里,停止音乐播放服务
                stopService(intent);
                finish();  //销毁本活动
            }
        });
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case 1:
                if(grantResults[0]!=PackageManager.PERMISSION_GRANTED){
                    Toast.makeText(this, "未授权,无法实现预定的功能!", Toast.LENGTH_SHORT).show();
                    finish();
                }else{
                    Toast.makeText(this, "请发一条短信验证...", Toast.LENGTH_SHORT).show();
                }
        }
    }
}

4.实验结果

进入程序,按钮为灰色不可用

点击手机模拟器桌面的短信,给5554(自己)发送短信

收到短信,跳转到程序,音乐开始播放

点击停止按钮,音乐停止播放,程序也同时退出。

5 优化及代码仓库地址

这里我们可以更改按钮监听触发的事件

       btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v){
                //显式服务调用意图(非绑定式)
                Intent intent=new Intent(MainActivity.this, MyAudioService.class);
                //在Activity组件里,停止音乐播放服务
                stopService(intent);
                isCast=false;
                btnStop.setEnabled(isCast);
//                finish();  //销毁本活动
            }
        }

这样,点击按钮后就不会退出程序。而会变灰不可用,当又有短信来时,又可以触发音乐服务,按钮可用,再次点击又可以停止音乐服务。

代码仓库地址:
https://gitee.com/hu_hong_tao/android-development-experiment3

本文地址:https://blog.csdn.net/iamsweet/article/details/109633530

《实验三 广播和服务.doc》

下载本文的Word格式文档,以方便收藏与打印。