前言:
App會了保護使用者,通常都會製作一個閒置太久就登出的功能。通常會有兩個使用情境:
情境A、當使用者不使用app且把app縮到背景運行時,過一段時間後自動登出。
情境B、當使用者不使用手機,直接把手機螢幕黑掉待機。
逾時登出Demo |
第一種比較簡單
此時你要有三個條件
1、非必要條件
如果你的app有常駐的ToolBar,你可以不用每個Activity都寫一次ToolBar
可以直接寫一個底層帶有ToolBar的Activity,並讓其他的Activity都extands(繼承)它。
為什麼呢?
因為如果你沒有寫這個class讓大家都繼承,你每一個Activity都要加上逾時登出的代碼。
這邊就不再實作繼承的BaseActivity,我會直接寫在範例內的Activity內。
2、情境A
在Application內複寫onTrimMemory的方法。
這裡是讓情境A在縮到背景運行時,瞬間記錄下時間點。
簡單的介紹一下客製化的Application
概念:
android系統會為每個程序運行時創建一個Application類的對象且僅創建一個,所以Application可以說是單例 (singleton)模式的一個類.且application對象的生命週期是整個程序中最長的,它的生命週期就等於這個程序的生命週期。因為它是全局的單例的,所以在不同的Activity,Service中獲得的對象都是同一個對象。所以通過Application來進行一些,數據傳遞,數據共享,數據緩存等操作。
簡單的說就是存放整個App共用的共同參數的地方。
3、情境B
寫一個廣播BroadcastReceiver,在螢幕黑掉時,把暫停的時間點帶入廣播中,在喚起手機和app時,會再帶入。
edit(2017/10/20)
寫了一個part2
ndroid元件(ActivityLifecycleCallbacks) — 逾時登出製作 (二)
重點程式碼:
先來完成情境A的情況吧
首先你要先畫一個xml
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.hello.kaiser.baseactivity.MainActivity"> <TextView android:id="@+id/login_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="點我登入" android:textSize="50dp" /> </RelativeLayout>此時我只有在中間佈局一個TextView,方便模擬登入登出效果
接下來來做自製的Application吧!
CustomApplication.java
public class CustomApplication extends Application { //用來判斷使用者登出與否 public static boolean IsLogin = false; @Override public void onCreate() { super.onCreate(); } }裡面目前只塞一個boolean參數,用以判斷登入與否
/**
* true 登入狀態
* false 登出狀態
*/
此時Application是不會運行的!
你還要註冊自己的Application,告訴整個App,你要用我的喔!不可以使用系統預設的。
接下來把畫面切到AndroidManifest.xml中
<application android:name=".CustomApplication" 其他略... > ... </application>
再來就是MainActivity.java了
這邊稍微做麻煩一點
public class MainActivity extends AppCompatActivity { //元件 private TextView mLoginButton; private Activity activity; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); activity = this; initView();//初始化 元件畫面 initSet(); initListener();//初始化 監聽功能 } private void initView() { mLoginButton = (TextView) findViewById(R.id.login_btn); } private void initSet() { } private void initListener() { //設置按鈕點擊 mLoginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //點擊後,把文字改成已登入/登出(模擬登入效果) if (!CustomApplication.IsLogin) { mLoginButton.setText("已登入 \n 帳號:helloWorld"); CustomApplication.IsLogin = true; //告訴IsLogin你已經登入囉 } else { //出現Dialog和使用者確認是否要登出 new AlertDialog.Builder(activity) .setMessage("確定要登出嗎?") .setPositiveButton("ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mLoginButton.setText("點我登入"); CustomApplication.IsLogin = false;//告訴IsLogin你已經登出囉 } } ) .setNegativeButton("no", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).show(); } } }); } }這邊我在程式碼內有做了AlertDialog詢問使用者是否登出。
這邊有一個CustomApplication.IsLogin的布林參數,用來判斷整個app的使用者登入的狀態。
簡單的模擬登入登出就完成囉。
正式開始實作
情境A
先覆寫CustomApplication.java
public class CustomApplication extends Application { //用來判斷使用者登出與否 public static boolean IsLogin = false; //螢幕消失要存的時間點 public static long PAUSE_TIME = 0; //螢幕恢復時的時間點 public static long RESTART_TIME = 0; @Override public void onCreate() { super.onCreate(); } @Override public void onTrimMemory(int level) { //螢幕背景運行時,記錄時間 if (level == TRIM_MEMORY_UI_HIDDEN) { PAUSE_TIME = System.currentTimeMillis(); } super.onTrimMemory(level); } }這邊在參數部分加入的暫停時間,並且在onTrimMemory內紀錄暫停的時間
TRIM_MEMORY_UI_HIDDEN 可參考這裡。
簡述就是他會在onStop前調用,那為什麼不直接用onStop呢?
因為如果寫在onStop內,你每個activity的轉換、關閉都會被調用。
onTrimMemory則是只有在畫面被轉到背景運行時才會被調用。
然後把畫面轉回MainActivity.java吧
public class MainActivity extends AppCompatActivity { //元件 private TextView mLoginButton; private Activity activity; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); activity = this; initView();//初始化 元件畫面 initSet(); initListener();//初始化 監聽功能 } private void initView() { mLoginButton = (TextView) findViewById(R.id.login_btn); } private void initSet() { } private void initListener() { //設置按鈕點擊 mLoginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //點擊後,把文字改成已登入/登出(模擬登入效果) if (!CustomApplication.IsLogin) { mLoginButton.setText("已登入 \n 帳號:helloWorld"); CustomApplication.IsLogin = true; //告訴IsLogin你已經登入囉 } else { //出現Dialog和使用者確認是否要登出 new AlertDialog.Builder(activity) .setMessage("確定要登出嗎?") .setPositiveButton("ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //系統登出 memberLogOut(); } } ) .setNegativeButton("no", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).show(); } } }); } @Override protected void onResume() { super.onResume(); //假如登出狀態,設置所有時間歸零 參數 boolean isMemberlogout = false; //如果喚醒時,暫停時間不為零 if (CustomApplication.PAUSE_TIME != 0) { //獲取喚醒時的時間 CustomApplication.RESTART_TIME = System.currentTimeMillis(); //在這邊喚醒時間 - 暫停時間 每1000單位 = 1 second 這邊用三秒代替 if ((CustomApplication.RESTART_TIME - CustomApplication.PAUSE_TIME) > Long.valueOf("3000")) { if (CustomApplication.IsLogin) { //告訴它要變成登出狀態了 isMemberlogout = true; } } //告訴他要變成登出狀態了,請歸零時間 if (isMemberlogout) { CustomApplication.PAUSE_TIME = 0; CustomApplication.RESTART_TIME = 0; memberLogOut(); } } } //系統登出 private void memberLogOut() { mLoginButton.setText("點我登入"); //告訴IsLogin你已經登出囉 CustomApplication.IsLogin = false; } }這裡因為登出元件重複到,所以額外拉出來當成一個方法,這樣可以減少籠code
memberLogOut |
如果你要螢幕離開一秒後登出 單位為1000,看你自身需求。
這邊就完成簡單的情境A囉!
當你想切換到Line或是按到home鍵,只要過了三秒會自動幫你變成登出狀態。
情境B
寫一個廣播BroadcastReceiver,在螢幕黑掉時,把暫停的時間點帶入廣播中,在喚起手機和app時,會再帶入。那就開始著手寫廣播吧
MyReceiver.java
public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String actionStr = intent.getAction(); //假如螢幕按掉了 if (actionStr.equals(Intent.ACTION_SCREEN_OFF)) { //記錄時間點 CustomApplication.PAUSE_TIME = System.currentTimeMillis(); } } }這裏Intent有一個查看螢幕按掉的方法,直接調用,如果螢幕按掉就記錄時間。
之後再回到MainActivity.java寫一個MyReceiver的方法
//如果螢幕黑頻按掉時,存取記錄時間點 private void register() { IntentFilter fliter = new IntentFilter(); fliter.addAction(Intent.ACTION_SCREEN_OFF); mReceiver = new MyReceiver(); registerReceiver(mReceiver, fliter); }上面這個方法可以在onCreate內調用它。
之後不要忘記在你離開App的同時,反註冊它。
@Override protected void onDestroy() { //在結束app的同時,關掉廣播 if (mReceiver != null) { unregisterReceiver(mReceiver); mReceiver = null; } super.onDestroy(); }
這時候試試看你的新功能吧!!
DEMO: https://github.com/nikeru8/timeoutLogout
這篇看完以興趣可以去看看
沒有留言:
張貼留言