我有一个Android广播接收器(如果重要的话使用Eclipse),它由一个服务启动,该服务用于检查在线数据版本是否更新。如果是这样,我想在通知栏中触发通知。
一切似乎都运行正常,然而,从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中提取的那个多次错误。
有什么想法?对不起这么久。感谢。
科里
答案 0 :(得分:2)
SharedPreference.Editor.commit()
是一个阻止通话。这将花费时间并可能导致可能的ANR。
在API 9及更高版本上使用apply()
,然后在将旧版API版本本地存储期望值之前将其解析,将此代码移至服务,并记录异常,以便针对竞争条件进行适当调整此
答案 1 :(得分:0)
只有当您意识到某些内容发生了变化时,您才应该编写/提交更改 - 即“if(updated)”分支。并且您不应该使用静态成员,而是提交从服务器读取的值。
假设您的Receiver已重新启动(在新进程中)。在这种情况下,静态值以其初始值开始,因此latestversion为“0”。你提交这个值。
接下来你会读到“0”。现在,internalversion低于服务器版本 - 即使没有发生任何变化。
答案 2 :(得分:0)
尝试使用:
int mode = Context.MODE_PRIVATE;
而不是
int mode = Activity.MODE_PRIVATE;
它将开始在 SharedPreferences 中保存值。