1. 程式人生 > >Android鎖屏狀態下點亮螢幕並彈窗提醒

Android鎖屏狀態下點亮螢幕並彈窗提醒

類似於手機鎖屏狀態下QQ來訊息然後點亮螢幕並彈窗,如圖。
這裡寫圖片描述
相信QQ的這個功能大家都是很熟悉的了,下面就開始講具體的實現步驟。

一、新建一個Activity並在OnCreate中新增四個標識

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_alarm_handler);
        final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); //下面就是根據自己的跟你需求來寫,跟寫一個Activity一樣的 //拿到傳過來的資料 String msg = getIntent().getStringExtra
("msg"); textview = (TextView) findViewById(R.id.textview); textview.setText("收到訊息:" + msg); }

四個標識的意思分別是:

  1. 鎖屏狀態下顯示
  2. 解鎖
  3. 保持螢幕常量
  4. 開啟螢幕

然後在AndroidManifest.xml中對該Activity加上如下屬性。

        <activity
            android:name=".AlarmHandlerActivity"
            android:excludeFromRecents
="true" android:launchMode="singleInstance" android:taskAffinity="" android:theme="@android:style/Theme.Wallpaper.NoTitleBar" />

Android:excludeFromRecents控制在不在recent列表中顯示。true時不顯示;false顯示,預設。

這個Activity其實就是我們需要的彈窗,類似於上圖中的彈出的QQ訊息,只不過是把Acitivity設定為不顯示標題以及背景設定為螢幕桌面桌布或者設定成透明的都行,然後中間的View就自己按需要來寫。把Activity的背景設定為螢幕桌面桌布只需要在AndroidManifest.xml中對應的Activity的標籤下的theme屬性設定為@android:style/Theme.Wallpaper.NoTitleBar就可以。
注意,設定了上面這個theme屬性後,這個Activity要繼承Activity,繼承AppCompatActivity會報錯。

二、新建一個廣播,並在廣播中啟動彈窗Activity

重寫onReceiver方法,並在方法中寫上如下語句。收到需要的廣播就類似於QQ收到新訊息,然後判斷是否需要彈出。

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive: 收到廣播");
        Log.d(TAG, intent.getAction());
        //拿到傳來過來資料
        String msg = intent.getStringExtra("msg");
        //拿到鎖屏管理者
        KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
        if (km.isKeyguardLocked()) {   //為true就是鎖屏狀態下
            //啟動Activity
            Intent alarmIntent = new Intent(context, AlarmHandlerActivity.class);
            //攜帶資料
            alarmIntent.putExtra("msg", msg);
            //activity需要新的任務棧
            alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(alarmIntent);
        }
    }

在廣播中啟動Activity的context可能不是Activity物件,所以需要新增NEW_TASK的標誌,否則啟動時可能會報錯

別忘了在AndroidManifest.xml中宣告receiver,並新增過濾器,用來過濾廣播,這接受我們需要的。

        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="1000">
                <action android:name="com.fu" />
            </intent-filter>
        </receiver>

三、新增許可權

在AndroidManifest.xml中新增許可權。

<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>  
<uses-permission android:name="android.permission.WAKE_LOCK"/>  

其實以上的差不多就已經實現了我們需要的功能。下面為了方便測試,演示下過,加的其他的步驟。

四、模擬演示

1.新建一個Service,並在裡面實現延遲傳送廣播

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate: ");
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent();
                intent.setAction("com.fu");
                intent.putExtra("msg", "新訊息1");
                MyService.this.sendBroadcast(intent);
                Log.d(TAG, "第一次傳送廣播");
            }
        }, 10000);
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent();
                intent.setAction("com.fu");
                intent.putExtra("msg", "新訊息2");
                MyService.this.sendBroadcast(intent);
                Log.d(TAG, "第二次傳送廣播");
            }
        }, 20000);
    }

上面程式碼是在service中的onCreate中,延遲10傳送一次廣播,延遲20秒又傳送了一次廣播,目的是為了讓手機出於鎖屏介面下收到廣播,然後點亮螢幕彈出提示窗。
別忘了在AndroidManifest.xml中宣告service

        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true" />

2.開啟service

    intent = new Intent(MainActivity.this, MyService.class);
    startService(intent);

3.鎖屏等待亮屏彈窗

這是鎖屏介面下的截圖
這裡寫圖片描述 這裡寫圖片描述

五、補充說明

如果彈窗的Activity沒有被銷燬,也就是說,第一次亮屏有彈窗,但我們沒有去關閉它,而是又按下了鎖屏鍵,這時第二次來訊息的時候,就會呼叫onNewIntent()方法,那我們就重寫onNewIntent()方法。

    /**
     * 這個方法是當這個activity沒有銷燬的時候,人為的按下鎖屏鍵,然後再啟動這個Activity的時候會去呼叫
     *
     * @param intent
     */
    @Override
    protected void onNewIntent(Intent intent) {
        Log.i(TAG, "onNewIntent: 呼叫");
        PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
        if (!pm.isScreenOn()) {
            String msg = intent.getStringExtra("msg");
            textview.setText("又收到訊息:" + msg);
            //點亮螢幕
            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP |
                    PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");
            wl.acquire();
            wl.release();
        }
    }
  • 彈窗activity的佈局檔案
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.fu.notifydemo.AlarmHandlerActivity">

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@android:color/white"
        android:text="收到訊息:"
        android:textColor="@android:color/holo_red_dark"
        android:textSize="25sp" />

</RelativeLayout>

以上就是本人對鎖屏狀態下點亮螢幕並彈窗提醒一些初步理解,如有錯誤的地方,還望指正。

參考文獻: