Service(服务)是一个后台运行的组件,执行长时间运行且不需要用户交互的任务。即使应用被销毁也依然可以工作。 服务的两种启动状态
状态 | 描述 |
---|---|
Started | Android的应用程序组件,如活动,通过startService()启动了服务,则服务是Started状态。一旦启动,服务可以在后台无限期运行,即使启动它的组件已经被销毁。 |
Bound | 当Android的应用程序组件通过bindService()绑定了服务,则服务是Bound状态。Bound状态的服务提供了一个客户服务器接口来允许组件与服务进行交互,如发送请求,获取结果,甚至通过IPC来进行跨进程通信。 |
要创建服务,需要创建一个继承自Service基类或者它的已知子类的Java类。
Service基类定义了不同的回调方法和多数重要方法。你不需要实现所有的回调方法。
回调 | 描述 |
---|---|
onStartCommand() | 其他组件(如活动)通过调用startService()来请求启动服务时,系统调用该方法。如果你实现该方法,你有责任在工作完成时通过stopSelf()或者stopService()方法来停止服务。 |
onBind() | 当其他组件想要通过bindService()来绑定服务时,系统调用该方法。如果你实现该方法,你需要返回IBinder对象来提供一个接口,以便客户来与服务通信。你必须实现该方法,如果你不允许绑定,则直接返回null。 |
onUnbind() | 当客户中断所有服务发布的特殊接口时,系统调用该方法。 |
onRebind() | 当新的客户端与服务连接,且此前它已经通过onUnbind(Intent)通知断开连接时,系统调用该方法。 |
onCreate() | 当服务通过onStartCommand()和onBind()被第一次创建的时候,系统调用该方法。该调用要求执行一次性安装。 |
onDestroy() | 当服务不再有用或者被销毁时,系统调用该方法。你的服务需要实现该方法来清理任何资源,如线程,已注册的监听器,接收器等。 |
修改AndroidManifest.xml
文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.user.service">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService" />
</application>
</manifest>
添加<service android:name=".MyService" />
这句话.
增加MyService.java代码:
package com.example.user.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "服务已经启动", Toast.LENGTH_LONG).show();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "服务已经停止", Toast.LENGTH_LONG).show();
}
}
修改MainActivity.java代码:
package com.example.user.service;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Method to start the service
public void startService(View view) {
startService(new Intent(getBaseContext(), MyService.class));
}
// Method to stop the service
public void stopService(View view) {
stopService(new Intent(getBaseContext(), MyService.class));
}
}
修改activity_main.xml
文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="137dp"
android:layout_marginTop="57dp"
android:layout_marginEnd="159dp"
android:layout_marginBottom="253dp"
android:onClick="startService"
android:text="启动服务"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="137dp"
android:layout_marginTop="105dp"
android:layout_marginEnd="159dp"
android:layout_marginBottom="57dp"
android:onClick="stopService"
android:text="停止服务"
app:layout_constraintBottom_toTopOf="@+id/button2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
运行效果:
修改AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.user.service">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
创建MyService.java:
package com.example.user.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
private MyBinder binder = new MyBinder();
private int count = 0;
public class MyBinder extends Binder
{
public int getCount()
{
return count;
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.d("test","Service onBinder.");
return binder;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("test","Service onCreate.");
count++;
}
@Override
public boolean onUnbind(Intent intent){
Log.d("test","Service onUnbind");
return true;
}
@Override
public void onDestroy(){
super.onDestroy();
Log.d("test","Service onDestroy");
}
}
修改MainActivity.java:
package com.example.user.service;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Button b1,b2,getCon;
MyService.MyBinder binder;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("test","--service connect--");
binder = (MyService.MyBinder)service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("test","--service disconnect--");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b1 = (Button) findViewById(R.id.button1);
b2 = (Button) findViewById(R.id.button2);
getCon = (Button) findViewById(R.id.button3);
final Intent intent = new Intent(this, MyService.class);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(intent, conn, Service.BIND_AUTO_CREATE);
}
});
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
unbindService(conn);
}
});
getCon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,
"count:"+binder.getCount(),Toast.LENGTH_SHORT).show();
}
});
}
}
修改activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="148dp"
android:layout_marginTop="77dp"
android:layout_marginEnd="148dp"
android:layout_marginBottom="95dp"
android:text="start"
app:layout_constraintBottom_toTopOf="@+id/button2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="148dp"
android:layout_marginTop="95dp"
android:layout_marginEnd="148dp"
android:layout_marginBottom="243dp"
android:text="stop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button1" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="148dp"
android:layout_marginTop="78dp"
android:layout_marginEnd="148dp"
android:layout_marginBottom="85dp"
android:text="GetStatus"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2" />
</android.support.constraint.ConstraintLayout>
执行结果:
2020-06-28 16:36:15.052 8758-8758/com.example.user.service D/test: Service onCreate.
2020-06-28 16:36:15.054 8758-8758/com.example.user.service D/test: Service onBinder.
2020-06-28 16:36:15.056 8758-8758/com.example.user.service D/test: --service connect--
2020-06-28 16:36:40.249 8758-8780/com.example.user.service D/EGL_emulation: eglMakeCurrent: 0xebc57240: ver 2 0 (tinfo 0xebc036c0)
2020-06-28 16:36:40.257 8758-8780/com.example.user.service D/EGL_emulation: eglMakeCurrent: 0xebc57240: ver 2 0 (tinfo 0xebc036c0)
2020-06-28 16:37:27.518 8758-8758/com.example.user.service D/test: Service onUnbind
2020-06-28 16:37:27.518 8758-8758/com.example.user.service D/test: Service onDestroy