2014-02-13 4 views
5

SO в настоящее время у меня есть класс AsyncTask, который запускает и данные POST на моем сервере, когда я нажимаю кнопку (которая отлично работает).вызов AsyncTask из широковещательного приемника android

Что я пытаюсь сделать сейчас, это обработать то, что происходит, когда пользователь не подключен к Интернету. поэтому я установил эти классы для уведомления приложения, когда интернет подключен, чтобы данные могли быть отправлены автоматически на сервер.

AsyncTask класс (внутренний класс)

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

    ProgressDialog dialog = new ProgressDialog(getActivity()); 
    final AlertDialog finishedDialog = new AlertDialog.Builder(getActivity()) 
    .setCancelable(false) 
    .setPositiveButton(android.R.string.ok, null) 
    .create(); 



    @Override 
    protected String doInBackground(String... urls) { 
     onProgressUpdate("Uploading Data..."); 
     return POST(urls[0]); 
    } 

    @Override 
    protected void onPreExecute() { 
     this.dialog.show(); 
     finishedDialog.setOnShowListener(new DialogInterface.OnShowListener(){ 

      @Override 
      public void onShow(DialogInterface dialog) { 
       Button b = finishedDialog.getButton(AlertDialog.BUTTON_POSITIVE); 
       b.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 
        // navigate to match summary..... 
        finishedDialog.dismiss(); 
       } 

      }); 
      } 

     }); 
    } 

    protected void onProgressUpdate(String msg) { 
     dialog.setMessage(msg); 

    } 

    // onPostExecute displays the results of the AsyncTask. 
    @Override 
    protected void onPostExecute(String result) { 
     if (result != ""){ 

      finishedDialog.setTitle("Upload Complete!"); 
      finishedDialog.setMessage("Data Sent Successfully"); 
      finishedDialog.show(); 
      dialog.dismiss(); 
      editor.clear(); 
      editor.commit(); 
      //Toast.makeText(getActivity().getBaseContext(), result, Toast.LENGTH_LONG).show(); 
     }else 
     { 
      Handler handler = new Handler(); 
      handler.postDelayed(new Runnable() { 
       public void run() { 
        finishedDialog.setTitle("Upload Failed!"); 
        finishedDialog.setMessage("Data Will Automatically Be Uploaded When Internet Connection Is Available"); 
        finishedDialog.show(); 
        dialog.dismiss(); 
       }}, 1000); 

      setFlag(true); 
     } 
    } 

} 


public static boolean getFlag() { 
    return flag; 
} 

public void setFlag(boolean flag) { 
    this.flag = flag; 
} 


public String POST(String url){ 
    InputStream inputStream = null; 
    String result = ""; 
    try { 

     // 1. create HttpClient 
     HttpClient httpclient = new DefaultHttpClient(); 

     // 2. make POST request to the given URL 
     HttpPost httpPost = new HttpPost(url); 


     if(adapter.updateNeeded()){ 
      JSONObject main = new JSONObject(exmaplePrefs.getString("jsonString", "cant find json")); 
      JSONObject dbUpdates = new JSONObject(exmaplePrefs.getString("ChangesJSON", "cant find Changejson")); 
      main.put("Team_Updates", dbUpdates); 
      json = main.toString(); 
     }else{ 
      json = exmaplePrefs.getString("jsonString", "cant find json"); 
      // String json = "{\"twitter\":\"test\",\"country\":\"test\",\"name\":\"test\"}"; 
     } 




     // 5. set json to StringEntity 
     StringEntity se = new StringEntity(json); 
     se.setContentType("application/json;charset=UTF-8"); 

     // 6. set httpPost Entity 
     httpPost.setEntity(se); 

     // 7. Set some headers to inform server about the type of the content 
     // httpPost.setHeader("Accept", "application/json"); 
     // httpPost.setHeader("Content-type", "application/json"); 
     // httpPost.setHeader("json", json); 


     // 8. Execute POST request to the given URL 

     HttpResponse httpResponse = httpclient.execute(httpPost); 

     // 9. receive response as inputStream 
     inputStream = httpResponse.getEntity().getContent(); 

     String status = httpResponse.getStatusLine().toString(); 
     // 10. convert inputstream to string 
     if (!status.equals("HTTP/1.1 500 Internal Server Error")){ 
      if(inputStream != null){ 
       result = convertInputStreamToString(inputStream); 
      } 
      else{ 
       result = "Did not work!"; 
      } 
     }else{ 
      System.out.println("500 Error"); 

     } 



    } catch (Exception e) { 
     Log.d("InputStream", e.getLocalizedMessage()); 
     System.out.println("eerroorr "+e); 
    } 

    // 11. return result 
    System.out.println(result); 
    return result; 

} 

private static String convertInputStreamToString(InputStream inputStream) throws IOException{ 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 
    String line = ""; 
    String result = ""; 
    while((line = bufferedReader.readLine()) != null) 
     result += line; 

    inputStream.close(); 
    return result; 

} 
} 

