Duy trì sự hiện diện của ứng dụng trên Wear

Stay organized with collections Save and categorize content based on your preferences.

Wear OS tự động xử lý việc chuyển sang chế độ tiết kiệm pin cho một ứng dụng đang hoạt động khi một người dùng không còn sử dụng đồng hồ nữa. Đây được gọi là chế độ môi trường xung quanh của hệ thống. Nếu người dùng tương tác lại với đồng hồ trong một khung thời gian nhất định, thiết bị Wear OS sẽ đưa người dùng quay lại ứng dụng nơi họ đã dừng lại.

Đối với các trường hợp sử dụng cụ thể, chẳng hạn như người dùng muốn xem nhịp tim và nhịp độ trong khi chạy, bạn cũng có thể kiểm soát nội dung hiển thị ở chế độ tiết kiệm pin (chế độ môi trường xung quanh). Các ứng dụng Wear OS chạy ở cả chế độ môi trường xung quanh lẫn chế độ tương tác được gọi là ứng dụng luôn bật.

Việc cho phép một ứng dụng liên tục xuất hiện sẽ ảnh hưởng đến thời lượng pin, vì vậy bạn hãy cân nhắc ảnh hưởng đó khi thêm tính năng này vào ứng dụng.

Định cấu hình dự án của bạn

Để hỗ trợ chế độ môi trường xung quanh, hãy làm theo các bước sau:

  1. Tạo hoặc cập nhật dự án của bạn dựa vào cấu hình trên trang Tạo và chạy ứng dụng cho thiết bị đeo.
  2. Thêm quyền WAKE_LOCK vào tệp kê khai Android:
<uses-permission android:name="android.permission.WAKE_LOCK" />

Chế độ môi trường xung quanh bằng lớp AmbientModeSupport

Để sử dụng lớp AmbientModeSupport, hãy làm như sau:

  1. Tạo một lớp con của FragmentActivity hoặc một trong các lớp con của nó.
  2. Triển khai giao diện AmbientCallbackProvider, như trong ví dụ sau. Ghi đè phương thức getAmbientCallback() để cung cấp các lệnh gọi lại cần thiết nhằm phản ứng với các sự kiện xung quanh từ hệ thống Android. Ở bước sau, bạn sẽ tạo lớp gọi lại tuỳ chỉnh.

    Kotlin

    class MainActivity : AppCompatActivity(), AmbientModeSupport.AmbientCallbackProvider {
        …
        override fun getAmbientCallback(): AmbientModeSupport.AmbientCallback = MyAmbientCallback()
        …
    }
    

    Java

    public class MainActivity extends AppCompatActivity implements AmbientModeSupport.AmbientCallbackProvider {
        …
        @Override
        public AmbientModeSupport.AmbientCallback getAmbientCallback() {
            return new MyAmbientCallback();
        }
        …
    }
    
  3. Trong phương thức onCreate(), hãy bật Chế độ môi trường xung quanh bằng cách gọi AmbientModeSupport.attach(FragmentActivity). Phương thức này trả về một AmbientModeSupport.AmbientController. Bộ điều khiển này cho phép bạn kiểm tra trạng thái môi trường xung quanh bên ngoài lệnh gọi lại. Bạn nên tham chiếu đến đối tượng AmbientModeSupport.AmbientController:

    Kotlin

    class MainActivity : AppCompatActivity(), AmbientModeSupport.AmbientCallbackProvider {
        ...
        /*
         * Declare an ambient mode controller, which will be used by
         * the activity to determine if the current mode is ambient.
         */
        private lateinit var ambientController: AmbientModeSupport.AmbientController
        ...
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            ...
            ambientController = AmbientModeSupport.attach(this)
        }
        ...
    }
    

    Java

    public class MainActivity extends AppCompatActivity implements AmbientModeSupport.AmbientCallbackProvider {
        ...
        /*
         * Declare an ambient mode controller, which will be used by
         * the activity to determine if the current mode is ambient.
         */
        private AmbientModeSupport.AmbientController ambientController;
        ...
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ...
            ambientController = AmbientModeSupport.attach(this);
        }
        ...
    }
    
  4. Tạo một lớp bên trong mở rộng lớp AmbientCallback để thao tác trên các sự kiện xung quanh. Lớp này sẽ trở thành đối tượng được trả về từ phương thức bạn đã tạo ở Bước 2:

    Kotlin

    private class MyAmbientCallback : AmbientModeSupport.AmbientCallback() {
    
        override fun onEnterAmbient(ambientDetails: Bundle?) {
          // Handle entering ambient mode
        }
    
        override fun onExitAmbient() {
          // Handle exiting ambient mode
        }
    
        override fun onUpdateAmbient() {
          // Update the content
        }
    }
    

    Java

    private class MyAmbientCallback extends AmbientModeSupport.AmbientCallback {
        @Override
        public void onEnterAmbient(Bundle ambientDetails) {
          // Handle entering ambient mode
        }
    
        @Override
        public void onExitAmbient() {
          // Handle exiting ambient mode
         }
    
        @Override
        public void onUpdateAmbient() {
          // Update the content
        }
    }
    

