2016-03-29 39 views
0

我的目標是實現一個出現在用戶選擇的時間的通知。 我已經嘗試Service,這個工程,但問題是它需要很多後臺進程(代碼如下),另一個是AlarmManager,但這似乎不能正常工作,特別是在API 19 +。我找不到最新的編碼良好的教程或有關類似問題的有用答案,因此我轉向你。安卓定製時間通知服務/廣播/報警管理器

你們所有人都知道:如果朋友給你發短信給Whatsapp,即使你的手機處於關機或睡眠狀態(屏幕關閉),你也會收到通知。我相信你們中的一些人已經實現了這樣的東西。

準確的任務: 我的應用程序應每天通知一天關於他的日程安排事件。

例如: 他選擇了13:00(我總是使用24h格式)來提醒他他的事件。 他安排在第二天2個事件: - 驅動孩子上學 - 轉到健身房

次日13:00應用程序顯示一個通知: 「你今天有兩個事件!:1).. 2)...「

用信息填充通知不是問題。這工作正常,我測試了很多。我錯過了只有編碼良好的後臺線程,它們注意用戶選擇的時間來顯示通知。

請注意

  • 中,TimerTask蜱-INTERVALL是1000毫秒(1秒)。我確定這是不是很好的編碼,但它的作品。 但是,我正在尋找一個更好,更電池友好的解決方案。

  • 而且我添加了「android.permission.RECEIVE_BOOT_COMPLETED」「android.permission.WAKE_LOCK」權限。

  • 的服務標記爲START_STICKY

的Manifest.xml:

<?xml version="1.0" encoding="utf-8"?> 
<manifest ... > 
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> 
    <uses-permission android:name="android.permission.WAKE_LOCK" /> 

    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <service android:name=".services.NotificationService" android:exported="false"/> 

     <receiver android:name=".services.BootReceiver"> 
      <intent-filter> 
       <action android:name="android.intent.action.BOOT_COMPLETED"/> 
      </intent-filter> 
     </receiver> 

     <activity 
      android:name=".activities.MainActivity" 
      android:label="@string/app_name" 
      android:screenOrientation="portrait" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

     //Other Activities 

    </application> 

</manifest> 

BootReceiver:

public class BootReceiver extends WakefulBroadcastReceiver{ 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     context.startService(new Intent(context, NotificationService.class)); 
    } 
} 

NotificationService:

public class NotificationService extends Service{ 

    private Calendar currentCalendar, plannedCalendar; 

