Android Service和广播

摘要:
前言:我们都知道Android的四个基本组件:Activity、ContentProvider、Service和BroadcastReceiver。我们在前面的文章中详细解释了前两个。今天,我们将具体讨论后两者的用法。因为Service和BroadcastReceiver经常一起使用,所以我们将一起学习。1、 服务是Android系统的后台服务组件

前言:

我们都知道Android的四大基本组件:ActivityContentProviderService以及BroadcastReceiver,前面的两个我们在前几篇已经具体讲解了,今天这一天我们就把后两者的使用具体说一下,由于ServiceBroadcastReceiver常常一起使用,所以我们一起来学习。

 

 

一.Service的使用

ServiceAndroid系统的后台服务组件,没有用户界面,但可以长时间的运行,比Activity的优先级高,可以用于进程间的通信。

Service也同Activity一样有自己的生命周期,但是Service有两种生命周期,也就是Service由两种启动以及对应的停止方式:

1.以启动方式使用的Service

(1)特点:

A.通过Content.startService()启动,Content.stopService()或者Content.stopSelf()来停止;

(即只能通过其他组件启动,但可以自己停止)

B.不能与外部的组件进行交互;

(2)生命周期:

onCreate——>onStartCommand——>onDestroy

(3)示例代码:L0828_Service(记得注册)

MyService.java:

 

package com.example.l0828_service; 
import java.util.Timer; 
import java.util.TimerTask; 
import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
public class MyService extends Service{ 
    //声明定时器,用于创建新的进程来计时 
    private Timer timer; 
    private TimerTask task; 
    private static int i=0; 
    //继承Service必须要重写的方法onBind 
    @Override
    public IBinder onBind(Intent intent) { 
        return null; 
    } 
    /*Service的生命周期一:onCreate、onStartCommand、onDestroy方法构成*/
    //onCreate方法,启动服务,每次启动仅仅调用一次 
    @Override
    public void onCreate() { 
        System.out.println("onCreate"); 
        super.onCreate(); 
    } 
    //onStartCommand方法,一般在其中完成Service的工作 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) { 
        System.out.println("onStartCommond"); 
        startTimer(); 
        return super.onStartCommand(intent, flags, startId); 
    } 
    //onDestroy方法,用来释放Service的资源 
    @Override
    public void onDestroy() { 
        System.out.println("onDestroy"); 
        stopTimer(); 
        super.onDestroy(); 
    } 
    //开启定时器 
    public void startTimer(){ 
        timer =new Timer(); 
        task=new TimerTask(){ 
            @Override
            public void run() { 
                i++; 
                System.out.println(i); 
            } 
        }; 
        timer.schedule(task, 1000, 1000); 
    } 
    //停止定时器 
    public void stopTimer(){ 
        timer.cancel(); 
    } 
}

 

Mainactivity.java:

package com.example.l0828_service; 
import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
public class MainActivity extends Activity implements OnClickListener{ 
    private Button btn_start,btn_stop; 
    //声明Intent用于Activity向Service的跳转 
    private Intent intent; 
    @Override
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        btn_start=(Button) findViewById(R.id.btn_start); 
        btn_stop=(Button) findViewById(R.id.btn_stop); 
        btn_start.setOnClickListener(this); 
        btn_stop.setOnClickListener(this); 
        //Activity组件向Service组件的跳转 
        intent=new Intent(MainActivity.this,MyService.class); 
    } 
    @Override
    public void onClick(View v) { 
        switch (v.getId()) { 
        case R.id.btn_start: 
            //开启服务 
            startService(intent); 
            break; 
        case R.id.btn_stop: 
            //停止服务 
            stopService(intent); 
            break; 
        } 
    } 
}

主配置文件.xml文件中注册:

<service android:name="MyService"></service>

运行效果:

起始界面

Android Service和广播第1张

点击开始——停止的过程显示:

Android Service和广播第2张

停止之后再次点击开始按钮又重新执行onCreate方法:

Android Service和广播第3张

2.以绑定方式使用的Service

(1)特点:

A.通过Content.bindService()绑定而建立与服务器的连接,通过Content.unbindService()方法解除绑定从而断开与服务器的连接;

B.如果没有调用startService直接通过调用bindService绑定服务器也会自动启动服务器;

C.能获得Service的对象,从而能够使得其他组件与Service的交互;

D.同一个Service可以绑定多个服务连接,同时与不同的组件交互;

(2)生命周期:

onCreate——>onBind——>onCommand——>onUnbind——>onRebind——>onDestroy

如果onUnbind方法返回true,则当取消绑定之后重写绑定服务时就直接调用onRebind方法了。

