1.1Service——服务
什么是服务? 它也是一个程序。只不过是没有界面的程序。 在windows也是存在服务的。 Android中使用Service实现没有界面的程序,使用场景是: 例如:微信已经关闭,但是依然可以收到外界的消息,这个程序就是一个服务。 当手机用户去往另一个城市,手机自动显示新的城市和实时的天气,背后也是一个服务。 音乐播放时,即使息屏也是可以听到声音,音乐界面已经关闭,但是音乐仍在播放,这是一个服务。 缓存电影到无网的环境播放,下载并不影响正在播放的电影,下载程序就是一个服务程序。 Service是Android4大组件之一,哪些属于android的4大组件: (1)Activity(活动,也就是程序的界面,开发的实践1个Activity+多个fragment) (2)Service(服务,没有界面的程序) (3)BroadCastReceiver(广播接收者,BroadCastSender,跨程序的通信) (4)ContentProvider(内容提供者,跨程序的数据源调用,ContentResolver,ContentObserver) 使用Service需要注意的事项: (1)通常线程是在Activity中发起,那么这个线程的生命周期就属于这个Activity,当这个Activity被回收后,线程就会中断。 例如:A(Actvity)B(Activity)C(Activity),再返回A,BC如果被回收,C中发起的线程就会中断。 C如果发起一个下载的程序,在C被回收时,这个下载程序也会被中断。
activity_a.xml 温馨提示:宝,你要学会自己打代码哦!这里就不放源码了,快来实操一遍啊!
activity_b.xml activity_c.xml AActivity.java CActivity.java 效果: CActivity被回收后(日志停止输出):
1.2创建第一个服务
如何创建Activity? (1)创建一个类继承Activity (2)注册Activity (3)启动Activity startActivity(intent) 如何创建服务? (1)创建一个类继承Service (2)注册 (3)启动Service startService(intent) 【案例】 MyService.java MainActivity.java androidManifest.xml 日志:
2.1Service的生命周期(通过不同生命周期阶段的回调方法来观察)
如何建立一个Service? (1)自定义一个类,继承Service (2)注册 (3)启动,startService(intent) Service的生命周期分为两种不同的Service来观察: (1)Unbound模式下的生命周期(非绑定式) 回调方法有些哪些? onCreate、onStartCommand、onDestroy 【案例】 activity_main.xml MyService.java MainActivity.java androidManifest.xml 效果: 日志: (2)Bounded模式下的生命周期(绑定式) 原理图。 步骤: 1)引入Binder子类,在其中实现调用服务的方法。获得一个Binder实例,这个binder实例可以对Service的生命周期进行控制,这个实例是通过onBind方法返回出去的。 2)编写有关Service的生命周期方法(onCreate\onDestroy) 3)编写有关Service的相关服务方法(不是生命周期方法) 4)引入ServiceConnection,目的是将Binder实例传递给Activity 5)在Activity中使用Binder对Service进行控制。 Bounded方式用到的启动服务的方法: bindService(参数1:intent,参数2:ServiceConnection,参数3:BIND_AUTO_CREATE) 参数1:表示启动什么服务 参数2:binder实例从哪个连接对象中获取 参数3:启动方式,推荐使用:自动创建。 【案例】 activity_main2.xml MyService2.java MainActivity2.java AndroidManifest.xml 效果: 日志:
2.2Service生命周期2(音乐播放器)
日志: Service两种启动模式的生命周期 Service的启动方式有2种: unbounded:无绑定的形式。StartService(intent),特征:服务一旦启动后,不能控制,只能停止,因此不能干预运行的中间过程。例如:听音乐,没有界面,音乐在播放,只能播放(Start)和停止(stop)。停止后,只能从头开始。 方法:startService(intent)、stopService(intent) Bounded:绑定的形式。bindService(intent,conn,BIND_AUTO_CREATE),特征:服务启动后,能对服务全过程进行控制。例如:听音乐的过程,没有界面,音乐可以播放可以暂停。 方法:bindService(intent,conn,BIND_AUTO_CREATE)(启动服务)、unbindService(conn)(停止服务)
2.使用IntentService 默认情况下Service是运行在主线程中,主线程是不能够运行耗时任务的,如果运行耗时任务就会出现“ANR”(application not responding,应用程序无响应,卡顿)。Android对于超过一定时间限制的任务,就会出现ANR提示。
【案例】在service中运行耗时任务,体验ANR。 activity_main2.xml MyService2.java MainActivity2.java 效果:反复点击按钮出现ANR 日志: activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btnBind"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="绑定"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnPlay"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="播放"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnBind" />
<Button
android:id="@+id/btnPause"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="暂停"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnPlay" />
<Button
android:id="@+id/btnUnbind"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="卸绑"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnPause" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main2
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btnStart"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="启动耗时任务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
services包下
MyService
package com.example.myapplication.services;
import android.app.Service;
import android.content.Intent;
import android.nfc.Tag;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
private static final String TAG = "MyService";
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG,"onBind");
return new MyBinder();
}
private void playInService(){
Log.i(TAG,"音乐正在播放...");
}
private void pauseInService(){
Log.i(TAG,"音乐暂停播放...");
}
public class MyBinder extends Binder{
public void Paly(){
playInService();
}
public void pause(){
pauseInService();
}
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG,"onCreate");
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG,"onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.i(TAG,"onDestory");
super.onDestroy();
}
}
MyService2
package com.example.myapplication.services;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyService2 extends Service {
private static final String TAG = "MyService";
public MyService2() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
private Long index=0l;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Long endTime=System.currentTimeMillis()+100*1000;
Log.i(TAG,"耗时任务开始执行...");
while (System.currentTimeMillis()<endTime){
try {
Thread.sleep(100);
Log.i(TAG,"执行次数:"+index);
} catch (InterruptedException e){
e.printStackTrace();
}
}
Log.i(TAG,"耗时任务结束执行...");
return super.onStartCommand(intent,flags,startId);
}
}
MainActivity
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.example.myapplication.services.MyService;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MyService";
private Button btnBind,btnPlay,btnPause,btnUnbind;
private MyService.MyBinder myBinder;
ServiceConnection coon=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i(TAG,"onServiceConnected");
myBinder= (MyService.MyBinder) iBinder;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnBind = findViewById(R.id.btnBind);
btnPlay = findViewById(R.id.btnPlay);
btnPause = findViewById(R.id.btnPause);
btnUnbind = findViewById(R.id.btnUnbind);
btnBind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(MainActivity.this,MyService.class);
Log.i(TAG,"bindService");
bindService(intent,coon,BIND_AUTO_CREATE);
}
});
btnPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (myBinder!=null)
myBinder.Paly();
}
});
btnPause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (myBinder!=null);
myBinder.pause();
}
});
btnUnbind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (myBinder!=null)
myBinder.pause();
}
});
btnUnbind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.i(TAG,"unbindService");
unbindService(coon);
myBinder=null;
}
});
}
}
MainActivity2
package com.example.myapplication;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.example.myapplication.services.MyService2;
public class MainActivity2 extends AppCompatActivity {
private Button btnStart;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
btnStart = findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(MainActivity2.this, MyService2.class);
startService(intent);
}
});
}
}
后续我会继续写的 么么叽么么叽么么哒!
|