NetworkUtil класс

public class NetworkUtil { 

public static int TYPE_WIFI = 1; 
public static int TYPE_MOBILE = 2; 
public static int TYPE_NOT_CONNECTED = 0; 


public static int getConnectivityStatus(Context context) { 
    ConnectivityManager cm = (ConnectivityManager) context 
      .getSystemService(Context.CONNECTIVITY_SERVICE); 

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 
    if (null != activeNetwork) { 
     if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) 
      return TYPE_WIFI; 

     if(activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) 
      return TYPE_MOBILE; 
    } 
    return TYPE_NOT_CONNECTED; 
} 

public static String getConnectivityStatusString(Context context) { 
    int conn = NetworkUtil.getConnectivityStatus(context); 
    String status = null; 
    if (conn == NetworkUtil.TYPE_WIFI) { 
     status = "Wifi enabled"; 
    } else if (conn == NetworkUtil.TYPE_MOBILE) { 
     status = "Mobile data enabled"; 
    } else if (conn == NetworkUtil.TYPE_NOT_CONNECTED) { 
     status = "Not connected to Internet"; 
    } 
    return status; 
} 
} 

BroadcastReceiver класс

public class NetworkChangeReceiver extends BroadcastReceiver { 


@Override 
public void onReceive(final Context context, final Intent intent) { 
    intent.getExtras(); 
    String status = NetworkUtil.getConnectivityStatusString(context); 

    Toast.makeText(context, status, Toast.LENGTH_LONG).show(); 

    if(MatchFragment.getFlag()){ 
     //send data 
    } 
} 
} 

Так в классе BroadcastReceiver я проверяю флаг, который получает значение ИСТИНА, когда приложение пытается отправить данные, но нет Интернета (onPostExecute в Асыне cTask Class).

так что хотите сделать, это как-то как вызвать метод POST. мне нужно создать новый класс задач Async? Я немного здесь.

Благодаря

ответ

9

Использование AsyncTask в BroadcastReceiver является плохой практика.

Вы должны использовать Service потому, что Android OS может убить процесс или onReceive() может выполняться до завершения, прежде чем asyncTask будет возвращать результат, так что нет никакой гарантии, вы получите ожидаемый результат.

+0

согласен, я собирался сказать. – Coderji

+1

@Coderji hahaha .. да, ваша мысль проходит через мой разум :) – QuokMoon

+0

Хорошо, могу ли я получить пример того, как реализовать сервис по отношению к моей проблеме? –

5

Вы не должны использовать AsyncTask в широковещательном приемнике, потому что система может убить ваш процесс после возвращения из метода onReceive (если нет какой-либо активной службы или активности). Proof link

Официальная документация recommends IntentService для таких случаев (см. Пункт о широковещательных приемниках).

+0

Это неверно, в документации на Android говорится, что вызов goAsync и использование AsyncTasks является допустимым и предлагаемым сценарием. –

2

Другие ответы не правильные according to Google's documentation. Руководство разработчика радиоприемников явно вызывает то, что вы можете использовать AsyncTask с от BroadcastReceiver с, если вы звоните goAsync() первый и отчет о состоянии в ожидании результата в AsyncTask

По этой причине, вы не должны начинать долго выполняющиеся фон потоков от широковещательного приемника. После onReceive() система может убить процесс в любое время, чтобы восстановить память, и при этом он завершает порожденный поток, выполняемый в этом процессе. Чтобы избежать этого, вы должны либо вызвать goAsync() (если вы хотите немного больше времени для обработки широковещательной передачи в фоновом потоке) или запланировать JobService из получателя с помощью JobScheduler, поэтому система знает, что процесс продолжается выполнять активную работу.

И позже он уточняет, сколько времени вы на самом деле получаете:

Вызов goAsync() в методе вашего приемника OnReceive() и передавая BroadcastReceiver.PendingResult для фонового потока. Это позволяет сохранить активную трансляцию после возврата из onReceive(). Однако даже с таким подходом система ожидает, что вы быстро закончите широковещательную передачу (менее 10 секунд). Это позволяет вам переместить работу в другой поток, чтобы избежать смятия основной нити.

public class MyBroadcastReceiver extends BroadcastReceiver { 
    private static final String TAG = "MyBroadcastReceiver"; 

    @Override 
    public void onReceive(final Context context, final Intent intent) { 
     final PendingResult pendingResult = goAsync(); 
     AsyncTask<String, Integer, String> asyncTask = new AsyncTask<String, Integer, String>() { 
      @Override 
      protected String doInBackground(String... params) { 
       StringBuilder sb = new StringBuilder(); 
       sb.append("Action: " + intent.getAction() + "\n"); 
       sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n"); 
       Log.d(TAG, log); 
       // Must call finish() so the BroadcastReceiver can be recycled. 
       pendingResult.finish(); 
       return data; 
      } 
     }; 
     asyncTask.execute(); 
    } 
} 
Смежные вопросы