【问题标题】:Return String from AsyncTask in BroadcastReceiver从 BroadcastReceiver 中的 AsyncTask 返回字符串
【发布时间】:2015-01-18 15:41:02
【问题描述】:

我一直在尝试一整天,但我似乎无法弄清楚。我正在尝试从 BroadcastReceiver 中的 AsyncTask 返回一个字符串,但我不确定如何正确执行(Java 中的新功能)。我有一个应用程序可以访问互联网并读取一个文本文件,这个文本文件是一个长字符串。我将字符串分隔成一个数组并以这种方式使用它的内容。在 BroadcastReceiver 中,我想根据用户在通知栏上的设置每 10-60 分钟广播一次(更新)气象站的温度。

我应该使用线程而不是 AsyncTask 吗?
我得到的错误是以下行:

字符串输出 = new GetWeatherValues().execute(weburi);

我还尝试了以下被注释掉的代码:

// GetWeatherValues clientraw = new GetWeatherValues();

// clientraw.doInBackground(weburi);

下面是我的班级,请帮忙,我搜索了很多,仍然没有结果。

public class UpdateFrequency extends BroadcastReceiver {

// Notification Text Elements
private final CharSequence tickerText = "Weather Updated";
private CharSequence contentTitle = "Weather at ";
private final CharSequence contentText = "Current Temperature is ";

final String http = "http://";
final String clientraw = "/clientraw.txt";
String weburi, webUrl;

// Notification Action Elements
private Intent notificationIntent;
private PendingIntent mContentIntent;

// Notification ID to allow for future updates
private static final int MY_NOTIFICATION_ID = 1;

final String PREFS_NAME = "SettingsFile";

SharedPreferences settings;
public String[] parts;

public static final String WebAddress = "webAddressKey";


@SuppressLint("NewApi")
@Override
public void onReceive(Context context, Intent intent) {

    Log.e("log_etag", "Entered Update Frequency");

    settings = context.getSharedPreferences(PREFS_NAME,
            Context.MODE_PRIVATE);
    if (settings.contains(WebAddress)) {
        webUrl = settings.getString(WebAddress, "");
        weburi = http + webUrl + clientraw;
        Log.e("log_etag", "WEB URL Frequency " + weburi);
    }
    
//      GetWeatherValues clientraw = new GetWeatherValues(); 
//      clientraw.doInBackground(weburi);

    String output = new GetWeatherValues().execute(weburi);

    String[] parts = output.split(" ");

    ArrayList<String> clientRawData = new ArrayList<String>();
    clientRawData.addAll(Arrays.asList(parts));
    
    //Time of last update from weather station.
    contentTitle = contentTitle + parts[29] + ":" + parts[30]; 
    
    Log.e("log_etag", "Content Title " + contentTitle);
    
    // The Intent to be used when the user clicks on the Notification View
    notificationIntent = new Intent(context, MainActivity.class);

    // The PendingIntent that wraps the underlying Intent
    mContentIntent = PendingIntent.getActivity(context, 0,
            notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);

    // Build the Notification
    Notification.Builder notificationBuilder = new Notification.Builder(
            context).setTicker(tickerText)
            .setSmallIcon(android.R.drawable.stat_sys_warning)
            .setAutoCancel(true).setContentTitle(contentTitle)
            .setContentText(contentText).setContentIntent(mContentIntent);
    

    // Get the NotificationManager
    NotificationManager mNotificationManager = (NotificationManager) context
            .getSystemService(Context.NOTIFICATION_SERVICE);

    // Pass the Notification to the NotificationManager:
    mNotificationManager.notify(MY_NOTIFICATION_ID,
            notificationBuilder.build());
}



private class GetWeatherValues extends AsyncTask<Void, Integer, String> {
            
