Android四大组件之- Service的创建与应用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

Service分为两种:一种是普通的Service,一种是IntentService。
启动Service的方式也有两种:一种是StartService()启动,一种是BindService()启动。本文重点介绍两种Service的区别和两种启动方式的区别。
本文主要是代码居多,通过代码运行的log打印,观察service的生命周期和特性来达到理解service的目的

一、startservice启动service

启动:
it = new Intent(MainActivity.this, StartFiring.class);
startService(it);
关闭:stopService(it);

StartFiring.java

public class StartFiring extends Service {
    public StartFiring() {
    }
    
    //该方法是Service都必须实现的方法,该方法会返回一个 IBinder对象,app通过该对象与Service组件进行通信!
    //不需要通信时不会调用此方法
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("StartFiring", "onBind()");
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");

    }

    //当Service第一次被创建后立即回调该方法,该方法在整个生命周期 中只会调用一次!
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("StartFiring", "onCreate()");
    }


    //    1.使用startService启动servic时调用
    //   2.多次使用startService启动servic时,不会创建新的Service对象(也就是不会多次调用onCreate方法),但是会多次调用onStartCommand()方法
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("StartFiring", "onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    //当Service被关闭时会回调该方法,该方法只会回调一次!
    @Override
    public void onDestroy() {
        Log.d("StartFiring", "onDestroy()");
        super.onDestroy();
    }
}

二、bindservice启动service

bindservice启动稍微复杂一点,直接上代码,文章最后会有对比总结

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView bt;
    private TextView bt2;
    private TextView bt3;
    private Intent it = null;
    MyService.MyBinder binder;
    private ServiceConnection conn = new ServiceConnection() {

        //Service服务被意外销毁时调用,如内存资源不足
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("MainActivity", "onServiceDisconnected()断开连接");
        }

        //Activity与Service连接成功时回调该方法
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("MainActivity", "onServiceConnected()连接成功");
            binder = (MyService.MyBinder) service;  //获取servicer的数据
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        bt = (TextView) findViewById(R.id.bt);
        bt2 = (TextView) findViewById(R.id.bt2);
        bt3 = (TextView) findViewById(R.id.tex);
        bt3.setOnClickListener(this);
        bt.setOnClickListener(this);
        bt2.setOnClickListener(this);
        it = new Intent(MainActivity.this, MyService.class);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt:
                //绑定service
                bindService(it, conn, Service.BIND_AUTO_CREATE);
                break;
            case R.id.bt2:
                //解除绑定
                unbindService(conn);
                break;
            case R.id.tex:
                Log.d("MainActivity", "count值为:" + binder.getCount());
                break;
        }
    }

MyService.java

public class MyService extends Service {
    private int count;
    private boolean quit = true;
    
    /*
        1.自定义一个内部类继承Binder,类中定义读取service数据的方法,将servie要传递给activity的数据放入Binder对象中
        2.创建内部类对象,onBind方法返回这个对象
        3.activity中通过ServiceConnection的回调方法onServiceConnected()拿到service传递的binder对象
        4.activity调用binder对象中的方法读取servie传递的数据

    */
    //自定义一个内部类继承Binder,类中定义读取service数据的方法,将
    public class MyBinder extends Binder {
        //定义读取service数据的方法
        public int getCount() {
            return count;
        }
    }

    private MyBinder binder = new MyBinder();

    //与activity交互,返回给activity一个IBinder对象
    //
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("MyService", "onBind()");
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("MyService", "onCreate()");
        new Thread() {
            public void run() {
                while (quit) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                }
            }
        }.start();
    }

    @Override
    public void onDestroy() {

        Log.d("MyService", "onDestroy()");
        super.onDestroy();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        quit = false;
        Log.d("MyService", "onUnbind()");
        return super.onUnbind(intent);
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
        Log.d("MyService", "onRebind()");
    }
}

三、Intentservice

MainActivity.java :做了三个启动按钮,每个启动携带的参数不一样,更直观的看到Intentservice的生命周期

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button bt;
    private Button tex;
    private Button bt2;
    private Intent it = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        bt = (Button) findViewById(R.id.bt);
        tex = (Button) findViewById(R.id.tex);
        bt2 = (Button) findViewById(R.id.bt2);

        bt.setOnClickListener(this);
        tex.setOnClickListener(this);
        bt2.setOnClickListener(this);
        it = new Intent(this, MyIntentService.class);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt:
                Bundle bd = new Bundle();
                bd.putString("a", "a");
                it.putExtras(bd);
                startService(it);
                break;
            case R.id.tex:
                Bundle bd2 = new Bundle();
                bd2.putString("a", "b");
                it.putExtras(bd2);
                startService(it);
                break;
            case R.id.bt2:
                Bundle bd3 = new Bundle();
                bd3.putString("a", "c");
                it.putExtras(bd3);
                startService(it);
                break;
        }
    }
}

MyIntentService.java :可通过Intent传递的不同数据执行不同的代码块

public class MyIntentService extends IntentService {
    //必须实现父类的构造方法
    public MyIntentService() {
        super("MyIntentService");
    }

