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

  

前言:  

   我们都知道 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) {                                                                                                                                                                                                                 }

   }
}

  运行效果:

    依次点击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-04-07 09:10:17 重新编辑]
  Java面向对象编程-->Java注解
  JavaWeb开发-->JSP技术详解(Ⅰ)
  JSP与Hibernate开发-->Spring、JPA与Hibernate的整合
  Java网络编程-->用Axis发布Web服务
  精通Spring-->绑定表单
  Vue3开发-->绑定表单
  Android面试题汇总
  android 自动化测试之MonkeyRunner学习
  Android中shape的使用
  在Window中下载Android源代码的步骤
  Android 安装实战
  Android SDCard UnMounted 流程分析
  Android定义的路径全局变量
  Android 使用SQLite数据库
  Android中的Intent Filter与安全
  Scroll的原理和简单使用
  UI渲染机制以及优化
  Android 应用程序组件
  Android网络编程之Http通信
  怎么让软键盘弹出时,部分控件上移
  Android - 监听WebView加载失败的处理
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


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