Xem lại mẫu AlwaysOnKotlin trên GitHub để biết thêm thông tin và các phương pháp hay nhất.

Chế độ môi trường xung quanh bằng lớp WearableActivity

Đối với các dự án mới hiện có, bạn có thể thêm tính năng hỗ trợ chế độ môi trường xung quanh vào ứng dụng Wear bằng cách cập nhật cấu hình dự án.

Tạo một hoạt động hỗ trợ chế độ môi trường xung quanh

Bạn có thể bật chế độ môi trường xung quanh trong hoạt động của mình bằng cách sử dụng lớp WearableActivity:

  1. Tạo một hoạt động mở rộng WearableActivity.
  2. Trong phương thức onCreate() của hoạt động, hãy gọi phương thức setAmbientEnabled().

Bật chế độ môi trường xung quanh trong hoạt động của bạn như sau:

Kotlin

class MainActivity : WearableActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setAmbientEnabled()
    ...
    }
}

Java

public class MainActivity extends WearableActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setAmbientEnabled();
        ...
    }

Xử lý quá trình chuyển đổi giữa các chế độ

Nếu người dùng không tương tác với ứng dụng của bạn trong một khoảng thời gian khi ứng dụng đang hiển thị, hoặc nếu màn hình bị che phủ, thì hệ thống sẽ chuyển hoạt động sang chế độ môi trường xung quanh.

Sau khi ứng dụng chuyển sang chế độ môi trường xung quanh, hãy cập nhật giao diện người dùng hoạt động lên một bố cục cơ bản hơn để giảm mức tiêu thụ điện năng. Sử dụng nền đen với văn bản và đồ hoạ màu trắng tối giản.

Để dễ dàng chuyển đổi từ chế độ tương tác sang chế độ môi trường xung quanh, hãy cố gắng duy trì vị trí tương tự của các mục trên màn hình.

Lưu ý: Ở chế độ môi trường xung quanh, hãy tắt mọi phần tử tương tác trên màn hình, chẳng hạn như các nút.

Khi hoạt động chuyển sang chế độ môi trường xung quanh, hệ thống sẽ gọi phương thức onEnterAmbient() của lệnh gọi lại xung quanh. Đoạn mã sau đây cho biết cách chuyển màu văn bản thành màu trắng và tắt tính năng khử răng cưa sau khi hệ thống chuyển sang chế độ môi trường xung quanh:

Kotlin

override fun onEnterAmbient(ambientDetails: Bundle?) {
    super.onEnterAmbient(ambientDetails)

    stateTextView.setTextColor(Color.WHITE)
    stateTextView.paint.isAntiAlias = false
}

Java

@Override
public void onEnterAmbient(Bundle ambientDetails) {
    super.onEnterAmbient(ambientDetails);

    stateTextView.setTextColor(Color.WHITE);
    stateTextView.getPaint().setAntiAlias(false);
}

Khi người dùng nhấn vào màn hình hoặc nhấc cổ tay, hoạt động sẽ chuyển từ chế độ môi trường xung quanh sang chế độ tương tác. Hệ thống sẽ gọi phương thức onExitAmbient(). Ghi đè phương thức này để cập nhật bố cục giao diện người dùng để ứng dụng hiển thị ở trạng thái tương tác đầy đủ màu sắc.

Đoạn mã sau đây cho biết cách thay đổi màu văn bản thành màu xanh lục và bật tính năng khử răng cưa khi hệ thống chuyển sang chế độ tương tác:

Kotlin

override fun onExitAmbient() {
    super.onExitAmbient()

    stateTextView.setTextColor(Color.GREEN)
    stateTextView.paint.isAntiAlias = true
}

Java

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

    stateTextView.setTextColor(Color.GREEN);
    stateTextView.getPaint().setAntiAlias(true);
}

Cập nhật nội dung ở chế độ môi trường xung quanh

Chế độ môi trường xung quanh cho phép bạn cập nhật thông tin mới cho người dùng trên màn hình, nhưng bạn phải lưu ý cân bằng các bản cập nhật màn hình với thời lượng pin. Bạn nên cân nhắc chỉ ghi đè phương thức onUpdateAmbient() để cập nhật màn hình mỗi phút một lần trở xuống ở chế độ môi trường xung quanh.

