在后台服务中启动密集POST以获得崩溃

时间:2017-12-21 08:12:53

标签: java android

因此,有一个背景服务,一旦GPS 位置发生变化,就会创建可运行对象。 Runnable包含HTTPConnection以进行POST,并通过sendBroadcast()两次发送广播消息。

因此,如果没有机会通过此方案发送数据,我遇到的问题就会发生,应用程序就会崩溃。

重新构建代码的任何线索,或者当新的TaskAsync准备就绪时,可能会更改TaskAsync取消待处理 TaskAsync的方法吗?

有任何线索吗?

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.text.format.DateFormat;
import android.util.Log;

import com.google.gson.Gson;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;


public class gps_service2 extends Service {
    private static final String TAG = "GPS SERVICE";
    private LocationManager mLocationManager = null;
    private static final int LOCATION_INTERVAL = 10000;
    private static final float LOCATION_DISTANCE = 10f;
    Context context;

    private class LocationListener implements android.location.LocationListener
    {
        Location mLastLocation;

        public LocationListener(String provider)
        {
            Log.e(TAG, "LocationListener " + provider);
            mLastLocation = new Location(provider);
        }

        @Override
        public void onLocationChanged(Location location)
        {
            Log.e(TAG, "onLocationChanged: " + location);

            try
            {
                ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(context, "App_Settings", 0);
                AppSettings appSettings = complexPreferences.getObject("App_Settings", AppSettings.class);
                if (appSettings != null) {

                    LocationItem locationItem = new LocationItem();
                    locationItem.DeviceID = appSettings.getDeviceID();
                    locationItem.Latitude =  Double.toString(location.getLatitude());
                    locationItem.Longitude = Double.toString(location.getLongitude());
                    Date d = new Date();
                    CharSequence timeOfRequest = DateFormat.format("yyyy-MM-dd HH:mm:ss", d.getTime()); // YYYY-MM-DD HH:mm:ss
                    locationItem.TimeOfRequest = timeOfRequest.toString();
                    locationItem.SerialNumber = appSettings.getSerialNumber();


                    Gson gson = new Gson();
                    String requestObject = gson.toJson(locationItem);
                    String url = appSettings.getIpAddress() + "/api/staff/savedata";
                    makeRequest(url, requestObject, dLocation);
                }
            }
            catch (Exception ex)
            {                
            } 
        }

        @Override
        public void onProviderDisabled(String provider)
        {
            Log.e(TAG, "onProviderDisabled: " + provider);
        }

        @Override
        public void onProviderEnabled(String provider)
        {
            Log.e(TAG, "onProviderEnabled: " + provider);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras)
        {
            Log.e(TAG, "onStatusChanged: " + provider);
        }
    }

    LocationListener[] mLocationListeners = new LocationListener[] {
            new LocationListener(LocationManager.GPS_PROVIDER),
            new LocationListener(LocationManager.NETWORK_PROVIDER)
    };

    @Override
    public IBinder onBind(Intent arg0)
    {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.e(TAG, "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    @Override
    public void onCreate()
    {
        context = this;
        Log.e(TAG, "onCreate");
        initializeLocationManager();
        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                    mLocationListeners[1]);
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "network provider does not exist, " + ex.getMessage());
        }
        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                    mLocationListeners[0]);
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "gps provider does not exist " + ex.getMessage());
        }
    }

    @Override
    public void onDestroy()
    {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
        if (mLocationManager != null) {
            for (int i = 0; i < mLocationListeners.length; i++) {
                try {
                    mLocationManager.removeUpdates(mLocationListeners[i]);
                } catch (Exception ex) {
                    Log.i(TAG, "fail to remove location listners, ignore", ex);
                }
            }
        }
    }

    private void initializeLocationManager() {
        Log.e(TAG, "initializeLocationManager");
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        }
    }

    public static double round(double value, int places) {
        if (places < 0) throw new IllegalArgumentException();
        BigDecimal bd = new BigDecimal(value);
        bd = bd.setScale(places, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }

    public void makeRequest(String uri, String json, DLocation dLocation) {

        HandlerThread handlerThread = new HandlerThread("URLConnection");
        handlerThread.start();
        Handler mainHandler = new Handler(handlerThread.getLooper());
        Runnable myRunnable = createRunnable(uri, json, dLocation);
        mainHandler.post(myRunnable);
    }

    private Runnable createRunnable(final String uri, final String data,final DLocation dLocation){

        Runnable aRunnable = new Runnable(){
            public void run(){
                try {
                    //Connect
                    HttpURLConnection urlConnection;
                    urlConnection = (HttpURLConnection) ((new URL(uri).openConnection()));
                    urlConnection.setDoOutput(true);
                    urlConnection.setRequestProperty("Content-Type", "application/json");
                    urlConnection.setRequestProperty("Accept", "application/json");
                    urlConnection.setRequestMethod("POST");
                    urlConnection.connect();

                    //Write
                    OutputStream outputStream = urlConnection.getOutputStream();
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
                    try {
                        writer.write(data);
                    } catch (IOException e) {
                        e.printStackTrace();
                        Log.d(TAG,"Ошибка записи в буфер для пережачи по HTTP");
                    }
                    writer.close();
                    outputStream.close();

                    //Read
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));

                    String line = null;
                    StringBuilder sb = new StringBuilder();

                    while ((line = bufferedReader.readLine()) != null) {
                        sb.append(line);
                    }

                    bufferedReader.close();
                    String result = sb.toString();

                    Log.d(TAG, result);

                    Intent iResult = new Intent("location_update");

                    DLocation dLocation = new DLocation();                    
                    iResult.putExtra("result", dLocation);
                    sendBroadcast(iResult);                   

                }catch( Exception err){
                    err.printStackTrace();
                    Log.d(TAG, "HTTP " + err.getMessage());
                }
            }
        };

        return aRunnable;
    }
}

