[详细]android中的service、IntentService、BindService

2024-05-11 03:18

本文主要是介绍[详细]android中的service、IntentService、BindService,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Service 服务

Service是一个不提供用户界面在后台执行耗时操作的应用程序组件。
没界面 运行在后台 耗时操作.
注意:service服务运行在主进程的主线程中
service默认不会开启工作线程
如果执行耗时操作时 需要程序员手动开启工作线程
Service不是一个进程也不是一个线程

什么情况下使用service什么情况使用worker Thread ? 耗时操作
如果执行耗时操作时用户不需要与app交互(耗时操作的结果可能不展示到用户界面)时采用service 例如:下载文件存储
如果执行耗时操作用户需要与app交互(耗时操作的结果需要展示到ui)时采用开启worker Thread 例如:ui界面网络加载

按照服务的启动方式 将服务划分为两类

启动服务 startService()
绑定服务 bindService()

启动式服务:应用程序组件(Activity)调用startService()方法启动服务时称为启动时服务
特点:
1.调用startService()方法一旦启动服务就会一直运行在后台 直到服务被杀死(自杀、他杀、系统回收)
2.启动服务的组件(Activity)被销毁后 启动的服务会一直运行 不受影响
3.启动式服务在后台执行单一的操作 不会将服务的操作结果*返回*给启动它的组件

/*** 点击按钮启动服务* @param view*/public void start(View view){Intent intent=new Intent(MainActivity.this,MyService.class);intent.putExtra("str","传递数据到service");startService(intent);//启动服务}/*** 点击按钮停止服务* @param view*/public void stop(View view){Intent intent=new Intent(MainActivity.this,MyService.class);stopService(intent);//根据intent中指定的对象停止服务}

启动式服务的生命周期
1. 当应用程序组件(Activity)调用startService()启动服务先回调onCreate()方法创建和初始化service—
2.接着回调onStartCommand()方法接收Intent意图请求并且开启工作线程执行耗时操作—-
3.当service中的操作执行完毕后调用StopSelf()或者时其它组件调用 stopService()就会回调onDestory()释放资源

启动时服务生命周期
onCreate()—>onStartCommand()—>StopService()

public class MyService extends Service{@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}/*** 表示当service第一次创建时回调的函数  初始化  注意:service只能被创建一次*/@Overridepublic void onCreate() {super.onCreate();Log.i("tag","--------onCreate-----");}/*** 表示当应用程序组件调用startService()方法启动服务时 服务就会启动并且回调该方法* @param intent  应用程序组件调用startService()启动服务时传递的Intent对象* @param flags   表示开启服务是够需要传递额外的数据* @param startId 用来唯一标示start请求* @return 表示当系统回调完onStartCommand()方法后 service被系统意外杀死时  是否能够重新启动服务以及* 是否可以继续执行请求操作*  根据返回值将service划分为粘性service和非粘性service** START_STICKY(常量1) STICKY粘性  当应用程序执行完onStartCommand()方法后 service被异常kill* 系统会自动重启服务  但是在重启服务时传入的intent为null  车祸苏醒失忆** START_NOT_STICKY(常量2) 非粘性  当应用程序执行完onStartCommand()方法后 service被异常kill* 系统不会自动重启服务       车祸死亡** START_REDELIVER_INTENT(常量3) 当应用程序执行完onStartCommand()方法后 service被异常kill* 系统会自动的重启服务并且将Intent重新传入   车祸苏醒正常*/@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.i("tag","--------onStartCommand-----"+intent.getStringExtra("str"));try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}
//        stopSelf();//自杀return START_REDELIVER_INTENT;}/*** 标示当service被销毁时回调的函数   资源释放* stopService();*/@Overridepublic void onDestroy() {super.onDestroy();Log.i("tag","--------onDestroy-----");}
}

示例:
/**
* 需求:点击按钮时启动服务下载图片 下载完成后存储到本地并且发送一个通知
* 点击通知打开下载的图片
*/