Để cập nhật nội dung ứng dụng, hãy ghi đè phương thức onUpdateAmbient() trong lệnh gọi lại xung quanh:

Kotlin

override fun onUpdateAmbient() {
    super.onUpdateAmbient()
    // Update the content
}

Java

@Override
public void onUpdateAmbient() {
    super.onUpdateAmbient();
    // Update the content
}

Mặc dù không nên, nhưng bạn vẫn có thể cập nhật ứng dụng Wear OS ở chế độ môi trường xung quanh thường xuyên hơn mỗi phút một lần. Đối với các ứng dụng yêu cầu cập nhật thường xuyên hơn, hãy sử dụng đối tượng AlarmManager để đánh thức bộ xử lý và cập nhật màn hình thường xuyên hơn.

Để triển khai một chuông báo cập nhật nội dung thường xuyên hơn ở chế độ môi trường xung quanh, hãy làm theo các bước sau:

  1. Chuẩn bị trình quản lý chuông báo
  2. Đặt tần suất cập nhật.
  3. Hãy kiểm tra xem thiết bị hiện có đang ở chế độ môi trường xung quanh hay không hoặc lên lịch cập nhật tiếp theo khi hoạt động chuyển sang chế độ môi trường xung quanh.
  4. Huỷ chuông báo khi hoạt động chuyển sang chế độ tương tác hoặc hoạt động bị dừng.

Lưu ý: Trình quản lý chuông báo có thể tạo các bản sao hoạt động mới khi hoạt động của bạn được kích hoạt. Để ngăn trường hợp này, hãy đảm bảo hoạt động của bạn được khai báo bằng tham số android:launchMode="singleInstance" trong tệp kê khai.

Phần sau đây sẽ mô tả chi tiết các bước này.

Chuẩn bị trình quản lý chuông báo

Trình quản lý chuông báo chạy PendingIntent để cập nhật màn hình và lên lịch cho chuông báo tiếp theo. Ví dụ sau đây cho biết cách khai báo trình quản lý chuông báo và ý định đang chờ xử lý trong phương thức onCreate() của hoạt động:

Kotlin

// Action for updating the display in ambient mode, per our custom refresh cycle.
private const val AMBIENT_UPDATE_ACTION = "com.your.package.action.AMBIENT_UPDATE"
...
private lateinit var ambientUpdateAlarmManager: AlarmManager
private lateinit var ambientUpdatePendingIntent: PendingIntent
private lateinit var ambientUpdateBroadcastReceiver: BroadcastReceiver

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setAmbientEnabled()

    ambientUpdateAlarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager

    ambientUpdatePendingIntent = Intent(AMBIENT_UPDATE_ACTION).let { ambientUpdateIntent ->
        PendingIntent.getBroadcast(this, 0, ambientUpdateIntent, PendingIntent.FLAG_UPDATE_CURRENT)
    }

    ambientUpdateBroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            refreshDisplayAndSetNextUpdate()
        }
    }
    ...
}

Java

// Action for updating the display in ambient mode, per our custom refresh cycle.
private static final String AMBIENT_UPDATE_ACTION = "com.your.package.action.AMBIENT_UPDATE";

private AlarmManager ambientUpdateAlarmManager;
private PendingIntent ambientUpdatePendingIntent;
private BroadcastReceiver ambientUpdateBroadcastReceiver;

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

    setAmbientEnabled();

    ambientUpdateAlarmManager =
        (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    Intent ambientUpdateIntent = new Intent(AMBIENT_UPDATE_ACTION);

    ambientUpdatePendingIntent = PendingIntent.getBroadcast(
        this, 0, ambientUpdateIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    ambientUpdateBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            refreshDisplayAndSetNextUpdate();
        }
    };
    ...
}

Đăng ký và huỷ đăng ký broadcast receiver bằng cách sử dụng onResume()onPause():

Kotlin

override fun onResume() {
    super.onResume()
    IntentFilter(AMBIENT_UPDATE_ACTION).also { filter ->
        registerReceiver(ambientUpdateBroadcastReceiver, filter)
    }
}

override fun onPause() {
    super.onPause()
    unregisterReceiver(ambientUpdateBroadcastReceiver)
    ambientUpdateAlarmManager.cancel(ambientUpdatePendingIntent)
}

Java

@Override
public void onResume() {
    super.onResume();
    IntentFilter filter = new IntentFilter(AMBIENT_UPDATE_ACTION);
    registerReceiver(ambientUpdateBroadcastReceiver, filter);
        ...
}

