1、在android O版本之後,橫幅彈出需要創建channelId,設置給notification,定義的channelId賦值必須是數字字符串,否則橫幅彈出失敗,:
如下代碼實現:
1、應用切後臺後彈出橫幅,點擊橫幅後打開應用並彈出dialog,提示用戶授權懸浮窗權限
2、如果用戶點擊前往設置,則進入設置,如果授權成功,返回應用後則彈框消失,否則彈框繼續存在
3、在懸浮窗授權界面不彈出橫幅通知
4、在彈出dialog後,選擇取消,再次切後臺後繼續走1-3流程。
private static final String TAG = "MainActivity";
private static final int RELEASE_LOCK_DELAY_TIME = 1000;
private static final int NOTIFICATION_ID = 1;
private static final String EXTRA_FROM_NOTIFICATION = "from_notification";
private TextView mScreenOnTxt;
private PowerManager.WakeLock mWakeLock;
private boolean mIsClickToGainOverlayPermission = false;
// channelId必須是數字
private String channelId = "1";
private NotificationManager notificationManager;
private AlertDialog mAlertDialog;
// 如果第一次啓動界面,從首次置後臺後再返回時彈出dialog
// 提示用戶,切後臺後需要懸浮窗權限
private int isFirstCreateAndBackground = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
setContentView(R.layout.activity_main);
mScreenOnTxt = findViewById(R.id.screen_on_txt);
registerScreenOnReceiver();
createChannelId();
isFirstCreateAndBackground = 0;
}
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "action = " + intent.getAction());
if (Intent.ACTION_SCREEN_ON.equalsIgnoreCase(intent.getAction())) {
Log.d(TAG, "screen on.");
} else if (Intent.ACTION_SCREEN_OFF.equalsIgnoreCase(intent.getAction())) {
Log.d(TAG, "screen off");
mScreenOnTxt.setText("screen off");
/* 如果滅屏後,點亮屏幕 */
wakeUpScreen();
}
}
};
private void registerScreenOnReceiver() {
// 註冊監聽屏幕亮滅屏動作
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mBroadcastReceiver, filter);
}
private void wakeUpScreen() {
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (mWakeLock == null) {
// 強制亮屏,並且弱光點亮屏幕
mWakeLock = powerManager.newWakeLock(
PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK,
"MainActivity:wakeup");
}
// 點亮屏幕,如果屏幕亮屏,則不需要點亮屏幕
if (powerManager.isScreenOn()) {
return;
}
if (mWakeLock.isHeld()) {
mWakeLock.release();
}
mWakeLock.acquire(RELEASE_LOCK_DELAY_TIME);
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
Intent intent = getIntent();
Log.d(TAG, "onResume intent = " + intent);
// 收到的intent中,是否從點擊notification過來的
boolean backFromClickNotification = false;
if (intent != null && intent.hasExtra(EXTRA_FROM_NOTIFICATION)) {
backFromClickNotification =
intent.getBooleanExtra(EXTRA_FROM_NOTIFICATION, false);
}
Log.d(TAG, "from notification extra value = " + backFromClickNotification +
"isFirstCreateAndBackground=" + isFirstCreateAndBackground);
if (isFirstCreateAndBackground == 1 || backFromClickNotification) {
displayDialogToNotifyUserToGainOverlayPermission();
}
cancelNotification();
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop");
checkOverlayPermissionBeforeBackground();
isFirstCreateAndBackground = 1;
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
unregisterReceiver(mBroadcastReceiver);
mWakeLock= null;
}
private void checkOverlayPermissionBeforeBackground() {
if (mIsClickToGainOverlayPermission) {
return;
}
if (!Settings.canDrawOverlays(this)) {
Log.d(TAG, "need overlay permissions.");
displayNotificationForOverlay();
} else {
Log.d(TAG, "has overlay permissions.");
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, "onNewIntent, intent = " + intent);
setIntent(intent);
}
private void createChannelId() {
String channelName = "MainActivity";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, channelName,
NotificationManager.IMPORTANCE_MAX);
notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
private void displayNotificationForOverlay() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId);
builder.setContentTitle("電話通知");
builder.setContentText("設置後臺需要懸浮窗權限");
builder.setSmallIcon(R.drawable.ic_launcher_background);
builder.setAutoCancel(true);
builder.setChannelId(channelId);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(EXTRA_FROM_NOTIFICATION, true);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pi = PendingIntent.getActivity(MainActivity.this,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pi);
Notification notification = builder.build();
notificationManager.notify(NOTIFICATION_ID, notification);
}
private void cancelNotification() {
if (notificationManager != null) {
Log.d(TAG, "cancelNotification, cancel.");
notificationManager.cancel(NOTIFICATION_ID);
}
}
private void displayDialogToNotifyUserToGainOverlayPermission() {
if (Settings.canDrawOverlays(this)) {
return;
}
if (mAlertDialog != null) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("需要使用懸浮窗權限");
builder.setPositiveButton("前往設置", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "click dialog goto gain overlay permissions.");
mAlertDialog.dismiss();
mAlertDialog = null;
mIsClickToGainOverlayPermission = true;
gotoGainOverlayPermission();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "取消授權", Toast.LENGTH_SHORT).show();
mAlertDialog = null;
}
});
builder.setCancelable(true);
mAlertDialog = builder.create();
mAlertDialog.show();
mIsClickToGainOverlayPermission = false;
}
private void gotoGainOverlayPermission() {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.d(TAG, "gotoGainOverlayPermission activity not founded");
}
}
return;
}