    //必须重写的核心方法,通过activity传递的intent数据执行不同的代码
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("MyIntentService", "onHandleIntent");
        String actin = intent.getExtras().getString("a");
        if (actin.equals("a")) {
            Log.d("MyIntentService", "第一个启动按钮");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //执行具体事务
                    try {
                        Thread.sleep(10000);
                        Log.d("MyIntentService", "Thread1停止");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } else if (actin.equals("b")) {
            Log.d("MyIntentService", "第二个启动按钮");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //执行具体事务
                    try {
                        Thread.sleep(10000);
                        Log.d("MyIntentService", "Thread2停止");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } else if (actin.equals("c")) {
            Log.d("MyIntentService", "第三个启动按钮");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //执行具体事务
                    try {
                        Thread.sleep(10000);
                        Log.d("MyIntentService", "Thread3停止");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } else {
            Log.d("MyIntentService", "其他");
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d("MyIntentService", "onBind");
        return super.onBind(intent);
    }

    @Override
    public void onCreate() {
        Log.d("MyIntentService", "onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("MyIntentService", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void setIntentRedelivery(boolean enabled) {
        super.setIntentRedelivery(enabled);
        Log.d("MyIntentService", "setIntentRedelivery");
    }

    @Override
    public void onDestroy() {
        Log.d("MyIntentService", "onDestroy");
        super.onDestroy();
    }
}

四、Intentservice和全局变量结合使用

首先MainActivity还是与上文Intentservice一样三个启动按钮,每个启动按钮启动携带不同的参数,创建一个Handler和计时器定时读取全局变量的值

然后创建一个实体类:EntityTest.java

public class EntityTest{
    public static int a = 0;
    public static int b = 0;
    public static int c = 0;
}

最后是Intentservice中的核心代码(部分需要重写的方法没有贴上)

public class MyIntentService extends IntentService {
    private boolean x = true;
    private boolean m = true;
    private boolean y = true;

    //必须实现父类的构造方法
    public MyIntentService() {
        super("MyIntentService");
    }
    //必须重写的核心方法,通过activity传递的intent数据执行不同的代码
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("MyIntentService", "onHandleIntent");
        String actin = intent.getExtras().getString("a");
        if (actin.equals("a")) {
            Log.d("MyIntentService", "第一个启动按钮");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //执行具体事务
                    while (x) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        MyBinder.a++;
                        if (MyBinder.a == 20) {
                            x = false;
                        }
                    }
                }
            }).start();
        } else if (actin.equals("b")) {
            Log.d("MyIntentService", "第二个启动按钮");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //执行具体事务
                    while (m) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        MyBinder.b++;
                        if (MyBinder.b == 20) {
                            m = false;
                        }
                    }
                }
            }).start();
        } else if (actin.equals("c")) {
            Log.d("MyIntentService", "第三个启动按钮");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //执行具体事务
                    while (y) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        MyBinder.c++;
                        if (MyBinder.c == 20) {
                            y = false;
                        }
                    }
                }
            }).start();
        } else {
            Log.d("MyIntentService", "其他");
        }

    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("MyIntentService", "onBind");
        return null;
    }
}
  

五、前台服务的实现

前台服务启动和关闭同样与讲解的启动方式一样,这里贴一下service的代码
MyService.java

public class MyService extends Service {
    String id = "logcat";
    String name = null;
    NotificationManager ntmg = null;
    NotificationChannel notcl;
    NotificationCompat.Builder bud;

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
    
    //当Service第一次被创建后立即回调该方法,该方法在整个生命周期 中只会调用一次!
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("StartFiring", "onCreate()");

        //发送log打开的通知
        name = getString(R.string.app_name);
        ntmg = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        // 1.创建NotificationChannel对象,传入id name 和 重要级别
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            notcl = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_HIGH);
            // 2.创建通知的通道
            ntmg.createNotificationChannel(notcl);
        }
        Intent intents = new Intent(MyService.this, MainActivity.class);
        PendingIntent pits = PendingIntent.getActivity(MyService.this, 0, intents, 0);
        bud = new NotificationCompat.Builder(MyService.this, id);
        bud.setContentTitle("前台service服务端")
                .setContentText("正在运行...")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(MyService.this.getResources(), R.drawable.ic_launcher_foreground))
                .setContentIntent(pits);
        //发送通知( id唯一,可用于更新通知时对应旧通知; 通过mBuilder.build()拿到notification对象 )
        startForeground(1,bud.build());
        ntmg.notify(1, bud.build());

    }

    //    1.使用startService启动servic时调用
    //   2.多次使用startService启动servic时,不会创建新的Service对象(也就是不会多次调用onCreate方法),但是会多次调用onStartCommand()方法
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("StartFiring", "onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.d("StartFiring", "onDestroy()");
        super.onDestroy();
    }
}

六、后台服务的实现

同样只贴service核心代码,以下代码执行流程:在activity中打开一次service,进入到service后执行具体的事物,并且间隔两秒发送一个广播,收到广播后再次自动启动service,如此形成循环,涉及到广播的内容下一篇讲解

/*
    手动打开一次线程后,执行具体的事务,然后间隔2秒进入广播,进入广播后在广播中再次启动线程,如此形成循环操作
*/
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //这里开辟一条线程,用来执行具体的逻辑操作:
        new Thread(new Runnable() {
            @Override
            public void run() {
                //循环执行的事务
                Log.d("BackService", new Date().toString());
            }
        }).start();

        manager = (AlarmManager) getSystemService(ALARM_SERVICE);
        //设置循环时间,每隔两秒循环一次
        int anHour = 2 * 1000;
        long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
        Intent i = new Intent(this, MyReceiver.class);
        pi = PendingIntent.getBroadcast(this, 0, i, 0);
        manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
        return super.onStartCommand(intent, flags, startId);
    }

总结

startservice启动普通service:无法通信,可以启动多次,多次启动仅执行一次onCreate方法,但执行多次onStartCommand方法
startservice启动IntentService:可通过inten传递数据到service
bindservice启动普通service:颗获取service中的数据,只能启动一次
bindservice启动IntentService:无实际应用

启动IntentService:
1.activity可以通过inten传递数据到service
2.service通过传递过来的不同参数执行不同操作
3.service执行完毕后会自动关闭

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值