前言:
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
這篇看完以興趣可以去看看




沒有留言:
張貼留言