Java 从广播接收器android调用AsyncTask

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21743800/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 10:26:53  来源:igfitidea点击:

call AsyncTask from Broadcast receiver android

javaandroidandroid-asynctaskbroadcastreceiver

提问by Chris Mowbray

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

广播接收器类

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 类中,我检查了当应用程序尝试发送数据但没有互联网时设置为 true 的标志(AsyncTask 类中的 onPostExecute)。

so what want to do is some how call the POST method. do i have to create a new Async task class? Im a bit stumped here .

所以想要做的是一些如何调用POST方法。我必须创建一个新的异步任务类吗?我有点难住这里。

Thanks

谢谢

回答by QuokMoon

Using AsyncTaskin BroadcastReceiveris a badpractice.

使用AsyncTaskinBroadcastReceiver是一种不好的做法。

You should use Servicebecause Android OS may kill your process or onReceive()may run to completion before asyncTaskwill return result, so there is no guarantee you will get the expected result.

您应该使用,Service因为 Android 操作系统可能会杀死您的进程或onReceive()可能会在asyncTask返回结果之前运行完成,因此无法保证您会得到预期的结果。

回答by renadeen

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). Proof link

您不应该在广播接收器中使用 AsyncTask,因为系统可以在从 onReceive 方法返回后终止您的进程(如果没有任何活动的服务或活动)。 证明链接

Official documentation recommendsIntentService for such cases (see paragraph about Broadcast Receivers).

官方文档建议在这种情况下使用IntentService(参见关于广播接收器的段落)。

回答by Hypothetical inthe Clavicle

The other answers are not correct according to Google's documentation. The Broadcast Receivers developer guide explicitly calls out that you can use AsyncTasks from BroadcastReceivers if you call goAsync()first and report the status to the pending result in the AsyncTask

根据 Google 的文档,其他答案不正确。该广播接收机开发人员指南明确要求了,您可以使用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. 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.

因此,您不应从广播接收器启动长时间运行的后台线程。在 onReceive() 之后,系统可以随时终止进程以回收内存,并在这样做时终止在进程中运行的衍生线程。为避免这种情况,您应该调用 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. This keeps the broadcast active after returning from onReceive(). However, even with this approach the system expects you to finish with the broadcast very quickly (under 10 seconds). It does allow you to move work to another thread to avoid glitching the main thread.

在接收器的 onReceive() 方法中调用 goAsync() 并将 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();
    }
}