2012-09-07 44 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节约值。