3)示例代码:

MyService.java:

 

package com.example.l0828_service2; 
import java.util.Timer; 
import java.util.TimerTask; 
import android.app.Service; 
import android.content.Intent; 
import android.os.Binder; 
import android.os.IBinder; 
public class MyService extends Service{ 
    private Timer timer; 
    private TimerTask task; 
    private int i=0; 
    private int j=0; 
    //创建内部类,用于创建Binder对象,onBinder方法中使用 
    class MyBinder extends Binder{ 
        public MyService getService(){ 
            return MyService.this; 
        } 
    } 
    private MyBinder binder=new MyBinder(); 
    public int getI() { 
        return i; 
    } 
    public void setI(int i) { 
        this.i = i; 
    } 
                                                                                                                                                                                                                      
    public int getJ() { 
        return j; 
    } 
    public void setJ(int j) { 
        this.j = j; 
    } 
    //下面分别重写Service生命周期的方法 
    @Override
    public IBinder onBind(Intent intent) { 
        //绑定服务,开始于界面交互 
        startTimer(); 
        System.out.println("onBind"); 
        return binder; 
    } 
    @Override
    public void onCreate() { 
        System.out.println("onCreate"); 
        super.onCreate(); 
    } 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) { 
        System.out.println("onStartCommand"); 
        return super.onStartCommand(intent, flags, startId); 
    } 
    @Override
    public boolean onUnbind(Intent intent) { 
        //解除与服务器的绑定,停止与界面的交互 
        stopTimer(); 
        System.out.println("onUnbind"); 
        //为了使onRebind能够调用到,使得onUnbind的返回值为true 
        super.onDestroy(); 
        return true; 
    } 
    @Override
    public void onRebind(Intent intent) { 
        System.out.println("onRebind"); 
        super.onRebind(intent); 
    } 
    @Override
    public void onDestroy() { 
        System.out.println("onDestroy"); 
                                                                                                                                                                                                                      
    } 
    //创建定时器,即创建另一个线程负责计时 
    public void startTimer(){ 
        timer=new Timer(); 
        task=new TimerTask() { 
                                                                                                                                                                                                                              
            @Override
            public void run() { 
                i++; 
                if(i==j){ 
                    System.out.println("此时您输入的数据于服务数据相同:"+j); 
                } 
                System.out.println(i); 
            } 
        }; 
        timer.schedule(task, 1000,1000); 
    } 
    //停止计时 
    public void stopTimer(){ 
        timer.cancel(); 
    } 
}

 

MainActivity.java:

package com.example.l0828_service2; 
import com.example.l0828_service2.MyService.MyBinder; 
import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.Toast; 
public class MainActivity extends Activity implements OnClickListener,ServiceConnection{ 
    private Button btn_bind,btn_unBind,btn_getService,btn_start,btn_stop; 
    private Intent intent; 
    private MyService myservice; 
    private EditText et; 
    @Override
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        et=(EditText) findViewById(R.id.et); 
        btn_bind=(Button) findViewById(R.id.btn_bind); 
        btn_unBind=(Button) findViewById(R.id.btn_unBind); 
        btn_getService=(Button) findViewById(R.id.btn_getService); 
        btn_start=(Button) findViewById(R.id.btn_start); 
        btn_stop=(Button) findViewById(R.id.btn_stop); 
        btn_bind.setOnClickListener(this); 
        btn_unBind.setOnClickListener(this); 
        btn_getService.setOnClickListener(this); 
        btn_start.setOnClickListener(this); 
        btn_stop.setOnClickListener(this); 
        intent=new Intent(MainActivity.this, MyService.class); 
    } 
    @Override
    public void onClick(View v) { 
        switch (v.getId()) { 
        case R.id.btn_bind: 
            bindService(intent, this, BIND_AUTO_CREATE); 
            break; 
        case R.id.btn_unBind: 
            unbindService(this); 
            break; 
        case R.id.btn_getService: 
            String info=et.getText().toString(); 
            if("".equals(info)){ 
                Toast.makeText(MainActivity.this,"当前的i值:"+myservice.getI() , Toast.LENGTH_SHORT).show(); 
            } 
            myservice.setJ(Integer.parseInt(info)); 
            break; 
        case R.id.btn_start: 
            startService(intent); 
            break; 
        case R.id.btn_stop: 
            stopService(intent); 
            break; 
        } 
    } 
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) { 
        MyService.MyBinder binder=(MyBinder) service; 
        myservice=binder.getService(); 
    } 
    @Override
    public void onServiceDisconnected(ComponentName name) { 
                                                                                                                                                                                                               
    } 
                                                                                                                                                                                                           
}

