Service启动模式
Service简介
Service表示服务,是Android系统的核心组件之一。
Service的本质是一个继承了android.app.Service的java类;
每一个Service都应该在AndroidMainfest.xml文件中进行注册;
Service由Android系统进行维护。
Service没有匹配的用户界面,通常用于后台处理耗时操作。
不允许在主线程中执行耗时操作。
Service是运行在主线程中的;
尽管Service被定位为“用于处理耗时操作”,但是各种耗时操作需要在Service中另外开辟线程来完成。
组件可以绑定到Service,实现进程间通信(Inter Process Communication)。
进程优先级:
Android系统力图维护尽可能多的线程,但由于设备性能有限,在动态管理内存的过程中,Android系统
会经常能够终止一些优先级低的进程,以释放资源,保证优先级高的进程正常运行。
进程优先级分类:
1、前台进程(Forground Process)
2、可见进程(Visible Process)
3、服务进程(Service Process)
4、后台进程(BackGround Process)
5、空进程(Empty Process)
启动Service
开发人员可以使用Intent激活Service组件。
激活Service组件的方式有:
调用Context定义的startService()方法(启动)
调用Context定义的bindService()方法(绑定)
启动Service的开发流程
启动Service的开发流程如下:
1、创建java类,继承android.app.Service;(Service中定义了抽象方法onBlind(),该方法必须被重写,但不一定需要被具体实现)
2、在AndroidMainfest.xml中的<application>下添加<service>子节点,
配置创建的Service;
3、在Activity中调用startService(Intent intent)方法启动Service;
显式或隐式启动Service
无论是显式Intent或隐式Intent都可以激活Service组件。
如果需要实现进程间通信,则应该为Service组件配置隐式意图过滤器。
停止Service
通过调用Context的stopService(Intent intent)方法可以停止Service,并销毁该Service组件。
在Service中调用stopSelf()方法可以停止自身。
Service的生命周期
如果Activity反复调用startService()方法,在Service中只会反复调用onStartCommand()方法。
Service类:
AndroidMainfest.xml
Service的粘性
Service的粘性:Service的粘性表现为其所在进程被意外中止后,该Service是否可以自动重新被启动。
默认情况下,使用startService()方式激活的Service组件是粘性的,则即使其所在进程被意外中止了,
稍后该Service依然会被自动创建出来。
设置Service的粘性
在Service生命周期中onStartCommand()方法的返回值决定了Service的粘性。
该方法的返回值可以被设置为:
START_STICKY:粘性的,被意外中止后自动重启,但丢失原来用于激活它的Intent;
START_NOT_STICKY:非粘性的,被意外中止后不会自动重启;
START_REDELIVER_INTENT:粘性的且重新发送Intent,即被意外中止后自动重启,且该Service
组件将得到原来用于激活它的Intent对象;
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,并不担保onStartCommand()会被重新调用。
案例:
Service播放音乐
使用系统的MediaPlayer类可以播放音乐,开发步骤如下:
创建MediaPlayer对象,可直接使用无参数构造方法;
调用MediaPlaye的reset()方法重置(不必要);
调用MediaPlayer的setDataSource()方法设置需要播放的歌曲;
调用MediaPlayer的prepare()方法加载(缓冲)歌曲;
调用MediaPlayer的start()方法播放歌曲;
当退出时应该调用release()方法释放资源。
本例的业务逻辑:
通过Activity激活Service,且在Service中创建mediaPlayer的实例,实现歌曲的播放;
被播放的歌曲保存在模拟器的sdcard/Misic/中;
当Activity被停止时,停止播放歌曲的Service;
当Service被停止时,释放MediaPlayer的资源。
Service表示服务,是Android系统的核心组件之一。
Service的本质是一个继承了android.app.Service的java类;
每一个Service都应该在AndroidMainfest.xml文件中进行注册;
Service由Android系统进行维护。
Service没有匹配的用户界面,通常用于后台处理耗时操作。
不允许在主线程中执行耗时操作。
Service是运行在主线程中的;
尽管Service被定位为“用于处理耗时操作”,但是各种耗时操作需要在Service中另外开辟线程来完成。
组件可以绑定到Service,实现进程间通信(Inter Process Communication)。
进程优先级:
Android系统力图维护尽可能多的线程,但由于设备性能有限,在动态管理内存的过程中,Android系统
会经常能够终止一些优先级低的进程,以释放资源,保证优先级高的进程正常运行。
进程优先级分类:
1、前台进程(Forground Process)
2、可见进程(Visible Process)
3、服务进程(Service Process)
4、后台进程(BackGround Process)
5、空进程(Empty Process)
启动Service
开发人员可以使用Intent激活Service组件。
激活Service组件的方式有:
调用Context定义的startService()方法(启动)
调用Context定义的bindService()方法(绑定)
启动Service的开发流程
启动Service的开发流程如下:
1、创建java类,继承android.app.Service;(Service中定义了抽象方法onBlind(),该方法必须被重写,但不一定需要被具体实现)
2、在AndroidMainfest.xml中的<application>下添加<service>子节点,
配置创建的Service;
3、在Activity中调用startService(Intent intent)方法启动Service;
显式或隐式启动Service
无论是显式Intent或隐式Intent都可以激活Service组件。
如果需要实现进程间通信,则应该为Service组件配置隐式意图过滤器。
停止Service
通过调用Context的stopService(Intent intent)方法可以停止Service,并销毁该Service组件。
在Service中调用stopSelf()方法可以停止自身。
Service的生命周期
如果Activity反复调用startService()方法,在Service中只会反复调用onStartCommand()方法。
案例:
<Button
android:id="@+id/btn_start"
android:layout_width="match_parent"
android:layout_height="wrap_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:onClick="doStart"
android:text="Start Service"/>
<Button
android:layout_marginTop="20dp"
android:id="@+id/btn_stop"
android:layout_width="match_parent"
android:layout_height="wrap_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:onClick="doStop"
android:text="Start Service"/>
public void doStart(View view){
Intent intent = new Intent(this,SampleService.class);
startService(intent);
}
public void doStop(View view){
Intent intent = new Intent(this,SampleService.class);
stopService(intent);
}
Service类:
public class SampleService exteds Service{
public void onCreate(){
Log.d(tag,"onCreate")
super.onCreate();
}
public int onStartCommand(Intent intent,int flags,int startId){
Log.d(tag,"onStartCommand");
return super.onStartCommand(intent,flags,startId);
}
public void onDestroy(){
Log.d(tag,"onDestroy");
super.onDestroy();
}
}
AndroidMainfest.xml
<service android:name="com.edu.hpu.cn.SampleService"></service>
Service的粘性
Service的粘性:Service的粘性表现为其所在进程被意外中止后,该Service是否可以自动重新被启动。
默认情况下,使用startService()方式激活的Service组件是粘性的,则即使其所在进程被意外中止了,
稍后该Service依然会被自动创建出来。
设置Service的粘性
在Service生命周期中onStartCommand()方法的返回值决定了Service的粘性。
该方法的返回值可以被设置为:
START_STICKY:粘性的,被意外中止后自动重启,但丢失原来用于激活它的Intent;
START_NOT_STICKY:非粘性的,被意外中止后不会自动重启;
START_REDELIVER_INTENT:粘性的且重新发送Intent,即被意外中止后自动重启,且该Service
组件将得到原来用于激活它的Intent对象;
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,并不担保onStartCommand()会被重新调用。
案例:
Service播放音乐
使用系统的MediaPlayer类可以播放音乐,开发步骤如下:
创建MediaPlayer对象,可直接使用无参数构造方法;
调用MediaPlaye的reset()方法重置(不必要);
调用MediaPlayer的setDataSource()方法设置需要播放的歌曲;
调用MediaPlayer的prepare()方法加载(缓冲)歌曲;
调用MediaPlayer的start()方法播放歌曲;
当退出时应该调用release()方法释放资源。
本例的业务逻辑:
通过Activity激活Service,且在Service中创建mediaPlayer的实例,实现歌曲的播放;
被播放的歌曲保存在模拟器的sdcard/Misic/中;
当Activity被停止时,停止播放歌曲的Service;
当Service被停止时,释放MediaPlayer的资源。
案例:
MainActivity:
package com.edu.hpu.service;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startMusic(View view){
Intent intent = new Intent(this,PlayerMusicService.class);
startService(intent);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
Intent intent = new Intent(this,PlayerMusicService.class);
stopService(intent);
super.onDestroy();
}
}
布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="136dp"
android:onClick="startMusic"
android:text="播放音乐" />
</RelativeLayout>
Service类:
package com.edu.hpu.service;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Environment;
import android.os.IBinder;
public class PlayerMusicService extends Service{
private MediaPlayer player;
@Override
public void onCreate() {
try {
player = new MediaPlayer();
player.reset();
player.setDataSource(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Music/Groove Coverage - She.mp3");
player.prepare();
player.start();
} catch (IllegalArgumentException e) {
// TODO: handle exception
e.printStackTrace();
}catch(SecurityException e){
e.printStackTrace();
}
catch(IllegalStateException e){
e.printStackTrace();
}
catch(IOException e){
e.printStackTrace();
}
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
player.release();
player = null;
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
配置:
<service
android:name="com.edu.hpu.service.PlayerMusicService"></service>
关于MediaPlayer
MediaPlayer支持主流的音频、视频文件的播放,亦支持播放
非本机的媒体文件;
MediaPlayer会开启子线程播放歌曲;
可调用pause()方法暂停播放,调用seekTo()方法快进到指定的
位置开始播放;
可调用prepareAsync()方法加载歌曲,并配置OnPreparedListener,
在监听器用调用MediaPlayer的start()方法;
通常为MediaPlayer配置OnCompletionListener,以实现在播放完成后的处理;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理