public class MainActivity extends AppCompatActivity {private String imageUrl="http://f.hiphotos.baidu.com/image/h%3D200/sign=236c94ef2c381f3081198aa999004c67/242dd42a2834349bbe78c852cdea15ce37d3beef.jpg";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}//点击按钮启动服务下载图片public void downLoad(View view){Intent intent=new Intent(MainActivity.this,DownLoadService.class);intent.putExtra("imagePath",imageUrl);startService(intent);}
}
public class DownLoadService extends Service{@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}//获取下载图片的地址--启动工作线程--下载图片--存储到本地--发送通知@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {//1.获取下载图片的地址final String imagePath=intent.getStringExtra("imagePath");//2.启动工作线程 service本身是在主线程的主进程中且本身不会开启线程,因而需要自己手动开启线程new Thread(new Runnable() {@Overridepublic void run() {//3.下载图片if(HttpUtils.isNetWorkConn(DownLoadService.this)){byte[] buff=HttpUtils.getHttpResult(imagePath);if(buff!=null && buff.length!=0){String fileName=imagePath.substring(imagePath.lastIndexOf("/")+1);//4.存储到本地boolean bl=ExternalStorgaUtils.writeExternalStoragePublic(Environment.DIRECTORY_DOWNLOADS,fileName,buff);if(bl){Log.i("tag","存储成功");//5.发送通知sendNotification(fileName);}else{Log.i("tag","存储失败");}}else{Log.i("tag","下载失败");}}else{Log.i("tag","网络异常");}}}).start();return super.onStartCommand(intent, flags, startId);}//发送通知的方法public void sendNotification(String fileName){NotificationCompat.Builder builder=new NotificationCompat.Builder(DownLoadService.this);builder.setContentTitle("提示信息");builder.setContentText("下载完成");builder.setSmallIcon(R.mipmap.ic_launcher);Intent intent=new Intent(DownLoadService.this,ResultActivity.class);intent.putExtra("fileName",fileName);PendingIntent pi=PendingIntent.getActivity(DownLoadService.this,1,intent,PendingIntent.FLAG_ONE_SHOT);builder.setContentIntent(pi);NotificationManager manager= (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);manager.notify(1,builder.build());}public class ResultActivity extends AppCompatActivity{private ImageView iv;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_result);iv= (ImageView) findViewById(R.id.iv);//获取通知中传递的文件名称String fileName=getIntent().getStringExtra("fileName");//获取图片文件的路径  storage/sdcard/downloads/filenameString pathName= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()+ File.separator+fileName;//decodeFile(String path) 根据参数中指定图片的路径转换成bitmap对象Bitmap bm= BitmapFactory.decodeFile(pathName);iv.setImageBitmap(bm);//关闭通知NotificationManager manager= (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);manager.cancel(1);}
}

IntentService

IntentService和Service的区别?
IntentService是Service的具体子类
当服务中只需要开启一个工作线程就可以完成耗时操作时 这时建议采用IntentService
当服务中仅开启一个工作线程并不能满足需求时 建议开启多个工作线程 使用service

IntentService的特点:

1.IntentService底层采用队列的形式管理发送的 Intent对象 其它组件发送的请求都会
存储到该队列中 IntentService中回调onHandleIntent()方法依次处理队列中的请求
onHandleIntent()底层已经开启工作线程
2. 当应用程序组件(Activity)调用startService()启动 IntentService时会执行
* onCreate()-onStartCommand()-onHandleIntent()-onDestory()
* 注意:onHandleIntent()执行完成请求后将服务自动销毁
*/

/*** 需求:根据网络地址下载apk文件 并且下载完成后在线安装*/
public class MainActivity extends AppCompatActivity {private String apkPath="http://apk.99danji.com/99apk/FlappyBird_20150730.apk";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}//点击按钮启动服务public void start(View view){Intent intent=new Intent(MainActivity.this,MyIntentService.class);intent.putExtra("path",apkPath);//启动服务时传递apk的下载地址startService(intent);}
}

绑定服务

应用程序组件(Activity)调用bindService()方法启动服务时 称为绑定服务
bindService()将服务玉启动服务绑定到一起

特点:

1.绑定式服务类似与客户端-服务端的接口形式 允许应用程序组件(Activity)与服务进行交互
(activity可以访问service的方法)
2.应用程序组件(Activity)调用bindService()方法将activity与service绑定到一起并且启动运行service
3.应用程序组件与service运行时间一致
多个应用程序组件可以同时绑定到同一个服务 服务销毁 绑定解除
当绑定多个应用程序的组件都被销毁时 服务也跟着被销毁
一方销毁另一方跟着销毁

绑定式服务的生命周期:

应用程序组件(Activity)调用bindService()绑定服务时回调用onCreate()创建服务--
回调onbind()方法将应用组件与service绑定到一起建立链接–当应用程序组件退出或者调用
unBindService()方法时解除绑定回调onUnBind()方法-- 最后当所有绑定服务的应用程序
都退出时回调onDestory()销毁服务

public class MainActivity extends AppCompatActivity {private MyServiceConnection connection;private MyService myService;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);connection=new MyServiceConnection();}/*** 以内部类的形式构建ServiceConnection接口子类*/public class MyServiceConnection implements ServiceConnection{/*** 表示当应用程序组件与service绑定成功后回调的函数* @param name* @param service*/@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.i("tag","-------onServiceConnected------");MyService.MyBinder myBinder= (MyService.MyBinder) service;//向下转型 Ibinder---MyBindermyService=myBinder.getService();//获取service的对象int num=myService.getRandom();Log.i("tag","获取的随机数是:"+num);}/*** 表示绑定服务意外中断时回调的函数* @param name*/@Overridepublic void onServiceDisconnected(ComponentName name) {}}/*** 点击按钮绑定服务*/public void bind(View view){/*bindService(Intent service, @NonNull ServiceConnection conn,int flags)Intent service,   表示绑定服务的意图对象(允许采用隐式意图和显式意图)@NonNull ServiceConnection conn, 表示监听当前组件绑定的服务变化的接口int flags 表示对绑定服务操作的标记返回值为boolean类型  表示是否成功绑定服务BIND_AUTO_CREATE 常量 表示绑定服务时若服务没有创建 则先创建再绑定*/Intent intent=new Intent(MainActivity.this,MyService.class);boolean bl=bindService(intent,connection, Context.BIND_AUTO_CREATE);Log.i("tag","服务绑定成功了吗?"+bl);}/*** 点击按钮解除绑定服务*/public void unBind(View view){unbindService(connection);//解除绑定}
}
public class MyService extends Service{/*** 表示服务第一次创建时回调的函数*/@Overridepublic void onCreate() {super.onCreate();Log.i("tag","---------onCreate------");}/** 需求:绑定服务的activity组件访问service中的getRandom()方法该如何操作?*  如果想要调用类中的函数 需要创建类的对象 然后对象.函数() 但是service是一个应用程序组件*  所以在使用时不能直接通过new service()de形式构建对象 如何获取service类的对象?*  发现应用程序组件调用bindService()方法绑定服务成功可以获取onBind()方法的返回值IBinder对象*  IBinder是一个接口 所以在service中定义一个IBinder类的子类 发现如果直接实现IBinder接口 需要*  重写的函数比较多 所以选择继承IBinder这个接口的子类Binder类  在继承Binder类的内部类中*  定义一个函数返回当前servive的对象 那么activity与service链接成功后就可以获取Ibinder对象*  进而就获取服务对象*/public int getRandom(){return (int) (Math.random()*10+1);}/*** 表示应用程序组件(activity)调用bindService()方法绑定服务时*  注意:应用程序与service只能绑定一次* @param intent* @return*/@Nullable@Overridepublic IBinder onBind(Intent intent) {Log.i("tag","---------onBind------");return new MyBinder();}/*构建Ibinde若接口的具体子类对象*/public class MyBinder extends Binder{//定义函数 返回当前service服务类的对象public MyService getService(){return MyService.this;}}/*** 表示应用程序组件(activity)与service解除绑定时回调的函数* @param intent* @return*/@Overridepublic boolean onUnbind(Intent intent) {Log.i("tag","---------onUnbind------");return super.onUnbind(intent);}/*** 表示当其它的应用程序组件绑定服务时回调的函数* @param intent*/@Overridepublic void onRebind(Intent intent) {super.onRebind(intent);Log.i("tag","---------onRebind------");}/*** 表示当service销毁时回调的函数*/@Overridepublic void onDestroy() {super.onDestroy();Log.i("tag","---------onDestroy------");}
}

示例:bindService实现后台播放音乐

public class MainActivity extends AppCompatActivity {private ServiceConnection conn;private PlayMusicService playMusicService;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);conn=new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {PlayMusicService.MyBinder myBinder= (PlayMusicService.MyBinder) service;playMusicService=myBinder.getService();}@Overridepublic void onServiceDisconnected(ComponentName name) {}};Intent intent=new Intent(this,PlayMusicService.class);boolean bl=bindService(intent,conn, Context.BIND_AUTO_CREATE);Log.i("tag","服务绑定成功了吗?"+bl);}/*** 点击按钮执行操作* @param view*/public void clickView(View view){switch (view.getId()){case R.id.btn_play:playMusicService.playMusic();break;case R.id.btn_pause:playMusicService.pauseMusic();break;case R.id.btn_stop:playMusicService.stopMusic();break;}}
}
public class PlayMusicService extends Service{private MediaPlayer mediaPlayer;private boolean isStop=false;//标示是否停止@Overridepublic void onCreate() {super.onCreate();initMediaPlayer();//初始化操作}/*初始化MediaPlayer*/public void initMediaPlayer(){if(mediaPlayer==null){mediaPlayer=new MediaPlayer();}mediaPlayer.reset();try {//设置assets资产中的文件作为MediaPlayer播放音频源AssetFileDescriptor sdf=getAssets().openFd("thatway.mp3");mediaPlayer.setDataSource(sdf.getFileDescriptor(),sdf.getStartOffset(),sdf.getLength());mediaPlayer.prepare();//准备方法  播放之前MediaPlayer必须处于准备状态if(sdf!=null){sdf.close();}} catch (IOException e) {e.printStackTrace();}//表示播放异常时触发的监听器mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {mp.reset();Toast.makeText(PlayMusicService.this,"播放异常!",Toast.LENGTH_LONG).show();return false;}});//表示播放完毕后触发的监听器mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {Toast.makeText(PlayMusicService.this,"音乐播放完毕!",Toast.LENGTH_LONG).show();}});}/*播放音乐*/public void playMusic(){if(isStop){initMediaPlayer();isStop=false;}if(mediaPlayer!=null && !mediaPlayer.isPlaying()){//isPlaying() true表示正在播放mediaPlayer.start();//播放音乐}}/*暂停音乐*/public void pauseMusic(){if(mediaPlayer!=null && mediaPlayer.isPlaying()){mediaPlayer.pause();}}/*停止播放*/public void stopMusic(){if(mediaPlayer!=null){mediaPlayer.stop();isStop=true;}}@Nullable@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}public class MyBinder extends Binder{public PlayMusicService getService(){return PlayMusicService.this;}}@Overridepublic boolean onUnbind(Intent intent) {if(mediaPlayer!=null){mediaPlayer.release();//重置mediaPlayer=null;}return super.onUnbind(intent);}
}

这篇关于[详细]android中的service、IntentService、BindService的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/978355

相关文章

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

沁恒CH32在MounRiver Studio上环境配置以及使用详细教程

目录 1.  RISC-V简介 2.  CPU架构现状 3.  MounRiver Studio软件下载 4.  MounRiver Studio软件安装 5.  MounRiver Studio软件介绍 6.  创建工程 7.  编译代码 1.  RISC-V简介         RISC就是精简指令集计算机(Reduced Instruction SetCom

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

arduino ide安装详细步骤

​ 大家好,我是程序员小羊! 前言: Arduino IDE 是一个专为编程 Arduino 微控制器设计的集成开发环境,使用起来非常方便。下面将介绍如何在不同平台上安装 Arduino IDE 的详细步骤,包括 Windows、Mac 和 Linux 系统。 一、在 Windows 上安装 Arduino IDE 1. 下载 Arduino IDE 打开 Arduino 官网

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR