Android 10 (Q) 問題解決記錄

前言

最近在使用Pixel3測試時在Android10的系統上遇到一些疑難問題, 在此跟你們分享一下java

1. Android 10 (Q)沒法接收UDP廣播包的問題

在Android10上, App默認是沒有接收UDP廣播包的權限的, 致使一些搜索功能不可用, 具體的解決方案 須要申請MulticastLock才能夠接收廣播包, 代碼以下:android

//獲取
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
//須要在AndroidManifest申請 CHANGE_WIFI_MULTICAST_STATE 權限, 該權限爲非敏感權限, 不用動態申請
multiCastLock = wifiManager.createMulticastLock("nulticase_lock");

//請求Lock, 注意運行時只能請求一個, 反覆申請會報錯, 獲取以後就能接收廣播了
multiCastLock.acquire();

//再也不接收廣播的時候須要釋放lock
multiCastLock.release();
複製代碼

2. Android 10 (Q) App在後臺沒法觸發振動

當手機處於後臺時, 調用振動的代碼無效, 調用的代碼爲:bash

Vibrator mVibrator = (Vibrator) App.getInstance().getSystemService(Context.VIBRATOR_SERVICE);
long[] pattern = {100, 1000, 100, 1000};
mVibrator.vibrate(pattern, 2);
複製代碼

此時看logcat上的打印爲:測試

E/VibratorService: Ignoring incoming vibration as process with uid = 10323 is background, usage = USAGE_UNKNOWNui

在工程全局搜索可找到以下源碼:this

//package com.android.server;
//VibratorService.java
//只摘取了部分源碼

Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg, reason);
if (mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
  > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
    && !vib.isNotification() && !vib.isRingtone() && !vib.isAlarm()) {
        Slog.e(TAG, "Ignoring incoming vibration as process with"
         + " uid = " + uid + " is background,"
         + " usage = " + AudioAttributes.usageToString(vib.usageHint));
    return;
}

public boolean isNotification() {
    return VibratorService.this.isNotification(usageHint);
}
    
public boolean isRingtone() {
    return VibratorService.this.isRingtone(usageHint);
}

public boolean isAlarm() {
    return VibratorService.this.isAlarm(usageHint);
}

public boolean isAlarm() {
    return VibratorService.this.isAlarm(usageHint);
}
    
private static boolean isNotification(int usageHint) {
    switch (usageHint) {
        case AudioAttributes.USAGE_NOTIFICATION:
        case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
        case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
        case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
            return true;
        default:
            return false;
    }
}

private static boolean isRingtone(int usageHint) {
    return usageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
}

private static boolean isAlarm(int usageHint) {
    return usageHint == AudioAttributes.USAGE_ALARM;
}

複製代碼

由源碼可知, 當App處於後臺時且AudioAttributes不是Notification、Ringtone或者Alarm時, 請求振動的操做會被拒絕, 首先App在後臺, 因此mProcStatesCache.get() 這個判斷必然爲ture, 那處理方案須要從usageHint來解決spa

經過查看mVibrator.vibrate()的參數會發現, 有一個構造方法爲日誌

public void vibrate(long[] pattern, int repeat, AudioAttributes attributes)code

正好能夠傳入一個AudioAttributes, 故該問題解決方案以下:server

Vibrator mVibrator = (Vibrator) App.getInstance().getSystemService(Context.VIBRATOR_SERVICE);
long[] pattern = {100, 1000, 100, 1000};
AudioAttributes audioAttributes = new AudioAttributes.Builder()
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .setUsage(AudioAttributes.USAGE_ALARM) // 源碼中isAlarm判斷可經過
                    .build();
mVibrator.vibrate(pattern, 2);
複製代碼

3. Android 10 (Q) 彈出通知欄, 振動無效

在Android 10上, 經過NotificationManager.notify()彈出一個通知欄, 雖然設置了振動, 可是沒有效果, 查看Logcat有如下打印

E/VibratorService: Ignoring incoming vibration as process with uid = 10323 is background, usage = USAGE_UNKNOWN

如出一轍的錯誤日誌, 由此可知在設置振動時, 沒有設置AudioAttributes,解決方法在設置AudioAttributes時將其設置爲Alarm便可,代碼以下:

//AudioAttributes須要經過setSound來設置

//建立默認鈴聲, 也能夠設置自定義鈴聲
Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID,
                CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
        notificationChannel.enableVibration(true); //啓用振動
        AudioAttributes audioAttributes = new AudioAttributes.Builder()
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                .setUsage(AudioAttributes.USAGE_ALARM) //關鍵的一行, 設置AudioAttributes爲Alarm
                .build();
        notificationChannel.setSound(uri, audioAttributes);
        notifyManager.createNotificationChannel(notificationChannel);

複製代碼

結語

以上是我在適配中的總結,但願對你們的適配有所幫助,如有錯誤,敬請斧正。

相關文章
相關標籤/搜索