1

我有一个 Android 广播接收器(如果重要,则使用 E​​clipse),它由一个服务启动,该服务假设检查在线数据版本是否已更新。如果是这样,我想在通知栏中触发通知。

一切似乎都正常,但是,它从 SharedPreferences 获得的结果并不可靠。假设广播接收器获取存储在 SharedPreferences 中的当前值,并将其与从 Web url 获取的值进行比较。如果它比较该值并看到已进行更新(即 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);
        }
    }
}

是的,我可能试图在 BroadcastReceiver 中做太多事情,这可能会导致问题,但是我无法弄清楚如何以其他方式做到这一点。当我记录这段代码的结果时,第一次通过它就很好。第二次通过 internalVersion 出现 0。它从 URL 获得的值总是正确的,它是 internalVersion,它从 SharedPreferences 中提取的那个是错误的很多次。

有什么想法吗?抱歉这么久。谢谢。

科里

4

3 回答 3

2

SharedPreference.Editor.commit()是阻塞调用。这需要时间,并可能导致 ANR。

在 API 9 及更高版本上使用apply()并在之前将其线程化,同时在较旧的 API 版本上本地存储预期值,将此代码移动到服务,并记录您的异常,以便您可以针对此类竞争条件进行适当的调试。

于 2012-09-07T21:57:23.377 回答
0

尝试使用:

 int mode = Context.MODE_PRIVATE;

代替

 int mode = Activity.MODE_PRIVATE;

它将开始在SharedPreferences中保存值。

于 2013-03-18T07:44:29.573 回答
0

只有当您意识到某些事情发生了变化时,您才应该编写/提交您的更改——即在“if (updated)”分支中。而且您不应该使用静态成员,而是提交您从服务器读取的值。

假设您的接收器已重新启动(在进程中)。在这种情况下,静态值从它们的初始值开始,所以最新版本是“0”。你提交这个值。

下一次运行你会读到“0”。现在 internalversion 低于服务器版本 - 即使没有发生任何变化。

于 2012-09-07T22:18:51.273 回答