2 个答案:

答案 0 :(得分:5)

Runnable只是一个接口,当你使用Runnable接口创建一个线程时,它基本上会在它创建的线程下运行,在这里运行与UI线程的关联,根据谷歌文档网络调用必须在工作线程中在UI线程中。

那么为什么它在模拟器上运行
android有DVM(dalvik虚拟机),它的工作方式与JVM类似,但不是.class文件,DVM使用.dex扩展名,因此设备可能有较旧或较新版本的DVM。

<强>修正
使用android的AsyncTask进行网络调用。 android(DVM)与JVM相比资源有限,说到线程,所以最好使用AsyncTask

check this answer too

用于将JSON传递给服务器的AsyncTask代码,并以回调方式响应

public class WebService extends AsyncTask<String,String,String> {
private static final String TAG="SyncToServerTAG";




private String urlString;
private JSONObject jsonObject=null;
private int screenId=1;

public WebService(String url) {
    this.urlString=url;
}

public WebService(Context context, String url, JSONObject jsonObject) {
    this.urlString = url;
    this.jsonObject = jsonObject;
}

@Override
protected String doInBackground(String... strings) {
    try {
        URL url = new URL(urlString);
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setChunkedStreamingMode(0);
        urlConnection.setConnectTimeout(5000);
        urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        urlConnection.setDoOutput(true);
        urlConnection.setDoInput(true);
        urlConnection.setRequestMethod("POST");
        if(jsonObject!=null) {
            OutputStream os = urlConnection.getOutputStream();
            os.write(jsonObject.toString().getBytes("UTF-8"));
        }

        InputStream in = new BufferedInputStream(urlConnection.getInputStream());
        BufferedReader br = new BufferedReader(new InputStreamReader(
                (urlConnection.getInputStream())));

        String output="";
        while (true) {
            String line=br.readLine();
                Log.d(TAG,line+" ");
            if(line!=null)
                output+=line;
            else
                break;
        }

        in.close();
        urlConnection.disconnect();
        JSONObject j;
        if(output.equals(""))
            publishProgress("Server give null");
        else {
            j=new JSONObject(output);
            return output;
        }
        return output;
    } catch (MalformedURLException e) {
        e.printStackTrace();
        publishProgress(e.toString());
    } catch (IOException e) {
        e.printStackTrace();
        publishProgress(e.toString());
    } catch (JSONException e) {
        e.printStackTrace();
        publishProgress(e.toString());
    }
    return null;
}

@Override
protected void onProgressUpdate(String... values) {
    super.onProgressUpdate(values);
    fireError(values[0]);
}

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    if(s!=null) {
        try {
            JSONObject jsonObject=new JSONObject(s);
            fireComplete(0, jsonObject);
        } catch (JSONException e) {
            e.printStackTrace();
            fireError("Non acceptable responds from server ["+urlString+"]");
        }
    }
}

public interface OnWebCompleteListener{
    void onComplete(JSONObject result, int dataSource);
    void onError(String error);
}
private OnWebCompleteListener onWebCompleteListener;
private void fireComplete(int sourse,JSONObject cache){
    if(onWebCompleteListener!=null)
        onWebCompleteListener.onComplete(cache,sourse);
}
private void fireError(String message){
    if(onWebCompleteListener!=null)
        onWebCompleteListener.onError(message);
}
public void start(OnWebCompleteListener onWebCompleteListener){
    if(onWebCompleteListener==null)
        throw new RuntimeException("You must provide non-null value as start listener");
    this.onWebCompleteListener=onWebCompleteListener;
    execute((String)null);
}

}

<强>用法

    WebService webService=new WebService(context,"url",jsonObject);
    webService.start(new WebService.OnWebCompleteListener() {
    @Override
    public void onComplete(JSONObject result, int dataSource) {

    }

    @Override
    public void onError(String error) {

    }
    });

答案 1 :(得分:1)

您的代码非常容易受到攻击。我认为你崩溃是因为你的makeRequest方法退出之前你Runnable有机会完成任务。 您在发送资源后立即关闭资源,从而释放系统资源。 你第二次打电话给广播,资源不再存在导致崩溃....