Android仿微信QQ等實現鎖屏消息提醒


demo代碼如下:

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import com.demo.lockscreenmsgdemo.MyService;
import com.demo.lockscreenmsgdemo.R;

/**
 * 仿qq,微信,支付寶鎖屏消息
 * 使用步驟,點擊這個按鈕以后,按返回鍵退出APP,關閉手機屏幕,5s以后會受到鎖屏消息,可以點擊進入消息詳情頁面
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.start_service_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                startService(intent); //啟動后台服務
            }
        });
    }
}
import android.app.KeyguardManager;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import com.demo.lockscreenmsgdemo.R;

/**
 * 鎖屏消息內容的activity
 */
public class MessageActivity extends AppCompatActivity {

    private Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("tag", "onCreate:啟動了消息內容的activity ");
        //四個標志位顧名思義,分別是鎖屏狀態下顯示,解鎖,保持屏幕長亮,打開屏幕。這樣當Activity啟動的時候,它會解鎖並亮屏顯示。
        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); //打開屏幕
        //使用手機的背景
        Drawable wallPaper = WallpaperManager.getInstance(this).getDrawable();
        win.setBackgroundDrawable(wallPaper);
        setContentView(R.layout.activity_message);

        mContext = this;
        initView();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        //獲取電源管理器對象
//        PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
//        if (!pm.isScreenOn()) {
//            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP |
//                    PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");
//            wl.acquire();  //點亮屏幕
//            wl.release();  //任務結束后釋放
//        }
    }

    private void initView() {
        findViewById(R.id.message_layout).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //先解鎖系統自帶鎖屏服務,放在鎖屏界面里面
                KeyguardManager keyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
                keyguardManager.newKeyguardLock("").disableKeyguard(); //解鎖
                //點擊進入消息對應的頁面
                mContext.startActivity(new Intent(mContext, DetailsActivity.class));
                finish();
            }
        });

        findViewById(R.id.close_iv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
    }
}
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.demo.lockscreenmsgdemo.R;

public class DetailsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_details);
    }
}
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;

import com.demo.lockscreenmsgdemo.activity.MessageActivity;

/**
 * 監聽鎖屏消息的廣播接收器
 */
public class LockScreenMsgReceiver extends BroadcastReceiver {
    private static final String TAG = "LockScreenMsgReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG, "onReceive:收到了鎖屏消息 ");
        String action = intent.getAction();
        if (action.equals("com.zx.lockscreenmsgdemo.LockScreenMsgReceiver")) {
            //管理鎖屏的一個服務
            KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
            String text = km.inKeyguardRestrictedInputMode() ? "鎖屏了" : "屏幕亮着的";
            Log.i(TAG, "text: " + text);
            if (km.inKeyguardRestrictedInputMode()) {
                Log.i(TAG, "onReceive:鎖屏了 ");
                //判斷是否鎖屏
                Intent alarmIntent = new Intent(context, MessageActivity.class);
                //在廣播中啟動Activity的context可能不是Activity對象,所以需要添加NEW_TASK的標志,否則啟動時可能會報錯。
                alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                if(Build.VERSION.SDK_INT >= 26){
                    alarmIntent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
                }



                context.startActivity(alarmIntent); //啟動顯示鎖屏消息的activity
            }
        }
    }
}
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

/**
 * 模擬推送,在退出APP后的一段時間發送消息
 */
public class MyService extends Service {
    private static final String TAG = "MyService";

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "onBind: ");
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        Log.i(TAG, "onCreate: ");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand: ");
        sendMessage();
        return START_STICKY;
    }


    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy: ");
        super.onDestroy();
    }


    /**
     * 模仿推送,發消息
     */
    private void sendMessage() {
        System.out.println("sendMessage");
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Intent intent = new Intent();
                intent.setAction("com.demo.lockscreenmsgdemo.LockScreenMsgReceiver");
                //Android O版本對后台進程做了限制廣播的發送,對隱式廣播也做了限制;必須要指定接受廣播類的包名和類名
                //解決Background execution not allowed-----8.0以上發送的隱式廣播無法被收到問題
                intent.setComponent(new ComponentName("com.demo.lockscreenmsgdemo","com.demo.lockscreenmsgdemo.LockScreenMsgReceiver"));
                sendBroadcast(intent); //發送廣播
            }
        }).start();
    }
}

