【问题标题】:Check a site to display notifications检查网站以显示通知
【发布时间】:2012-12-02 22:14:39
【问题描述】:

假设地址www.foo.com/notification.txt 经常使用格式化字符串进行更新,该字符串必须在 Android 设备中显示为通知。获取该字符串的最佳方法是什么?

我已经尝试了几件事。我最后一次尝试是创建一个扩展 BroadcastReceiver 的类并配置 ALARM_SERVICE 以重复调用它:

AndroidManifest.xml:

 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
 <receiver  android:process=":remote" android:name="Alarm"></receiver>
    <receiver android:name=".AutoStart">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
        </intent-filter>
    </receiver>

Alarm.java:

package br.com.mypackage.cfqm;
import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;

import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import android.widget.Toast;

public class Alarm extends BroadcastReceiver 
{    
    int period_ms = 5*60*1000;
    SharedPreferences prefs;
    String user;
    String pass;
    Context context;

    public void check_notifications(){
            //http request to get and parse the notifications
        String[] notifications = http_request("http://foo.com/notification.html")).split("\n");

        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.cancelAll();
        int notification_next_id = 0;


        for (String notification_line:notifications){
            String[] notification = notification_line.split(";");
            if (notification.length==3)
                notify(notification_next_id++,notification[0],notification[1],notification[2]);
        }
    }

    public void notify(Integer id,String title,String text,String url){
            //displays a single notification
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        NotificationCompat.Builder notificationBuilder =
            new NotificationCompat.Builder(context)
                .setSmallIcon(R.drawable.ic_action_search)
                .setAutoCancel(true)
                .setContentTitle(title)
                .setContentText(text);
        Intent resultIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
        stackBuilder.addParentStack(Main.class);
        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
        notificationBuilder.setContentIntent(resultPendingIntent);
        notificationManager.notify(id,notificationBuilder.build());
        Log.v("cfqm","notificado");

    }

    public String http_request(String url) {
            //makes a http request
        try {
            HttpClient httpClient = new DefaultHttpClient();
            HttpContext localContext = new BasicHttpContext();
            HttpGet httpGet = new HttpGet(url);
            HttpResponse response = httpClient.execute(httpGet, localContext);
            String result = ""; 

            BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            String line = null;
            while ((line = reader.readLine()) != null)
              result += line + "\n";
            return result;
        }
        catch (Exception e){
            e.printStackTrace();
            return "";
        }

    }


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

         StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
         StrictMode.setThreadPolicy(policy); 

         // The function below will be called periodically
         check_notifications();
     }

     public void SetAlarm(Context context)
     {
         prefs = PreferenceManager.getDefaultSharedPreferences(context);
         user = prefs.getString("user","");
         pass = prefs.getString("pass","");

         AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
         Intent i = new Intent(context, Alarm.class);
         PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
         am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), period_ms, pi); // Millisec * Second * Minute
     }

     public void CancelAlarm(Context context)
     {
         Intent intent = new Intent(context, Alarm.class);
         PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         alarmManager.cancel(sender);
     }
 }

如果我所做的只是记录一个字符串,我可以让函数 check_notifications 重复运行。但是无论我在里面使用 http_request 都会发生奇怪的事情,从应用程序崩溃到整个系统冻结。我知道我应该异步运行它。但是怎么做呢?

【问题讨论】:

  • 在大多数情况下,应用程序崩溃等奇怪的事情会在日志中留下关于原因的有价值信息。在此处询问之前调查 LogCat 输出通常会有所帮助。如果您无法解释 logcat 输出,您可以尝试用谷歌搜索它。如果仍然没有成功,问问题引用 logcat

标签: android asynchronous process notifications httprequest


【解决方案1】:

你必须使用AsyncTask

Android 文档在这里: Async Class 很简单。

此外,如果您希望它定期运行,请考虑使用 Service(Service Class)

此外,应用程序崩溃是因为您在主线程上运行某些东西,而不是在后台运行。因此,一切都会冻结,直到您从网页中获得结果。 在该网页负载过重的情况下,您必须等待。

异步类示例:

 private class MyAsyncTask extends AsyncTask<URL, Integer, Integer> {

 protected Integer doInBackground(URL... urls) {
     int count = urls.length;
     long totalSize = 0;
//This is for many urls. If you download staff only from one url use url[0] instead of a for-loop. 
     for (int i = 0; i < count; i++) {
         //do something with url[i]
     }
     return 0; //or return some stats you can later use (eg how many bytes downloaded)
 }

 protected void onProgressUpdate(Integer... progress) {
//You can completely skip this method. It is to show a progress bar of how % is done
     setProgressPercent(progress[0]);


 }

 protected void onPostExecute(Integer result) {
//This is where everything finishes, and you got the result of your webpage

     showDialog("Downloaded " + result + " bytes");
 }
}

然后,创建一个新的 AsyncTask 对象,并像这样启动任务:

asyncTaskObj.execute(...);

【讨论】:

  • 我不知道如何修改该代码以使用 Async 类(我不是 Android 开发人员,只是将这个简单的应用程序作为一个例外,非常抱歉,真的)。究竟应该在那里做什么。让 BroadcastReceiver 定期运行已经够难的了。那么,例如,我如何让一个完全不同的 AsyncTask 定期运行?
  • 所以我只有我的http_request 函数来获取该url 的内容,我的notify 函数使用NotificationManager 在doinBackground 中显示它?即使 HttpRequest 在那里运行同步,它会完全没问题吗?为了让它定期运行,我只在我的 Main 函数中有这个 stackoverflow.com/questions/6531950/…
  • 你必须把你的 HTTP 请求放在 doInBackground 上,当一切都完成后,onPostExecute 被调用。所以onPostExecute,当你的任务完成后,放任何你想做的事!是的,您可以使用该链接的代码(使其定期运行)。您拥有的链接中的异步任务是“PerformBackgroundTask”。所以用你的 AsyncTask 类名替换它。希望对你有所帮助!
  • 太好了,谢谢。我会试试看。知道你已经很有帮助了,但是如果我有疑问,你可以稍后再回来吗?
  • 我会,只要我看到通知。
猜你喜欢
  • 1970-01-01
  • 2019-06-01
  • 2020-06-06
  • 1970-01-01
  • 2016-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多