Androidデバイスで独立した時間を保つ

こんにちは



ある晴れた日、マネージャーが私のところに来て、「ユーザーが電話の時刻を変更するのを防ぐことができますか?」と言います。 そしてもちろん、私の答えはノーでしたが、これは問題を解決しませんでした。 状況から抜け出す方法を探す必要がありました。

決定の基準は次のとおりです。





私たちは座って、考えました、そして別の受け入れられる選択肢がありました- ブラックジャックであなた自身を行うこと...そしてデバイスに依存しない時間です。







免責事項
このソリューションは、ミリ秒単位の精度を保証しません。 エラーは1〜4分です。

特に上級ユーザーによるハッキング(バイパス)から保護されていません。 さらに言えば、すべてが壊れます。 平均的な素人向けに設計されています。





それでは始めましょう。

最初に、時間の保存を担当するクラスを作成します。 場所として、SharedPreferencesを選択しました。

なぜなら ここでは些細なことが行われますが、スポイラーに隠して目が冷たくならないようにします。

クラスSettingsMaster
class SettingsMaster { private static final String FILE_SETTINGS = "prop"; private static final String LOCAL_TIME = "LOCAL_TIME"; private static final String SYSTEM_TIME = "SYSTEM_TIME"; private static final String FLASH_BACK = "FLASH_BACK"; private static SharedPreferences getPreference(final Context context) { return context.getSharedPreferences(FILE_SETTINGS, Context.MODE_PRIVATE); } private static SharedPreferences.Editor getEditor(final Context context) { return getPreference(context).edit(); } public static void setTime(final Context context, final long mls) { getEditor(context).putLong(LOCAL_TIME, mls).apply(); } public static long getTime(final Context context) { return getPreference(context).getLong(LOCAL_TIME, 0); } public static void setSystemTime(final Context context, final long mls) { getEditor(context).putLong(SYSTEM_TIME, mls).apply(); } public static long getSystemTime(final Context context) { return getPreference(context).getLong(SYSTEM_TIME, 0); } public static void setFlashBack(final Context context, final boolean isFlashback) { getEditor(context).putBoolean(FLASH_BACK, isFlashback).apply(); } public static boolean isFlashBack(final Context context) { return getPreference(context).getBoolean(FLASH_BACK, false); } }
      
      









次は、メインAPIを提供するクラスです。 彼は時間を節約して与え、時間を更新するタイマーを開始します。

すべてが非常に一般的です。 ここで興味深いのは、サーバー時間を設定するとき、まずタイマーを停止し、新しいサーバー時間を保存してから再起動する必要があります。

クラスIndependentTimeHelper
 public class IndependentTimeHelper { public static void setServerTime(final Context context, final long serverTime) { stopTimer(context); SettingsMaster.setTime(context, serverTime); SettingsMaster.setFlashBack(context, false); SettingsMaster.setSystemTime(context,System.currentTimeMillis()); startTimer(context); } static void startTimer(final Context context) { final Intent intent = new Intent(context, TimeReceiver.class); intent.setAction(TimeReceiver.ACTION_TO_UPDATE_TIME); if (PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE) == null) { final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + TimeReceiver.TIME_PERIOD, TimeReceiver.TIME_PERIOD, pendingIntent); } } static void stopTimer(final Context context) { final Intent intent = new Intent(context, TimeReceiver.class); intent.setAction(TimeReceiver.ACTION_TO_UPDATE_TIME); final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE); if (pendingIntent != null) { final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(pendingIntent); pendingIntent.cancel(); } } public static long getTime(final Context context) { if (SettingsMaster.isFlashBack(context)) return -1; return SettingsMaster.getTime(context); } }
      
      









興味深いことに移りましょう。 すべてのメインロジックはレシーバーに落ちました。

レシーバーは、起動時に開始、シャットダウン時に開始、更新時に開始の3つのイベントにサブスクライブします。



時間が更新されたときに何が起こるかは明らかであり、時間を増やす必要があります。

  private void incrementTimeAndSaveSystemTime(final Context context) { final long localTime = SettingsMaster.getTime(context) + TIME_PERIOD; SettingsMaster.setTime(context, localTime); SettingsMaster.setSystemTime(context, System.currentTimeMillis()); }
      
      





TIME_PERIODの値は30秒​​に選択されました。 いいえ、バッテリーには影響しません。 それが動作するアプリケーションは常に私のデバイスにインストールされており、すべてがクールです。



次のステップは、システムの時刻を記憶して、デバイスがオフになったおおよその時刻を知ることができるようにすることです。

 if (action.equals(Intent.ACTION_SHUTDOWN)) SettingsMaster.setSystemTime(context, System.currentTimeMillis());
      
      







そして最後に、最も重要なことは、デバイスがオフ状態にあった時間を計算することです。

最初に、最後に保存されたシステム時間を取得します

 final long systemTime = SettingsMaster.getSystemTime(context);
      
      





休暇を計算します

 final long offTime = System.currentTimeMillis() - systemTime;
      
      





ゼロ以下の場合、時間の変換につまずきました。 私たちは特に前進することに興味がなく、追跡することは非常に困難です。

 if (offTime <= 0) SettingsMaster.setFlashBack(context, true);
      
      







それを現在のものに追加し、タイマーを開始します

 final long localTime = SettingsMaster.getTime(context); final long newLocalTime = localTime + offTime; SettingsMaster.setTime(context, newLocalTime); IndependentTimeHelper.startTimer(context);
      
      





完全な受信機コード
 public class TimeReceiver extends BroadcastReceiver { public static final String ACTION_TO_UPDATE_TIME = "com.useit.independenttime.ACTION_TO_UPDATE_TIME"; public static final long TIME_PERIOD = 30 * 1000; @Override public void onReceive(Context context, Intent intent) { if (SettingsMaster.getTime(context) <= 0) { IndependentTimeHelper.stopTimer(context); return; } final String action = intent.getAction(); if (action.equals(Intent.ACTION_BOOT_COMPLETED)) startReceiverAfterBootComplete(context); if (action.equals(Intent.ACTION_SHUTDOWN)) SettingsMaster.setSystemTime(context, System.currentTimeMillis()); if (action.equals(ACTION_TO_UPDATE_TIME)) incrementTimeAndSaveSystemTime(context); } private void startReceiverAfterBootComplete(final Context context) { final long systemTime = SettingsMaster.getSystemTime(context); if (systemTime > 0) { final long offTime = System.currentTimeMillis() - systemTime; if (offTime <= 0) SettingsMaster.setFlashBack(context, true); final long localTime = SettingsMaster.getTime(context); final long newLocalTime = localTime + offTime; SettingsMaster.setTime(context, newLocalTime); IndependentTimeHelper.startTimer(context); } } private void incrementTimeAndSaveSystemTime(final Context context) { final long localTime = SettingsMaster.getTime(context) + TIME_PERIOD; SettingsMaster.setTime(context, localTime); SettingsMaster.setSystemTime(context, System.currentTimeMillis()); } }
      
      









以上です。 できた

マニフェストに許可を追加することを忘れないでください

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







ソースと例



その結果、デバイスの時間を維持するためのシステムが機能しました。 はい、それは完璧ではありませんが、タスクをうまく解決します。



PS。 マネージャーは満足しています。



All Articles