0

我的应用程序将数据发送到服务器。在用户处于信号不良区域之前,它通常可以正常工作。如果用户处于信号良好的区域,则以下代码可以正常工作并发送数据。

String[] params = new String[]{compID, tagId, tagClientId, carerID,
                formattedTagScanTime, formattedNowTime, statusForWbService, getDeviceName(), tagLatitude, tagLongitude}; 
        AsyncPostData apd = new AsyncPostData();

            apd.execute(params);

.

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

        ProgressDialog progressDialog;
        String dateTimeScanned;

        @Override
        protected void onPreExecute()
        {


           // progressDialog= ProgressDialog.show(NfcscannerActivity.this, 
                //  "Connecting to Server"," Posting data...", true); 

            int buildVersionSdk = Build.VERSION.SDK_INT;
            int buildVersionCodes = Build.VERSION_CODES.GINGERBREAD;

            Log.e(TAG, "buildVersionSdk = " + buildVersionSdk 
                    + "buildVersionCodes = " + buildVersionCodes);

            int themeVersion;
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD) {

                 themeVersion = 2;

            }else{

                 themeVersion = 1;
            }

            progressDialog = new ProgressDialog(NfcscannerActivity.this, themeVersion);
            progressDialog.setTitle("Connecting to Server");
            progressDialog.setMessage(" Sending data to server...");
            progressDialog.setIndeterminate(true);

            try{
            progressDialog.show();
            }catch(Exception e){

                //ignore
            }
        };  


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

            Log.e(TAG, "carerid in doinbackground = " + params[3] + " dateTimeScanned in AsyncPost for the duplecate TX = " + params[4]);

            dateTimeScanned = params[4];

            return nfcscannerapplication.loginWebservice.postData(params[0], params[1], params[2], params[3], params[4],
                    params[5], params[6], params[7] + getVersionName(), params[8], params[9]);

        }

         @Override
            protected void onPostExecute(String result)
            {
             super.onPostExecute(result);

                try{
                progressDialog.dismiss();
                }catch(Exception e){
                    //ignore
                }

                if( result != null && result.trim().equalsIgnoreCase("OK")  ){

                    Log.e(TAG, "about to update DB with servertime");
                    DateTime sentToServerAt = new DateTime();
                    nfcscannerapplication.loginValidate.updateTransactionWithServerTime(sentToServerAt,null);
                    nfcscannerapplication.loginValidate.insertIntoDuplicateTransactions(dateTimeScanned);

                    tagId = null;
                    tagType = null;
                    tagClientId = null;

                    //called to refresh the unsent transactions textview
                    onResume();

                }else if(result != null && result.trim().equalsIgnoreCase("Error: TX duplicated")){
                    Log.e(TAG, "response from server is Duplicate Transaction ");


                    //NB. the following time may not correspond exactly with the time on the server
                    //because this TX has already been processed but the 'OK' never reached the phone,
                    //so we are just going to update the phone's DB with the DupTX time so the phone doesn't keep 
                    //sending it.

                    DateTime sentToServerTimeWhenDupTX = new DateTime();
                    nfcscannerapplication.loginValidate.updateTransactionWithServerTime(sentToServerTimeWhenDupTX,null);

                    tagId = null;
                    tagType = null;
                    tagClientId = null;



                }else{

                    Toast.makeText(NfcscannerActivity.this,
                            "No phone signal or server problem",
                            Toast.LENGTH_LONG).show();
                }
            }

    }//end of AsyncPostData 

.

信号不良区域的应用程序往往会显示进度条几分钟,然后再显示一段时间的黑屏,从而使应用程序无法使用。

我认为解决此问题的方法是执行以下操作。

