android - 检查站点以显示通知

标签 android asynchronous process notifications httprequest

假设地址 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>

报警器.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 还是会发生奇怪的事情,从应用程序崩溃到整个系统卡住。我知道我应该异步运行它。但是如何呢?

最佳答案

你必须使用AsyncTask

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

此外,如果您希望它定期运行,请考虑使用服务( 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(...);

关于android - 检查站点以显示通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13674491/

相关文章:

android - 使用 Firebase/Parse/PubNub 的跨平台文本、图像、视频 Chat for Android、iOS 和 Web

java - 当读取 extras 值的 Activity 位于顶部时,通知传递旧的 Intent Extras

android - GCM 在模拟器中有效,但在移动设备中无效

c - 是否每个进程都将其 stdin stdout stderr 定义为键盘、终端等?

java - 计算 Panchanga 元素结束时间

c# SocketAsyncEventArgs 阻塞 ReceiveAsync 处理程序中的代码

javascript - 使用来自一个异步 API 调用的数据到另一个异步 API 调用

java - 在java中删除文件

process - 执行 TProcess 时隐藏控制台

Objective-C IOS 设备之间的异步通信