欢迎光临
我们一直在努力

Android Service - Service 生命周期变化、Service 与 Activity 双向交互

Service 生命周期变化

1、Service
  • BindAndUnbindLifecycleService.java

public class BindAndUnbindLifecycleService extends Service {

public static final String TAG = BindAndUnbindLifecycleService.class.getSimpleName();

private IBinder LocalBinder = new BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder();

public class BindAndUnbindLifecycleServiceBinder extends Binder {
public BindAndUnbindLifecycleService getService() {
return BindAndUnbindLifecycleService.this;
}
}

@Override
public void onCreate() {
super.onCreate();

Log.i(TAG, "onCreate");
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");

return LocalBinder;
}

@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind");

return super.onUnbind(intent);
}

@Override
public void onDestroy() {
super.onDestroy();

Log.i(TAG, "onDestroy");
}
}

  • AndroidManifest.xml

<service android:name=".myservice.BindAndUnbindLifecycleService" />

2、Activity Layout
  • activity_bind_and_unbind_service_test1.xml
  • <?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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".BindAndUnbindServiceTest1Activity">

    <Button
    android:id="@+id/btn_bind"
    android:layout_width="wrap_content"
    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/btn_unbind"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="解绑服务"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_bind" />

    <Button
    android:id="@+id/btn_go"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="跳转"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

  • activity_bind_and_unbind_service_test2.xml
  • <?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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".BindAndUnbindServiceTest2Activity">

    <Button
    android:id="@+id/btn_bind"
    android:layout_width="wrap_content"
    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/btn_unbind"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="解绑服务"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_bind" />

    <Button
    android:id="@+id/btn_back"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="回退"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    3、Activity Code
  • BindAndUnbindServiceTest1Activity.java
  • public class BindAndUnbindServiceTest1Activity extends AppCompatActivity {

    public static final String TAG = BindAndUnbindServiceTest1Activity.class.getSimpleName();

    private Button btnBind;
    private Button btnUnbind;
    private Button btnGo;

    private BindAndUnbindLifecycleService bindAndUnbindLifecycleService;

    private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    Log.i(TAG, "onServiceConnected");

    BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder bindAndUnbindLifecycleServiceBinder = (BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder) service;
    BindAndUnbindLifecycleService bindAndUnbindLifecycleService = bindAndUnbindLifecycleServiceBinder.getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    Log.i(TAG, "onServiceDisconnected");
    }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    EdgeToEdge.enable(this);
    setContentView(R.layout.activity_bind_and_unbind_service_test1);
    ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
    Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
    v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
    return insets;
    });

    btnBind = findViewById(R.id.btn_bind);
    btnUnbind = findViewById(R.id.btn_unbind);
    btnGo = findViewById(R.id.btn_go);

    btnBind.setOnClickListener(v -> {
    bindService(new Intent(this, BindAndUnbindLifecycleService.class), serviceConnection, Context.BIND_AUTO_CREATE);
    });

    btnUnbind.setOnClickListener(v -> {
    unbindService(serviceConnection);
    });

    btnGo.setOnClickListener(v -> {
    startActivity(new Intent(this, BindAndUnbindServiceTest2Activity.class));
    });
    }
    }

  • BindAndUnbindServiceTest2Activity.java
  • public class BindAndUnbindServiceTest2Activity extends AppCompatActivity {

    public static final String TAG = BindAndUnbindServiceTest2Activity.class.getSimpleName();

    private Button btnBind;
    private Button btnUnbind;
    private Button btnBack;

    private BindAndUnbindLifecycleService bindAndUnbindLifecycleService;

    private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    Log.i(TAG, "onServiceConnected");

    BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder bindAndUnbindLifecycleServiceBinder = (BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder) service;
    BindAndUnbindLifecycleService bindAndUnbindLifecycleService = bindAndUnbindLifecycleServiceBinder.getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    Log.i(TAG, "onServiceDisconnected");
    }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    EdgeToEdge.enable(this);
    setContentView(R.layout.activity_bind_and_unbind_service_test2);
    ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
    Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
    v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
    return insets;
    });

    btnBind = findViewById(R.id.btn_bind);
    btnUnbind = findViewById(R.id.btn_unbind);
    btnBack = findViewById(R.id.btn_back);

    btnBind.setOnClickListener(v -> {
    bindService(new Intent(this, BindAndUnbindLifecycleService.class), serviceConnection, Context.BIND_AUTO_CREATE);
    });

    btnUnbind.setOnClickListener(v -> {
    unbindService(serviceConnection);
    });

    btnBack.setOnClickListener(v -> {
    finish();
    });
    }
    }

    4、Test
  • 在 BindAndUnbindServiceTest1Activity 中,点击【绑定服务】按钮,输出结果
  • onCreate
    onBind
    onServiceConnected

  • 在 BindAndUnbindServiceTest1Activity 中,点击【跳转】按钮,跳转到 BindAndUnbindServiceTest2Activity

  • 在 BindAndUnbindServiceTest2Activity 中,点击【绑定服务】按钮,输出结果

  • onServiceConnected

  • 在 BindAndUnbindServiceTest2Activity 中,点击【解绑服务】按钮,输出结果
  • 无内容输出

  • 在 BindAndUnbindServiceTest2Activity 中,点击【回退】按钮,回退到 BindAndUnbindServiceTest1Activity

  • 在 BindAndUnbindServiceTest1Activity 中,点击【解绑服务】按钮,输出结果

  • onUnbind
    onDestroy


    Service 与 Activity 双向交互

    1、演示
    (1)Service
    • ServiceCallback.java

    public interface ServiceCallback {
    void onTaskComplete(int result);
    }

    • CommunicateService.java

    public class CommunicateService extends Service {
    private final IBinder binder = new CommunicateServiceBinder();
    private ServiceCallback serviceCallback;
    private final Handler handler = new Handler(Looper.getMainLooper());

    public class CommunicateServiceBinder extends Binder {
    public CommunicateService getService() {
    return CommunicateService.this;
    }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
    return binder;
    }

    // 注册回调
    public void setCallback(ServiceCallback serviceCallback) {
    this.serviceCallback = serviceCallback;
    }

    public void startLongTask() {
    new Thread(() -> {

    // 模拟耗时操作
    try {
    Thread.sleep(3000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }

    // 发送数据
    int result = 100;
    if (serviceCallback != null) {
    handler.post(() -> serviceCallback.onTaskComplete(result));
    }
    }).start();
    }
    }

    • AndroidManifest.xml

    <service android:name=".myservice.CommunicateService" />

    (2)Activity
    • activity_communicate_service_test.xml

    <?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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CommunicateServiceTestActivity">

    <TextView
    android:id="@+id/tv_test_content"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text=""
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

    <Button
    android:id="@+id/btn_execute_task"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="执行任务"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    • CommunicateServiceTestActivity.java

    public class CommunicateServiceTestActivity extends AppCompatActivity {

    public static final String TAG = CommunicateServiceTestActivity.class.getSimpleName();

    private TextView tvTestContent;

    private CommunicateService communicateService;
    private boolean isBound = false;
    private final ServiceCallback serviceCallback = result -> {
    tvTestContent.setText(String.valueOf(result));
    };
    private final ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    Log.i(TAG, "onServiceConnected");

    communicateService = ((CommunicateService.CommunicateServiceBinder) service).getService();
    isBound = true;

    communicateService.setCallback(serviceCallback);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    Log.i(TAG, "onServiceDisconnected");

    isBound = false;
    }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    EdgeToEdge.enable(this);
    setContentView(R.layout.activity_communicate_service_test);
    ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
    Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
    v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
    return insets;
    });

    tvTestContent = findViewById(R.id.tv_test_content);
    findViewById(R.id.btn_execute_task).setOnClickListener(v -> {
    if (communicateService != null) {
    communicateService.startLongTask();
    }
    });
    }

    @Override
    protected void onStart() {
    super.onStart();

    Intent intent = new Intent(this, CommunicateService.class);
    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
    super.onStop();

    if (isBound) {
    if (communicateService != null) {
    communicateService.setCallback(null);
    }
    unbindService(serviceConnection);
    isBound = false;
    }
    }
    }

    2、小结
    方向方式关键代码
    Activity → Service 直接调用 Service 方法 communicateService.startLongTask()
    Service → Activity 通过回调接口 serviceCallback.onTaskComplete(result)
    赞(0)
    未经允许不得转载:171主机测评 » Android Service - Service 生命周期变化、Service 与 Activity 双向交互
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址