运行效果:

初始界面:

Android Service和广播第4张

依次点击start、bind、unbind、输入一个服务还未计时到的数、getService、stop的过程:

Android Service和广播第5张

下图是上面执行过程的输出情况,可以清晰明了的看出整个执行的过程:

Android Service和广播第6张

下面是这样的执行顺序的结果:

start、bind、输入及时数据、getService、unbind、(正是此时调用了onRebind方法)bind、unbind、stop的过程

Android Service和广播第7张

二.BroadcastReceiver的使用

1.使用广播实现简单的数据接收功能:

(1)MainActivity.java:

package com.example.l0829_broadcastreceiver; 
import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
public class MainActivity extends Activity { 
    @Override
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        findViewById(R.id.btn_send).setOnClickListener(new OnClickListener() { 
                                                                                                                        
            @Override
            public void onClick(View v) { 
                //仍然是使用Intent来实现组件之间的跳转 
                Intent intent=new Intent(MainActivity.this, MyBroadCastReceiver.class); 
                //把要向广播接收器发送的数据用Intent对象封装,注意键值要相同 
                intent.putExtra("name", "我接收到了"); 
                //发送数据 
                sendBroadcast(intent); 
            } 
        }); 
    } 
}

(2)MyBroadcastReceiver.java:

package com.example.l0829_broadcastreceiver; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
//继承BroadcastReceiver 
public class MyBroadCastReceiver extends BroadcastReceiver{ 
    //只需重写OnReceiver方法 
    @Override
    public void onReceive(Context context, Intent intent) { 
        //接收特定键值的数据,实现广播接收器的基本功能 
        String str=intent.getStringExtra("name"); 
        System.out.println(str); 
    } 
}

(3)一定不要忘记注册啊(四大基本组件是都需要在主配置文件中注册的):

<receiver android:name="MyBroadCastReceiver"></receiver>

2.再实现一个系统默认广播的例子——电量改变的广播:

(1)MainActivity.java

package com.example.l0829_system_broadcastreceiver; 
import android.app.Activity; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.os.Bundle; 
import android.widget.TextView; 
public class MainActivity extends Activity { 
    //创建一个广播的实例,在其onReceive方法中实现接收的过程 
    private  BroadcastReceiver myBR=new BroadcastReceiver(){ 
        @Override
        public void onReceive(Context context, Intent intent) { 
                //if(Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction()))这里也可以先判断一下,确保正确性 
                //下面就是接收系统当前电量信息的过程,注意这里的键值level和scale是系统固定值,不能改变 
                int level=intent.getIntExtra("level", 0); 
                int scale=intent.getIntExtra("scale", 100); 
                tv.setText("当前电量:"+level*100/scale+"%"); 
            } 
    }; 
    //声明一个TextView用来显示接受的当前电量值 
    private TextView tv; 
    @Override
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        tv=(TextView) findViewById(R.id.tv_receive); 
        //动态注册广播的方法,在onCreate方法中 
        registerReceiver(myBR, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 
    } 
    @Override
    protected void onStop() { 
        //在onStop方法中取消广播的注册 
        unregisterReceiver(myBR); 
        super.onStop(); 
    } 
}

(2)由于在代码中实现了Receiver的动态注册,那么主配置文件中就不用注册了

(3)运行效果:(有点小哈,凑合看看吧)

(另外有一个温馨提示:模拟器的电量值永远是50%,可以用真机测试)

Android Service和广播第8张

 

 

 

 

 

3.最后算是来个总结吧:

   我们实现一个Activity、Service、BroadcastReceiver三大组件结合使用的例子,完成Service始终在后台计时、BroadcastReceiver接收数据并及时更新主Activity的过程:

(1)MyService.java

package com.example.l0829_zujian_all; 
import java.util.Timer; 
import java.util.TimerTask; 
import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
public class MyService extends Service{ 
    private Timer timer; 
    private TimerTask task; 
    private int i=0; 
    private Intent intent; 
    public int getI() { 
        return i; 
    } 
    public void setI(int i) { 
        this.i = i; 
    } 
    @Override
    public void onCreate() { 
        //开始服务 
        startTimer(); 
        super.onCreate(); 
    } 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) { 
        return super.onStartCommand(intent, flags, startId); 
    } 
    @Override
    public IBinder onBind(Intent intent) { 
        return null; 
    } 
    @Override
    public boolean onUnbind(Intent intent) { 
        return super.onUnbind(intent); 
    } 
    @Override
    public void onRebind(Intent intent) { 
        super.onRebind(intent); 
    } 
    @Override
    public void onDestroy() { 
        //停止服务 
        stopTimer(); 
        super.onDestroy(); 
    } 
    public void startTimer(){ 
        timer=new Timer(); 
        task=new TimerTask() { 
                                
            @Override
            public void run() { 
                i++; 
                //在计时器中及时向ACTION_MY的BroadcastReceiver接收器中发送键值为id的数据 
                intent=new Intent(); 
                intent.setAction("ACTION_MY"); 
                intent.putExtra("id", i); 
                sendBroadcast(intent); 
            } 
        }; 
        timer.schedule(task, 500,1000); 
    } 
    public void stopTimer(){ 
        timer.cancel(); 
    } 
}

