0

I have been trying all day, but I can't seem to figure it out. I am trying to return a string from AsyncTask in BroadcastReceiver but I am not sure how to do it correctly (new at Java). I have an app that accesses the internet and reads a text file and this text file is a long string. I delimit the string into an array and use it contents that way. In the BroadcastReceiver I want to broadcast (update) the temperature from the weather station every 10-60 minutes depending on what the user sets-up on the notification bar.

Should I use a Thread instead of AsyncTask?
The error I get is with the following line:

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

I also tried the following code that is commented out:

// GetWeatherValues clientraw = new GetWeatherValues();

// clientraw.doInBackground(weburi);

Below is my Class, please help, I have searched a lot and still no result.

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;
    }
}
}
Community
  • 1
  • 1
Dino
  • 561
  • 3
  • 10
  • 21
  • Don't run an async task in broadcast receiver. After the `onReceive` method finishes consider the receiver instance unusable. Use the receiver to launch an `IntentService` or `Service` which will do the actual work. – Eugen Pechanec Jan 18 '15 at 15:47
  • Google "EventBus". You can use it to post data from services to activities or between anything pretty much. – Eugen Pechanec Jan 18 '15 at 15:48
  • What about a Running a Thread? Is that also a bad idea? – Dino Jan 18 '15 at 16:07
  • 1
    Unless you need a context, you should be fine. BUT! `IntentService` runs on a background thread (so you can use HTTP) and gives you a context. And since you wouldn't post back the result to the receiver (which has ended by this point) it fits perfectly. – Eugen Pechanec Jan 18 '15 at 16:13
  • Ah I see, I was running the HTTP in a Runnable Thread and changed it to AsyncTask as I read it was better. – Dino Jan 18 '15 at 16:20
  • 1
    `AsyncTask` is OK when used in an activity (or rather retained fragment). If you need to decouple it you use receiver-service pair with result posting to whoever wants it (here comes in the event bus). Or the service writes to a content provider which you observe in your activity using `CursorLoader` (again there's no direct connection between the service and the activity). I'm just tossing ideas, be sure to check the actual answers. – Eugen Pechanec Jan 18 '15 at 16:29

1 Answers1

1

what you can do is to override onPostExecute() in Async Task have a look at this link for How to use AsyncTask correctly in Android

onPostExecute() allow to handle your things on UI Thread.

and here you can access your String (String returnData)

and you can also return value from async-task for that have look at this link How to handle return value from AsyncTask but i will prefer for you not to that cos i will be a little bit complicated

a piece of code

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());

    }


  }
}
Community
  • 1
  • 1
Moubeen Farooq Khan
  • 2,875
  • 1
  • 11
  • 26
  • Ah, I see, you moved the code onto onPostExecute(), According to one of the links you showed me it states that I should do UI updates in this method. How do I get the context in this method? – Dino Jan 18 '15 at 16:13
  • if that answer is satisfies your problem then kindly accept it – Moubeen Farooq Khan Jan 18 '15 at 16:19
  • Just one last question, how do I get the context in this method, before it was being passed into the onReceive method. – Dino Jan 18 '15 at 16:25
  • replace context with MainActivity.this.getSystemService(Context.NOTIFICATION_SERVICE); – Moubeen Farooq Khan Jan 18 '15 at 16:28
  • 1
    The context from a broadcast receiver will not work after the `onReceive` method is finished. Which is before the `AsyncTask` finishes. – Eugen Pechanec Jan 18 '15 at 16:32
  • 1
    so Create Context mContext on the top of calss and in onReceive method what you have to do is mContext=context; now use mContext where-ever you want to use in that class – Moubeen Farooq Khan Jan 18 '15 at 16:35
  • I tried and it gave me this error **No enclosing instance of the type MainActivity is accessible in scope** on the get notification manager. – Dino Jan 18 '15 at 16:36
  • wthat do you want to do with onReceive Context – Moubeen Farooq Khan Jan 18 '15 at 16:40
  • you can get context By MainActivity.this if onReceive finishes this will work – Moubeen Farooq Khan Jan 18 '15 at 16:41
  • It was in the pending intent and notification builder that had the context underlined. I got no errors in the code now but when I compile and run on a device,it is giving me an HTTP error in connection, but the URL is there and is correct. The error is **android.os.NetworkOnMainThreadException** – Dino Jan 18 '15 at 16:48
  • Ah a quick question, in order to run the AsyncTask I have the following: **GetWeatherValues clientraw = new GetWeatherValues(); clientraw.doInBackground();** – Dino Jan 18 '15 at 16:51
  • 1
    what you have to do is new ABC().execute(yoururl); – Moubeen Farooq Khan Jan 18 '15 at 16:55
  • Excellent that worked, thanks @MoubeenFarooqWarar and Eugen Pechanc – Dino Jan 18 '15 at 16:57