頁面布局:

activity_details.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="com.demo.lockscreenmsgdemo.activity.DetailsActivity">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="18sp"
    android:text="這是消息的詳情"/>

</LinearLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.demo.lockscreenmsgdemo.activity.MainActivity">

    <Button
        android:id="@+id/start_service_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="開啟消息服務" />

</RelativeLayout>

activity_message.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:layout_marginStart="15dp"
    android:layout_marginEnd="15dp"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#381515"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/icon_iv"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_centerVertical="true"
            android:layout_marginStart="15dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/qq" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginStart="15dp"
            android:layout_toEndOf="@id/icon_iv"
            android:text="QQ"
            android:textColor="#fff" />

        <ImageView
            android:id="@+id/close_iv"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"
            android:layout_marginEnd="15dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/close" />

    </RelativeLayout>

    <LinearLayout
        android:id="@+id/message_layout"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#1c3636"
        android:orientation="vertical"
        android:paddingLeft="15dp"
        android:paddingTop="25dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=".在嗎?"
            android:textColor="#fff" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text=".今天有空嗎!"
            android:textColor="#fff" />
    </LinearLayout>

</LinearLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.demo.lockscreenmsgdemo">

    <!-- 解鎖屏幕需要的權限 -->
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
    <!-- 申請電源鎖需要的權限 -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".activity.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".activity.MessageActivity"
            android:excludeFromRecents="true"
            android:launchMode="singleInstance"
            android:taskAffinity="" />

        <receiver
            android:name=".LockScreenMsgReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>

                <!-- 監聽鎖屏消息 -->
                <action android:name="com.demo.lockscreenmsgdemo.LockScreenMsgReceiver" />
            </intent-filter>
        </receiver>

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

        <activity android:name=".activity.DetailsActivity"></activity>
    </application>

</manifest>

適用應用場景

  • 適用應用場景:應用沒有完全退出的情況下在后台運行時,如果用戶已經關閉了手機屏幕,如果我們的APP收到推送消息,則打開手機屏幕,彈框顯示消息的方式來提醒用戶。

實現思路

  • 在收到自己服務器的推送消息時,發送一條廣播,在接收到指定廣播之后在廣播的onReceive()中判斷當前屏幕是否處於關閉狀態,如果處於關閉狀態,則顯示這個彈窗消息,反之,則不需要顯示

說明:

  • KeyguardManager類,管理鎖屏

  • 在廣播中啟動Activity的context可能不是Activity對象,有可能是Service或者其他BroadcastReceiver,所以需要添加NEW_TASK的標志,否則啟動時會報錯。

  • 能夠在鎖屏狀態下顯示消息就是因為窗體對象的這個添加標志位的這個方法起了作用。四個標志位的作用,分別是鎖屏狀態下顯示,解鎖,保持屏幕長亮,打開屏幕。這樣當Activity啟動的時候,它會解鎖並亮屏顯示。保持屏幕長亮這個標志位是可選的。

設置了背景為壁紙的背景,所以顯示的是桌面的背景。如果背景設為默認的白色,則導致彈窗后面是一片白色,看起來很丑。如果背景設置為透明,則彈窗后面會顯示出解鎖后的界面(即使有鎖屏密碼,也是會顯示解鎖后的界面的),一樣很影響視覺效果。

當顯示完消息,點擊消息內容的時候,需要先先解鎖系統自帶鎖屏服務,才能進入我們對應的消息界面。

運行效果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM