2012-09-07 69 views
1

我有一個Android廣播接收器(使用Eclipse,如果它很重要),是由一個服務啓動的,假設檢查一個在線數據版本是否更新。如果是這樣,我想在通知欄中觸發通知。BroadcastReceiver SharedPreferences只是不可靠

一切似乎工作正常,但是,它從SharedPreferences獲得的結果是不可靠的。廣播接收器假設獲取存儲在SharedPreferences中的當前值並將其與來自Web網址的值進行比較。如果它比較了值並發現有更新(即url中的值大於存儲值),它會觸發通知並更新存儲在SharedPreferences中的值。廣播接收機每天檢查一次這個更新,這僅僅是爲了通知用戶,僅此而已。

我用來做這個的代碼似乎工作。但在這裏和那裏,它從SharedPreferences中提取默認值,並觸發更新通知,即使沒有任何更改。

我意識到我可能會在廣播接收器的onReceive中做太多的工作,但是我非常困惑如何從廣播接收器開始工作。

有沒有人有任何實現這個最好的方法的代碼示例?我已經搜索和搜索,但我似乎無法找到明確的步驟來做到這一點。以下是我有:

public class AlarmReceiver extends BroadcastReceiver { 

    public static JSONArray myJArray2; 
    public static InputStream is = null; 
    public static final String URL_DatabaseVersion = "http://www.mysite.com/mobile/version.php"; 
    public static NotificationManager nm; 
    public static Boolean updated = false; 
    public static int latestVersion = 0; 
    public static int internalVersion = 2; 

    public static final String PREFS_NAME = "MyPrefsFile"; 

    @Override 
    public void onReceive(Context context, Intent intent) { 

     updated = false; 
     SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0); 
     internalVersion = settings.getInt("dataversion", 1); 

     InputStream is = null; 
     String result = ""; 
     ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); 
     nameValuePairs.add(new BasicNameValuePair("","")); 

     try{ 
      HttpClient httpclient = new DefaultHttpClient(); 
      HttpPost httppost = new HttpPost(URL_DatabaseVersion); 
      httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
      HttpResponse response = httpclient.execute(httppost); 
      HttpEntity entity = response.getEntity(); 
      is = entity.getContent(); 
     }catch(Exception e){ 
     } 

     try{ 
      BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8); 
      StringBuilder sb = new StringBuilder(); 
      String line = null; 
      while ((line = reader.readLine()) != null) 
      { 
       sb.append(line + "\n"); 
      } 
      is.close(); 
      result=sb.toString(); 
     }catch(Exception e){ 
     } 

     try{ 
      JSONArray myJArray = new JSONArray(result); 
      myJArray2 = myJArray; 
     }catch(JSONException e){ 
     }  

     int mode = Activity.MODE_PRIVATE; 
     SharedPreferences mySharedPreferences = context.getSharedPreferences("MyPrefsFile",mode);   
     SharedPreferences.Editor editor = mySharedPreferences.edit(); 
     editor.putInt ("dataversion", latestVersion); 
     editor.commit(); 

     if (!Arrays.asList(myJArray2).contains(null)) 
     { 
      try{ 
       for(int i=0;i<myJArray2.length();i++) 
       { 
        JSONObject json_data = myJArray2.getJSONObject(i); 
        latestVersion = json_data.getInt("title"); 

        if (internalVersion < latestVersion) 
        { 
         updated = true; 
        } 
        else 
        { 
         updated = false; 
        } 
       } 
      } 
      catch(Exception e) 
      {} 
      finally 
      {} 
     } 
     else 
     { 
      updated = false; 
     } 

     if (updated) 
     { 
      nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 
      CharSequence from = "Database Updated"; 
      CharSequence message = "I: " + internalVersion + " L: " + latestVersion + "Click to open."; 
      PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(), 0); 
      Notification notif = new Notification(R.drawable.icon, "Database Updated", System.currentTimeMillis()); 
      notif.setLatestEventInfo(context, from, message, contentIntent); 
      nm.notify(1, notif); 
     } 
    } 
} 

是的,我可能是試圖做太多的廣播接收器,並且可能會引起問題,但是我無法弄清楚如何做這任何其他方式。當我記錄這段代碼的結果時,第一次通過它的效果很好。第二次通過internalVersion時出現0.它從URL獲得的值總是正確的,它是internalVersion,它是從SharedPreferences中抽取的,這是多次錯誤的。

有什麼想法?對不起,這麼久。謝謝。

科瑞

+2

不知道它是否可以解決您的問題,但我會在「服務」中完成所有這些工作。我沒有明顯的理由可以在'BroadcastReceiver'中看到這一點。 – kabuko

+0

這可能是真的,但我不知道如何設置它來做到這一點。我是否需要從廣播接收器的onReceive中調用服務?不知道如何獲得24小時重複檢查,即使用戶目前沒有與應用程序交互。 – Tom

+1

是的,你可以從'BroadcastReceiver'開始'Service'。 – kabuko

回答

2

SharedPreference.Editor.commit()是一個阻塞調用。這需要時間並可能導致可能的ANR。

在API 9及更高版本上使用apply()並在此之前關閉此功能,同時在較早的API版本上本地存儲預期值,將此代碼移動到服務中,並記錄您的異常,以便您可以針對這種競爭條件進行適當調試。

0

只有當您意識到某些事情發生了變化時,您才應該編寫/提交您的更改 - 即在「if(updated)」分支中。你不應該使用靜態成員,而是提交從服務器讀取的值。

假設您的接收器已重新啓動(在新的過程中)。在這種情況下,靜態值以它們的初始值開始,所以latestversion爲「0」。你提交這個值。

接下來運行您閱讀「0」。現在內部版本低於服務器版本 - 即使沒有發生變化。

+0

那麼,我最終會得到一個服務來設置一個叫另一個服務的警報接收器? – Tom

+0

好吧,我已經實現了上述現在在一個從警報接收器調用的服務,它似乎很好。感謝您的指導。但是有一個問題,當服務運行時,我似乎得到了瞬間的屏幕閃爍,如果我在代碼的末尾沒有使用finish(),則該服務會顯示一個空白的白屏並保持活動狀態。有什麼建議麼? – Tom

+0

服務不顯示屏幕 - 這就是活動的目的(並且只有活動具有finish()方法)。你可以發佈一些代碼嗎? –

0

嘗試使用:的

int mode = Context.MODE_PRIVATE; 

代替

int mode = Activity.MODE_PRIVATE; 

會開始在SharedPreferences節約值。