String[] params = new String[]{compID, tagId, tagClientId, carerID,
                formattedTagScanTime, formattedNowTime, statusForWbService, getDeviceName(), tagLatitude, tagLongitude}; 
        AsyncPostData apd = new AsyncPostData();
        try {
            apd.execute(params).get(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TimeoutException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

这将导致 AsyncTask 在 10 秒后取消,但在执行时会出现黑屏,直到发送数据,然后是进度条几毫秒。

有没有办法在执行 AsyncTask.get() 时显示进度条?

提前致谢。马特。

还有什么想法为什么当用户处于不良信号区域时会出现黑屏,因此服务器没有响应。这个 senario 似乎会导致应用程序出现很多问题,因为它的行为是不寻常的,例如在以后发送额外的交易。

[编辑1]

public class SignalService extends Service{

    NfcScannerApplication nfcScannerApplication;
    TelephonyManager SignalManager;
    PhoneStateListener signalListener;
    private static final int LISTEN_NONE = 0;
    private static final String TAG = SignalService.class.getSimpleName();


    @Override
    public void onCreate() {
        super.onCreate();
        // TODO Auto-generated method stub
        Log.e(TAG, "SignalService created");
        nfcScannerApplication = (NfcScannerApplication) getApplication();
        signalListener = new PhoneStateListener() {
            public void onSignalStrengthChanged(int asu) {
                //Log.e("onSignalStrengthChanged: " , "Signal strength = "+ asu);
                nfcScannerApplication.setSignalStrength(asu);

            }
        };

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // TODO Auto-generated method stub
        Log.e(TAG, "SignalService destroyed");
        SignalManager.listen(signalListener, LISTEN_NONE);

    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        // TODO Auto-generated method stub
        Log.e(TAG, "SignalService in onStart");

         SignalManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
         SignalManager.listen(signalListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTH);

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

}
4

1 回答 1

0

您根本不需要计时器来做您正在尝试的事情(出于某种原因,我认为您正在尝试AsyncTask根据您上面的评论循环,这导致了我的结果。)。如果我理解正确,您的问题是失去服务。您有一个AsyncTask开始,根据某些条件可能会或可能不会结束。您的方法是使用 get 并在固定时间后取消任务,以防它在此之前没有完成执行 - 假设如果任务没有在 10 秒的截止时间内完成,则服务丢失。

解决此问题的更好方法是使用布尔标志,指示网络连接是否可用,然后在服务丢失时停止执行任务。这是我从这篇文章中获取的一个示例(我为我在一台蹩脚的计算机上使用的格式表示歉意 - 最重要的是 - IE8 - 所以我看不到代码的样子)。

public class MyTask extends AsyncTask<Void, Void, Void> {

private volatile boolean running = true;
private final ProgressDialog progressDialog;

public MyTask(Context ctx) {
    progressDialog = gimmeOne(ctx);

    progressDialog.setCancelable(true);
    progressDialog.setOnCancelListener(new OnCancelListener() {
        @Override
        public void onCancel(DialogInterface dialog) {
            // actually could set running = false; right here, but I'll
            // stick to contract.
            cancel(true);
        }
    });

}

@Override
protected void onPreExecute() {
    progressDialog.show();
}

@Override
protected void onCancelled() {
    running = false;
}

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

    while (running) {
        // does the hard work
    }
    return null;
}

// ...

} 

此示例使用一个进度对话框,允许用户通过按下按钮来取消任务。您不会这样做,而是要检查网络连接并根据您的任务是否连接到互联网来设置运行布尔值。如果连接丢失 - running 将设置为 false,这将触发 while 循环并停止任务。

至于任务完成后的工作。你永远不应该使用 get。要么(1)将所有需要在 doInBackgroundCompletes 之后完成的事情放在 onPostExecute 中(假设它不是太多),要么(2)如果您需要将数据返回到起始活动,请使用接口。您可以通过将作为参数添加到任务构造函数或使用设置接口的单独方法来添加接口。例如

public void setInterface(OnTaskComplete listener){
    this.listener = listener;
}

其中 OnTaskComplete 侦听器在AsyncTask. 请注意,我所描述的方法需要使用单独的AsyncTask类。你的现在是私有的,这意味着你需要稍微改变你的项目。

更新

要检查连接性,我会使用这样的东西。

public boolean isNetworkOnline() {
boolean status=false;
try{
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getNetworkInfo(0);
    if (netInfo != null && netInfo.getState()==NetworkInfo.State.CONNECTED) {
        status= true;
    }else {
        netInfo = cm.getNetworkInfo(1);
        if(netInfo!=null && netInfo.getState()==NetworkInfo.State.CONNECTED)
            status= true;
    }
}catch(Exception e){
    e.printStackTrace();  
    return false;
}
return status;

}  

您可以检查是否有实际的网络连接,您的应用程序可以通过该网络连接到服务器。此方法不必是公开的,并且可以成为您AsyncTask班级的一部分。就我个人而言,我在一个网络管理器类中使用了类似的东西来检查各种网络统计信息(其中之一是我可以连接到互联网)。

在 doInBackground 方法中开始执行循环之前,您将检查连接性,然后您可以在该方法的整个过程中定期更新。如果 netowkr 可用,任务将继续。如果没有,它将停止。

调用AsyncTask内置的 cancle 方法是不够的,因为它只会阻止 onPostExecute 运行。它实际上并没有阻止代码执行。

于 2013-07-18T14:12:39.393 回答