(2)MainActivity.java

package com.example.l0829_zujian_all; 
import android.app.Activity; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.TextView; 
public class MainActivity extends Activity implements OnClickListener{ 
    //创建接收器对象,并在onReceive方法中接收键值为id的数据 
    private BroadcastReceiver br=new BroadcastReceiver() { 
                       
        @Override
        public void onReceive(Context context, Intent intent) { 
            int val=intent.getIntExtra("id", 0); 
            System.out.println(intent.getIntExtra("id", 0)); 
            tv_show.setText(val+""); 
        } 
    }; 
    private Button btn_start,btn_stop; 
    private TextView tv_show; 
    private Intent intent; 
    @Override
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        tv_show=(TextView) findViewById(R.id.tv_show); 
        btn_start=(Button) findViewById(R.id.btn_start); 
        btn_stop=(Button) findViewById(R.id.btn_stop); 
        btn_start.setOnClickListener(this); 
        btn_stop.setOnClickListener(this); 
        intent=new Intent(MainActivity.this, MyService.class); 
        //接收器的动态注册,Action必须与Service中的Action一致 
        registerReceiver(br, new IntentFilter("ACTION_MY")); 
    } 
    @Override
    public void onClick(View v) { 
        switch (v.getId()) { 
        case R.id.btn_start: 
            startService(intent); 
            break; 
        case R.id.btn_stop: 
            stopService(intent); 
            break; 
        } 
    } 
    @Override
    protected void onDestroy() { 
        //取接收器的消注册 
        unregisterReceiver(br); 
        super.onDestroy(); 
    } 
}

(3)注册Service,而BroadcastReceiver就不用再注册了

(4)运行效果:

Android Service和广播第9张

 

 

 

 

 

 

Android Service和广播第10张

 

 

 

 

 

即一个计时更新主页面的功能

 

 

免责声明:文章转载自《Android Service和广播》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Redis布隆过滤器SwiftUI:Swift语法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android开发 设备横屏与竖屏的详解

需要了解横竖屏切换关键知识  1.在Android设备的横竖屏幕,每一次切换横竖屏其实是在重新创建Activity,Activity会重新走一遍生命周期.从onCreate 到 onDestroy   2.在Activity类里的变量也会重新创建,这点需要注意! 判断屏幕方向,方式一判断屏幕是否竖屏   @Override protected vo...

Android基础——广播(静态注册)

安卓版本高了就会有点问题,不能静态注册  令活动Main用来发广播,另一个接收器(不是Activity而是receiver)用来接收广播 注册文件 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/r...

WPF默认控件模板的获取和资源词典的使用

一、获取默认的控件模板WPF修改控件模板是修改外观最方便的方式,但是会出现不知道原来的控件的模板长什么样,或者想用来参考的,下面分享一下获取某控件默认控件模板的方式(已Button为例): 1、创建一个Button 2、在界面上选择Button,右键->编辑模板->编辑副本 ,即可看到XAML中自动生成了原始的控件模板 3、可以在默认模板上修改...

Android 11 拍照问题

安卓11有权限要求,以下方法管用 //跳转到相机 private void showCamera() { File fileDir = new File(Environment.getExternalStorageDirectory(),"Pictures"); if (!fileDir.exists()...

Android Tv 中的按键事件 KeyEvent 分发处理流程

本篇文章已授权微信公众号 安卓巴士Android开发者门户 独家发布 这次打算来梳理一下 Android Tv 中的按键点击事件 KeyEvent 的分发处理流程。一谈到点击事件机制,网上资料已经非常齐全了,像什么分发、拦截、处理三大流程啊;或者 dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent 啊...

PyQt5-按钮关闭窗体-4

import sys from PyQt5.QtWidgets import QApplication, QWidget,QToolTip,QPushButton from PyQt5.QtGui import QIcon,QFont from PyQt5.QtCore import QCoreApplication #demo_4:通过一个按钮关闭窗体...