>>分享Android开发相关的技术 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 18939 个阅读者 刷新本主题
 * 贴子主题:  Android的Service和广播的讲解 回复文章 点赞(0)  收藏  
作者:mary    发表时间:2020-05-15 01:20:32     消息  查看  搜索  好友  邮件  复制  引用

   前言:  

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

   一.  Service 的使用  

   Service 是 Android 系统的后台服务组件,没有用户界面,但可以长时间的运行,比 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>
   运行效果:

   起始界面

    点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

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

   点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

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

   点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

   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) {
    }

运行效果:
初始界面:

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

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

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

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

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

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

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

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

  二.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%,可以用真机测试)

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

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)运行效果:

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

即一个计时更新主页面的功能,在以后的Android应用开发的过程中,常常会用到,学会了吗?

加油!

            

----------------------------
原文链接:https://blog.51cto.com/wangzhaoli/1285948

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-06-06 15:11:29 重新编辑]
  Java面向对象编程-->继承
  JavaWeb开发-->访问数据库(Ⅰ)
  JSP与Hibernate开发-->Spring、JPA与Hibernate的整合
  Java网络编程-->对象的序列化与反序列化
  精通Spring-->Vue CLI脚手架工具
  Vue3开发-->Vue Router路由管理器
  android webView js方法和java 方法交互-android,unity3d
  Android ListView滑动加载
  Android开发随想:iPhone和Android之间的对话
  Android多线程及异步处理问题
  Android在SDcard建文件夹(在Android中移动文件必用)
  Android自定义组件
  Android多线程及异步处理问题
  Android 解码播放GIF图像
  Android Action Bar 自定义View
  Android SDCard Mount 流程分析
  Android Socket通信
  Android性能优化:App启动原理分析及启动时间优化
  Android_实现商品详情的展示页及布局
  【Android 修炼手册】Gradle 篇 -- Gradle 的基本使用
  Android炫酷菜单
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。