@Override
public void onPause() {
    super.onPause();
    unregisterReceiver(ambientUpdateBroadcastReceiver);
    ambientUpdateAlarmManager.cancel(ambientUpdatePendingIntent);
    ...
}
Cập nhật màn hình và lập lịch cập nhật dữ liệu

Trong hoạt động mẫu này, trình quản lý chuông báo sẽ kích hoạt 20 giây một lần ở chế độ môi trường xung quanh. Khi bộ hẹn giờ kêu tích tắc, chuông báo sẽ kích hoạt ý định cập nhật màn hình rồi đặt độ trễ cho lần cập nhật tiếp theo.

Ví dụ sau đây cho biết cách cập nhật thông tin trên màn hình và đặt chuông báo cho lần cập nhật tiếp theo:

Kotlin

// Milliseconds between waking processor/screen for updates
private val AMBIENT_INTERVAL_MS: Long = TimeUnit.SECONDS.toMillis(20)
...
private fun refreshDisplayAndSetNextUpdate() {
    if (isAmbient) {
        // Implement data retrieval and update the screen for ambient mode
    } else {
        // Implement data retrieval and update the screen for interactive mode
    }
    val timeMs: Long = System.currentTimeMillis()
    // Schedule a new alarm
    if (isAmbient) {
        // Calculate the next trigger time
        val delayMs: Long = AMBIENT_INTERVAL_MS - timeMs % AMBIENT_INTERVAL_MS
        val triggerTimeMs: Long = timeMs + delayMs
        ambientUpdateAlarmManager.setExact(
                AlarmManager.RTC_WAKEUP,
                triggerTimeMs,
                ambientUpdatePendingIntent)
    } else {
        // Calculate the next trigger time for interactive mode
    }
}

Java

// Milliseconds between waking processor/screen for updates
private static final long AMBIENT_INTERVAL_MS = TimeUnit.SECONDS.toMillis(20);
private void refreshDisplayAndSetNextUpdate() {
    if (isAmbient()) {
        // Implement data retrieval and update the screen for ambient mode
    } else {
        // Implement data retrieval and update the screen for interactive mode
    }
    long timeMs = System.currentTimeMillis();
    // Schedule a new alarm
    if (isAmbient()) {
        // Calculate the next trigger time
        long delayMs = AMBIENT_INTERVAL_MS - (timeMs % AMBIENT_INTERVAL_MS);
        long triggerTimeMs = timeMs + delayMs;
        ambientUpdateAlarmManager.setExact(
            AlarmManager.RTC_WAKEUP,
            triggerTimeMs,
            ambientUpdatePendingIntent);
    } else {
        // Calculate the next trigger time for interactive mode
    }
}
Lên lịch cho chuông báo tiếp theo

Lên lịch chuông báo để cập nhật màn hình bằng cách ghi đè phương thức onEnterAmbient()onUpdateAmbient(), như được hiển thị trong mã mẫu sau:

Kotlin

override fun onEnterAmbient(ambientDetails: Bundle?) {
    super.onEnterAmbient(ambientDetails)

    refreshDisplayAndSetNextUpdate()
}

override fun onUpdateAmbient() {
    super.onUpdateAmbient()
    refreshDisplayAndSetNextUpdate()
}

Java

@Override
public void onEnterAmbient(Bundle ambientDetails) {
    super.onEnterAmbient(ambientDetails);
    refreshDisplayAndSetNextUpdate();
}

@Override
public void onUpdateAmbient() {
    super.onUpdateAmbient();
    refreshDisplayAndSetNextUpdate();
}

Lưu ý: Trong ví dụ này, phương thức refreshDisplayAndSetNextUpdate() được gọi mỗi khi cần cập nhật màn hình. Để biết thêm ví dụ về thời điểm gọi phương thức này, hãy xem mẫu AlwaysOnKotlin trên GitHub.

Huỷ chuông báo

Khi thiết bị chuyển sang chế độ tương tác, hãy huỷ chuông báo trong phương thức onExitAmbient():

Kotlin

override fun onExitAmbient() {
    super.onExitAmbient()

    ambientUpdateAlarmManager.cancel(ambientUpdatePendingIntent)
}

Java

@Override
public void onExitAmbient() {
    super.onExitAmbient();
    ambientUpdateAlarmManager.cancel(ambientUpdatePendingIntent);
}

Khi người dùng thoát hoặc dừng hoạt động của bạn, hãy huỷ chuông báo trong phương thức onDestroy() của hoạt động:

Kotlin

override fun onDestroy() {
    ambientUpdateAlarmManager.cancel(ambientUpdatePendingIntent)
    super.onDestroy()
}

Java

@Override
public void onDestroy() {
    ambientUpdateAlarmManager.cancel(ambientUpdatePendingIntent);
    super.onDestroy();
}