android開發 鎖屏 真正的鎖屏,是go鎖屏那種。


想做個鎖屏界面很久了,最近一周,歷經千辛萬苦,越過種種挫折,終於完美實現了這一要求,在此將鎖屏思路分享出來。

注意:這不是什么一鍵鎖屏,是類似“go鎖屏”那樣的鎖屏界面。

 

准備:本程序共需要

兩個activity:home、main。

一個service:myService

一個receiver:bootReceiver

一個layout:layout

其中home作為屏幕home鍵專用的activity,main則是主要的展示鎖屏界面的activity。

service用於接收鎖屏/解鎖廣播,layout則是main所需要展示的界面。

 

思路:

!注意:以下代碼沒有順序聯系,具體請參考源碼!

 

1,給程序添加服務,當此服務接收到 鎖屏/解鎖廣播 時,關閉系統鎖屏界面,打開自己的鎖屏界面。

 

關鍵代碼:

/onReceive中:

keyguardManager = (KeyguardManager)context.getSystemService(context.KEYGUARD_SERVICE);
keyguardLock = keyguardManager.newKeyguardLock("");
keyguardLock.disableKeyguard();//解鎖系統鎖屏
startActivity(toMainIntent);//跳轉到主界面

 

注意,上面的代碼需要注冊權限:

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

 

另外,為了防止主界面被重復調用,我們在設置intent時還要加上一些filter:

//設置myservice中intent的filter
toMainIntent = new Intent(myService.this, Main.class);
toMainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//這個flags表示如果已經有這個activity,則將已有的提到棧頂,否則新建一個activity。
//在manifest中講主界面的啟動模式更改為:singleTask,功能和上面的“Intent.FLAG_ACTIVITY_NEW_TASK”類似
<activity
android:name="com.example.screenlocker.Main"
android:label="@string/app_name"
android:launchMode="singleTask" >
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
</activity>

 

當然,我們還可以在onDestroy中設置服務重啟,以保證此服務一直在后台運行

@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(screenReceiver);
    //重啟此服務
    startActivity(new Intent(myService.this,myService.class));
}

 

將一些其他的事項,如注冊服務、在主界面中啟動服務等設置完成后,我們可以run一遍了~

如果沒出錯,那么解鎖后首先打開的將是我們的鎖屏界面。

 

2,實現了鎖屏,但是還有一個問題,當按返回鍵或者home鍵的時候,我們的界面就輕易被KO了。別擔心,咱們一一屏蔽他們。

 

首先,拿返回鍵開刀:只需要在主界面中添加如下代碼即可:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
  switch (keyCode) {
  case KeyEvent.KEYCODE_BACK:
    return true;
  }
  return super.onKeyDown(keyCode, event);
}

 

可是,home鍵並不能通過此方法屏蔽或者捕捉。這對程序猿來說是個很頭疼的問題,在網上也有各種解決的辦法,但是筆者參考總結,決定用“GO鎖屏”的方式來實現:

這種辦法的思路是:把自己的程序設置為系統主屏幕!這樣,本來按home鍵是要轉到主屏幕的,設置好后,按home鍵則直接跳轉到我們的界面里來了!

好了,讓我們新建一個activity,命名為“home”,用來搶奪home鍵。然后在manifest中設置如下:

<activity android:name="com.example.screenlocker.Home" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.HOME" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

 

這樣,當按home鍵的時候,如果是在main界面按的,系統不做反應。如果是在其他時候按下home鍵,就會跳轉到這個activity中來。

(首次運行時,會讓你選擇按home鍵跳轉到“主屏幕”或者“test1(咱們自己寫的程序的appName)”)

也就是說,我們已經實現了鎖屏界面對home的屏蔽。如果是在非鎖屏狀態下按home,就會調用home界面。我們只需在home界面里如此設置即可:

onCreate(){
跳轉到系統主屏幕;//具體代碼見下文
finish();//結束這個activity
}

 

所以,這個activity沒有必要加載界面。故此,我們要將這個activity的theme設置為“不顯示”,這樣,不但避免浪費,更可以避免在跳轉的時候屏幕閃一下,影響用戶體驗

//manifest設置home的theme為noDisplay
<activity
    android:name="com.example.screenlocker.Home"
    android:theme="@android:style/Theme.NoDisplay" >
        <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.HOME" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

 

我們可以在home的oncreate里打這樣一行代碼:

Log.e("", "home is called");finish();//調用finish以防止程序卡在一個不展示的activity

 

然后運行一遍試試效果,就可以清楚的發現,當我們何時按home鍵時,會調用這一activity。

 

3,home鍵已經搶過來了。那么接下來,我們要做的是讓home界面跳轉到主界面:

 

首先,我們要獲取一個列表:列出所以可以作為主屏幕的程序:

List<String> pkgNamesT = new ArrayList<String>();
List<String> actNamesT = new ArrayList<String>();
List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
  for (int i = 0; i < resolveInfos.size(); i++) {
    String string = resolveInfos.get(i).activityInfo.packageName;
    if (!string.equals(context.getPackageName())) {//排除自己的包名
      pkgNamesT.add(string);
      string = resolveInfos.get(i).activityInfo.name;
      actNamesT.add(string);
    }
  }

 

然后,可以用alertDialog的方式讓用戶選擇要跳到哪個主屏幕,並用sharedPreferences記錄用戶的選擇。

new AlertDialog.Builder(context).setTitle("請選擇解鎖后的屏幕").setCancelable(false).setSingleChoiceItems(names, 0, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        editor.putString(packageName, pkgNames.get(which));
        editor.putString(activityName, actNames.get(which));
        editor.commit();
        originalHome();
        dialog.dismiss();
    }
}).show();

 

這樣,下次的時候就可以根據包名和類名,直接跳轉到用戶所設置的主屏幕了:

String pkgName = sharedPreferences.getString(packageName, null);
String actName = sharedPreferences.getString(activityName, null);
ComponentName componentName = new ComponentName(pkgName, actName);
Intent intent = new Intent();
intent.setComponent(componentName);
context.startActivity(intent);
((Activity) context).finish();

 

 

 

4,當然,最后,我們也希望可以將其設置為開機啟動:

public class BootReceiver extends BroadcastReceiver{
    String myPkgName = "com.example.screenlocker";//#包名
    String myActName = "com.example.acts.myService";//#類名
    
    @Override
    public void onReceive(Context context, Intent intent) {
        //啟動監聽服務
        Intent myIntent=new Intent();
        myIntent.setAction(myPkgName+"."+myActName);
        context.startService(myIntent);    
    }
}

 

注意:別忘了在manifest中添加開機啟動的權限哦:

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

 

不過我更推薦在home中加這么一行代碼:

startService(new Intent(Home.this, ScreenReceiver.class));

 

這樣,每次打開主屏幕都能打開這個后台服務,哈哈哈……

 

下載源碼

 

附言

筆者在查資料時,發現極難找到此類資料。要么晦澀難懂,要么資料不全。深深的體會到了四處碰壁的絕望,故此才有了此文。

本文將鎖屏實現思路及源碼分享出來,稍加修改即可使用,希望能幫到有同樣需求的人。希望有收獲的人能花半秒鍾推薦一下,方便其余coder查閱。


免責聲明!

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



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