那么这篇文档主要介绍了在一个APP中,打开另一个APP的服务,和绑定另一个APP的服务。
首先给出第一个app的代码:
MainActivity.java的代码,这是被动的APP所以里面是空的。
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
AppService.java代码:
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
public class AppService extends Service {
public AppService() {
}
@Override
public IBinder onBind(Intent intent) {
return new IAppServiceRemoteBinder.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void setData(String data) throws RemoteException {
AppService.this.data = data;
}
};
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("Service Started");
new Thread(){
@Override
public void run() {
super.run();
running = true;
while (running){
System.out.println(data);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
@Override
public void onDestroy() {
super.onDestroy();
running = false;
System.out.println("Service Destroy");
}
private String data = "默认数据";
private boolean running = false;
}
这里的onBind方法需要返回一个Binder对象,那么这里采用的aidl方法,首先你要创建一个aidl接口,接口代码如下:
interface IAppServiceRemoteBinder {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
void setData(String data);
}
这个接口中声明了一个方法setData,所以Binder一定要实现这个方法。以上是app的代码。
anotherapp代码如下:
首先给出MainActivity的代码:
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.widget.EditText;
import com.example.startservicefromanotherapp.IAppServiceRemoteBinder;
public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {
private Intent serviceIntent;
private EditText etInput;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etInput = findViewById(R.id.etInput);
serviceIntent = new Intent();
serviceIntent.setComponent(new ComponentName("com.example.startservicefromanotherapp",
"com.example.startservicefromanotherapp.AppService"));
findViewById(R.id.btnStartAppService).setOnClickListener(this);
findViewById(R.id.btnStopAppService).setOnClickListener(this);
findViewById(R.id.btnBindAppService).setOnClickListener(this);
findViewById(R.id.btnUnbindAppService).setOnClickListener(this);
findViewById(R.id.btnSync).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnStartAppService:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
} else {
startService(serviceIntent);
}
break;
case R.id.btnStopAppService:
stopService(serviceIntent);
break;
case R.id.btnBindAppService:
bindService(serviceIntent,this, Context.BIND_AUTO_CREATE);
break;
case R.id.btnUnbindAppService:
unbindService(this);
binder = null;
break;
case R.id.btnSync:
if(binder != null){
try {
binder.setData(etInput.getText().toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("Bind Service");
System.out.println(service);
binder = IAppServiceRemoteBinder.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
private IAppServiceRemoteBinder binder = null;
}
这个activity中有五个按钮分别控制:打开app的service、关闭app的service、绑定app的service、解除绑定app的service、更新service中的data数据。该类中,onServiceConnected方法主要作用是在绑定时,获取到AppServcie传来的IBinder,并把获取到的binder用于btnSync按钮更改data的值,从而完成信息的交互。
对应的activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnStartAppService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="启动外部服务" />
<Button
android:id="@+id/btnStopAppService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="停止外部服务" />
<Button
android:id="@+id/btnBindAppService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定外部服务" />
<Button
android:id="@+id/btnUnbindAppService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="借出绑定外部服务" />
<EditText
android:id="@+id/etInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="这是另一个应用中的数据" />
<Button
android:id="@+id/btnSync"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="同步数据到绑定的服务中" />
</LinearLayout>