    @Override
    protected String doInBackground(Void... params) {
        
                    try {

                        HttpClient httpclient = new DefaultHttpClient();
                        // get url data
                        HttpPost httppost = new HttpPost(weburi);
                        HttpResponse response = httpclient.execute(httppost);
                        HttpEntity entity = response.getEntity();

                        InputStream webs = entity.getContent();
                        // convert response to string
                        try {
                            final BufferedReader reader = new BufferedReader(
                                    new InputStreamReader(webs, "iso-8859-1"),
                                    8);

                            // read one line of code, file is one whole string.
                            try {

                                String returnData = reader.readLine();
                                webs.close();
                                return returnData;

                            } catch (Exception e) {
                                Log.e("log_tag",
                                        "Error in displaying textview "
                                                + e.toString());
                                e.printStackTrace();
                            }

                        } catch (Exception e) {
                            Log.e("log_tag",
                                    "Error converting string " + e.toString());
                        }
                    } catch (Exception e) {
                        Log.e("log_tag",
                                "Error in http connection " + e.toString());

                } 
        return null;
    }
}
}

【问题讨论】:

  • 不要在广播接收器中运行异步任务。在onReceive 方法完成后,认为接收器实例不可用。使用接收器启动IntentServiceService,这将完成实际工作。
  • 谷歌“EventBus”。您可以使用它将数据从服务发布到活动或任何东西之间。
  • 运行线程怎么样?这也是个坏主意吗?
  • 除非您需要上下文,否则应该没问题。但! IntentService 在后台线程上运行(因此您可以使用 HTTP)并为您提供上下文。而且由于您不会将结果发回给接收器(此时已结束),它非常适合。
  • AsyncTask 在活动(或保留片段)中使用时可以。如果您需要将其解耦,您可以使用接收器-服务对并将结果发布给任何想要它的人(这里是在事件总线中)。或者该服务使用CursorLoader 写入您在活动中观察到的内容提供者(同样,服务和活动之间没有直接连接)。我只是在折腾想法,请务必检查实际答案。

标签: java android android-asynctask


【解决方案1】:

你可以做的是在异步任务中覆盖 onPostExecute() 看看这个链接How to use AsyncTask correctly in Android

onPostExecute() 允许在 UI 线程上处理你的事情。

在这里你可以访问你的字符串(String returnData)

你也可以从异步任务返回值,看看这个链接How to handle return value from AsyncTask 但我更喜欢你不要因为我会有点复杂

一段代码

private class ABC extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {

          //here your code

        return returnData;
    }

    @Override
    protected void onPostExecute(String returnedData) {
       //
   String[] parts = returnedData.split(" ");
   ArrayList<String> clientRawData = new ArrayList<String>();
   clientRawData.addAll(Arrays.asList(parts));

   //Time of last update from weather station.
   contentTitle = contentTitle + parts[29] + ":" + parts[30]; 

   Log.e("log_etag", "Content Title " + contentTitle);

   // The Intent to be used when the user clicks on the Notification View
   notificationIntent = new Intent(context, MainActivity.class);

   // The PendingIntent that wraps the underlying Intent
    mContentIntent = PendingIntent.getActivity(context, 0,
        notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);

    // Build the Notification
     Notification.Builder notificationBuilder = new Notification.Builder(
        context).setTicker(tickerText)
        .setSmallIcon(android.R.drawable.stat_sys_warning)
        .setAutoCancel(true).setContentTitle(contentTitle)
        .setContentText(contentText).setContentIntent(mContentIntent);


    // Get the NotificationManager
    NotificationManager mNotificationManager = (NotificationManager) context
        .getSystemService(Context.NOTIFICATION_SERVICE);

    // Pass the Notification to the NotificationManager:
    mNotificationManager.notify(MY_NOTIFICATION_ID,
        notificationBuilder.build());

    }


  }
}

【讨论】:

  • 啊,我明白了,您将代码移至 onPostExecute(),根据您向我展示的链接之一,它表明我应该在此方法中进行 UI 更新。如何在此方法中获取上下文?
  • 如果该答案满足您的问题,请接受它
  • onReceive 方法完成后,来自广播接收器的上下文将不起作用。这是在AsyncTask 完成之前。
  • so 在 calss 的顶部和 o​​nReceive 方法中创建上下文 mContext 你要做的是 mContext=context;现在在你想在该类中使用的任何地方使用 mContext
  • 你要做的就是 new ABC().execute(yoururl);
猜你喜欢
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 1970-01-01
  • 1970-01-01
  • 2014-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多