    public static final String FILENAME_SETTINGS = "MySettings"; 
    private static final int MODE_PRIVATE = 0; 
    SharedPreferences data; 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     return START_STICKY; 
    } 

    private Timer timer; 
    private TimerTask timerTask = new TimerTask() { 
     @Override 
     public void run() { 
      data = getSharedPreferences(FILENAME_SETTINGS, MODE_PRIVATE); 

      int plannedHour = data.getInt("alarm_hour", 0); 
      int plannedMinute = data.getInt("alarm_minute", 0); 
      plannedCalendar = Calendar.getInstance(Locale.getDefault()); 
      plannedCalendar.set(Calendar.MINUTE, plannedMinute); 
      plannedCalendar.set(Calendar.HOUR_OF_DAY, plannedHour); 
      plannedCalendar.set(Calendar.SECOND, 0); 
      plannedCalendar.set(Calendar.MILLISECOND, 0); 

      //Kalender aktualisieren 
      currentCalendar = Calendar.getInstance(Locale.getDefault()); 
      currentCalendar.setTimeInMillis(System.currentTimeMillis()); 
      //Check ob es 00:00:00 Uhr ist --> Notification wieder erwuenscht!!! 
      currentCalendar.set(Calendar.SECOND, 0); 
      currentCalendar.set(Calendar.MILLISECOND, 0); 
      if(currentCalendar.get(Calendar.SECOND) == 0 && currentCalendar.get(Calendar.MINUTE) == 0 && currentCalendar.get(Calendar.HOUR_OF_DAY) == 0){ 
       SharedPreferences.Editor editor = data.edit(); 
       editor.putBoolean("notification", false); 
       editor.apply(); 
      } 
      //Nochmal aktualisieren weil durch den "Check" manipuliert wurde 
      currentCalendar = Calendar.getInstance(Locale.getDefault()); 
      currentCalendar.setTimeInMillis(System.currentTimeMillis()); 


      if((currentCalendar.getTimeInMillis() >= plannedCalendar.getTimeInMillis()) & !data.getBoolean("notification", false)) { 
       PowerManager mgr = (PowerManager) getSystemService(Context.POWER_SERVICE); 
       PowerManager.WakeLock wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock"); 
       wakeLock.acquire(); 

       notification(); 
       SharedPreferences.Editor editor = data.edit(); 
       editor.putBoolean("notification", true); 
       editor.apply(); 

       wakeLock.release(); 
      } 
     } 
    }; 

    @Override 
    public void onCreate(){ 
     super.onCreate(); 
     timer = new Timer(); 
     timer.schedule(timerTask, 0, 1000); 
    } 

    @Override 
    public void onDestroy() { 
     try{ 
      timer.cancel(); 
      timerTask.cancel(); 
     }catch (Exception e){ 
      e.printStackTrace(); 
     } 
     Intent intent = new Intent("Intent"); 
     intent.putExtra("VALUE", "blalal"); 
     sendBroadcast(intent); 
    } 

    public void notification(){ 
     Context context = getApplicationContext(); 
     Intent intent = new Intent(context, LiveSelectActivity.class); 
     PendingIntent pen = PendingIntent.getActivity(getBaseContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 

     NotificationCompat.Builder builder = new NotificationCompat.Builder(context) 
       .setContentTitle(getString(R.string.hineweisTrainingsGeplant)) 
       .setContentText("Content") 
       .setContentIntent(pen) 
       .setDefaults(Notification.DEFAULT_ALL) 
       .setAutoCancel(true) 
       .setSmallIcon(R.drawable.ic_add_white_24dp); 

     Notification notification = builder.build(); 
     NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
     manager.notify(1, notification); 
    } 

    @Nullable 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

} 
+1

「我已經試過服務,這個工程」 - 不在Android 6.0以上。在較老的設備上,它可以可靠地工作,但用戶會因爲您造成的功耗而威脅到您的生活。 「另一個是AlarmManager,但這似乎不能正常工作,尤其是在API 19+上 - 」這取決於你使用的是什麼。例如'setAlarmClock()'是可靠的,儘管它具有與「鬧鐘」隱喻緊密相關的UI元素。 「如果朋友爲Whatsapp發短信,即使您的手機處於關機或睡眠狀態(屏幕關閉),您也會收到通知」 - 他們使用Google Cloud Messaging AFAIK。 – CommonsWare

+0

@CommonsWare感謝您的快速建議。我以各種想像的方式嘗試了AlarmManager:setExakt(),setInexakt(),setInExaktRepeating()等。問題在於,當手機處於睡眠狀態時,即使使用RTC_WAKE_UP,手機也不會喚醒。此外,我沒有找到api 19+問題的解決方案。因爲在發出一個通知後,您必須手動設置下一個這就是爲什麼我設置服務。 –

+1

「當手機處於睡眠狀態時,即使使用RTC_WAKE_UP,它也不會喚醒它 - 對於其他開發者,至少在Android 6.0+之前(打盹模式/應用程序待機開始干擾),以及當您沒有錯誤。 「另外,我沒有找到api 19+問題的解決方案,因爲在發出一個通知後,您必須手動設置下一個」 - 再次,它適用於其他開發人員。 – CommonsWare

回答

0

使用AlarmManager安排Intent s表示您的服務將在所需的時間接收和處理。如果配置正確,它會工作。

+0

我已經提到我使用了AlarmManager。我遇到過很多問題,特別是使用我的api 21設備。^^ –

+1

這意味着只有一件事 - 您沒有正確配置它。請參閱@CommonsWare對您的問題的評論 – Sam

+0

好的,我會再次檢查。 –