简体   繁体   English

从广播接收器android调用AsyncTask

[英]call AsyncTask from Broadcast receiver android

SO currently i have an AsyncTask class that runs and POST's data to my server when I click a button(which works great). 所以当前我有一个AsyncTask类,当我点击一个按钮时,它运行和POST的数据到我的服务器(效果很好)。

What im trying to do now is handle what happens when the user is not connected to the internet. 我现在尝试做的是处理用户未连接到互联网时发生的情况。 so i have set up these classes to notify the app when internet has connected so that the data can be sent automatically to the server. 所以我设置了这些类,以便在互联网连接时通知应用程序,以便数据可以自动发送到服务器。

AsyncTask class(inner class) 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 class 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 class 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
    }
}
}

So in the BroadcastReceiver class I check the flag that gets set to true when the app attempts to send data but there is not internet (onPostExecute in AsyncTask Class). 因此,在BroadcastReceiver类中,当应用程序尝试发送数据但没有Internet(AsyncTask类中的onPostExecute)时,我会检查设置为true的标志。

so what want to do is some how call the POST method. 所以想要做的是如何调用POST方法。 do i have to create a new Async task class? 我是否必须创建一个新的Async任务类? Im a bit stumped here . 我有点难过这里。

Thanks 谢谢

Using AsyncTask in BroadcastReceiver is a bad practice. BroadcastReceiver使用AsyncTask是一种不好的做法。

You should use Service because Android OS may kill your process or onReceive() may run to completion before asyncTask will return result, so there is no guarantee you will get the expected result. 您应该使用Service因为Android OS可能会终止您的进程,或者onReceive()可能会在asyncTask返回结果之前运行完成,因此无法保证您将获得预期的结果。

You shouldn't use AsyncTask in Broadcast Receiver because the system can kill your process after returning from onReceive method (if there is no any active service or activity). 您不应该在Broadcast Receiver中使用AsyncTask,因为系统可以在从onReceive方法返回后终止您的进程(如果没有任何活动服务或活动)。 Proof link 证明链接

Official documentation recommends IntentService for such cases (see paragraph about Broadcast Receivers). 官方文档建议针对此类情况使用 IntentService(请参阅有关广​​播接收器的段落)。

The other answers are not correct according to Google's documentation . 根据Google的文档 ,其他答案不正确。 The Broadcast Receivers developer guide explicitly calls out that you can use AsyncTask s from BroadcastReceiver s if you call goAsync() first and report the status to the pending result in the AsyncTask 该广播接收机开发人员指南明确要求的是,你可以使用AsyncTask期从BroadcastReceiver ■如果你调用goAsync()第一和状态报告给未决结果中AsyncTask

For this reason, you should not start long running background threads from a broadcast receiver. 因此,您不应该从广播接收器开始长时间运行后台线程。 After onReceive(), the system can kill the process at any time to reclaim memory, and in doing so, it terminates the spawned thread running in the process. 在onReceive()之后,系统可以随时终止进程以回收内存,并且这样做会终止在进程中运行的生成线程。 To avoid this, you should either call goAsync() (if you want a little more time to process the broadcast in a background thread) or schedule a JobService from the receiver using the JobScheduler, so the system knows that the process continues to perform active work. 要避免这种情况,您应该调用goAsync()(如果您希望在后台线程中处理广播更多时间)或使用JobScheduler从接收器调度JobService,以便系统知道该进程继续执行活动工作。

And later it clarifies how much time you actually get: 后来它澄清了你实际得到多少时间:

Calling goAsync() in your receiver's onReceive() method and passing the BroadcastReceiver.PendingResult to a background thread. 在接收者的onReceive()方法中调用goAsync()并将BroadcastReceiver.PendingResult传递给后台线程。 This keeps the broadcast active after returning from onReceive(). 这使得从onReceive()返回后广播保持活动状态。 However, even with this approach the system expects you to finish with the broadcast very quickly (under 10 seconds). 但是,即使采用这种方法,系统也希望您能够非常快速地完成广播(10秒以内)。 It does allow you to move work to another thread to avoid glitching the main thread. 它允许您将工作移动到另一个线程,以避免故障主线程。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM