我的服务将内存增加了50 MB,并且在我停止后没有减少

时间:2018-08-26 13:04:02

标签: android performance service

我有这项服务,可以将我的位置发送到服务器并从中获取一些数据。

 package com.speed00.service;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.widget.Toast;

import com.google.gson.Gson;
import com.speed00.R;
import com.speed00.constant.AppConstant;
import com.speed00.helper.FunctionHelper;
import com.speed00.model.achivment.StepHelper;
import com.speed00.model.ride.RideResultResponse;
import com.speed00.model.ride.UpdateLocationData;
import com.speed00.model.ride.UpdateLocationResponse;
import com.speed00.prefrences.MyPreferences;
import com.speed00.prefrences.MySharedPreference;
import com.speed00.retrofit.ApiUtils;
import com.speed00.stepdetucter.StepDetector;
import com.speed00.stepdetucter.StepListener;
import com.speed00.ui.activity.HomeActivity;
import com.speed00.utils.Logger;
import com.speed00.utils.MySensorEventListener;
import com.speed00.utils.NetworkConnection;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MyService extends Service implements StepListener, SensorEventListener {
    // constant
    // run on another Thread to avoid crash
    private Handler mHandler = new Handler();
    // timer handling
    private Timer mTimer = null;
    private Double locationRange = 1.0;
    private String oldDegree;
    private boolean isServiceRunning;
    private int numSteps = 0;
    private final int FINAL_STEP = 15;
    private SensorManager sensorManager;
    private Sensor accel;
    String speed_received = "0";
    private boolean pedoMetterHasStarted = false;

    String pLatitude;
    String pLongitude;

    private SensorEventListener eListener;

    private Sensor accelerometer, magFieldSensor;
    private StepDetector simpleStepDetector;

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

    private BroadcastReceiver message = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, final Intent intent) {
            // TODO Auto-generated method stub
            new Handler().post(new Runnable() {
                @Override
                public void run() {
                    speed_received = intent.getStringExtra("current speed");
                    Logger.e("speed__recv" + speed_received);
                    if (speed_received != null) {
                        //   setSpeedValue(speed_received);//this method is calling to set speed.
                        //This method is calling to validate Timer For Ride
                        if (speed_received.equalsIgnoreCase("0")) {
                            if (!pedoMetterHasStarted) {
                                numSteps = 0;
                                statPedoMeter();
                            }
                        }
                        //Calculating distance value
                        String latitude = MySharedPreference.getInstance(MyService.this).getLatitude();
                        String longitude = MySharedPreference.getInstance(MyService.this).getLongitude();
                        if (TextUtils.isEmpty(pLatitude)) {
                            pLatitude = latitude;
                            pLongitude = longitude;
                        } else {
                            /*
                             * if distance is more then 2 km then its calculatiog.
                             *
                             * */
                            Location pLocation = new Location("P");
                            pLocation.setLongitude(Double.parseDouble(pLatitude));
                            pLocation.setLongitude(Double.parseDouble(pLongitude));
                            Location nLocation = new Location("N");
                            nLocation.setLongitude(Double.parseDouble(latitude));
                            nLocation.setLongitude(Double.parseDouble(longitude));
                            Logger.e("distance----" + pLocation.distanceTo(nLocation));

                            if (pLocation.distanceTo(nLocation) >= 10) {
                                pLatitude = latitude;
                                pLongitude = longitude;
                            }
                        }
                    }
                }
            });
        }
    };

    @Override
    public void onCreate() {
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        eListener = new MySensorEventListener(this, sensorManager);//for direction
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        magFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

        //callback sensor of ui
        sensorManager.registerListener(eListener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
        sensorManager.registerListener(eListener, magFieldSensor, SensorManager.SENSOR_DELAY_NORMAL);

        assert sensorManager != null;
        accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        simpleStepDetector = new StepDetector();
        simpleStepDetector.registerListener(this);

        Toast.makeText(getApplicationContext(), "Service Started", Toast.LENGTH_SHORT).show();
        isServiceRunning = true;
//        Toast.makeText(getApplicationContext(), "service started", Toast.LENGTH_SHORT).show();
        // cancel if already existed
        if (mTimer != null) {
            mTimer.cancel();
        } else {
            // recreate new
            mTimer = new Timer();
        }
        // schedule task
//        new Timer().scheduleAtFixedRate(new TimeDisplayTimerTask(), 100, NOTIFY_INTERVAL);
        runLoop();

        LocalBroadcastManager.getInstance(this).registerReceiver(message,
                new IntentFilter("send"));

    }

    private void runLoop() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                updateDriverLocation();
                if (isServiceRunning)
                    runLoop();
            }
        }, 1000);
    }

    /*
     *
     * This method is calling to update driver location
     * */
    private void updateDriverLocation() {
        //Get all user details data.
        String userId = MySharedPreference.getInstance(getApplicationContext()).getDriverId();
        String latitudeData = MySharedPreference.getInstance(getApplicationContext()).getLatitude();
        String longitudeData = MySharedPreference.getInstance(getApplicationContext()).getLongitude();
        String speedData = MySharedPreference.getInstance(getApplicationContext()).getSpeedData();//how to roinf
        Logger.e("SERVER " + latitudeData + " " + longitudeData);
        Logger.e("SPEED   " + speedData);
        String directionValue = MySharedPreference.getInstance(getApplicationContext()).getDirectionValue();
        String speeding = MySharedPreference.getInstance(getApplicationContext()).getSpeeding();
        String language = MyPreferences.newInstance(getApplicationContext()).getLanguage();//send speeding data to bakend.
        String directionText = MySharedPreference.getInstance(getApplicationContext()).getDirectionText();
        long driveTime = FunctionHelper.getDifference(MySharedPreference.getInstance(getApplicationContext()).getStartTime());
        String validateUTurn = validateUTurn();

//        Logger.e("update_request--" + request);
        ApiUtils.getAPIService().updateDriverLocation(validateUTurn, directionText, speeding, "" + driveTime, language, userId,
                AppConstant.START_RIDE, speedData, directionValue, latitudeData, longitudeData).enqueue(new Callback<UpdateLocationResponse>() {
            @Override
            public void onResponse(Call<UpdateLocationResponse> call, Response<UpdateLocationResponse> response) {
                if (response.isSuccessful()) {
                    UpdateLocationResponse updateLocationResponse = response.body();
                    if (updateLocationResponse.getErrorCode().equalsIgnoreCase(AppConstant.ERROR_CODE)) {
                        if (updateLocationResponse.getData().size() > 0) {
                            UpdateLocationData updateLocationData = updateLocationResponse.getData().get(0);
                            String eventData = FunctionHelper.validateData(updateLocationData);
                            broadCastEventData(eventData, updateLocationResponse.getErrorCode());
                            broadCastResponseData(updateLocationResponse);
                        }
                    }
                }
            }

            @Override
            public void onFailure(Call<UpdateLocationResponse> call, Throwable t) {
            }
        });
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    /*
     *
     *This method is calling  to validateUTurn.
     *
     *
     * */
    private String validateUTurn() {
        String currentDegree = MySharedPreference.getInstance(this).getDirectionValue();
        String uTurnStatus = "0";
        if (TextUtils.isEmpty(oldDegree)) {
            oldDegree = currentDegree;
            uTurnStatus = "0";
            return uTurnStatus;
        } else {
            if (oldDegree == "0.0") {
                oldDegree = currentDegree;
            }
            if (Float.parseFloat(oldDegree) <= Float.parseFloat(currentDegree)) {
                uTurnStatus = "1";
            } else {
                uTurnStatus = "0";
            }
            if (Float.parseFloat(oldDegree) == 360 || Float.parseFloat(oldDegree) > 270) {
                if (Float.parseFloat(currentDegree) > 0 && Float.parseFloat(oldDegree) <= 90) {
                    uTurnStatus = "1";
                }
            }
            oldDegree = currentDegree;
            return uTurnStatus;
        }

    }

    public synchronized void broadCastEventData(String eventData, String errorCode) {
        Intent intent = new Intent("event_broad_cast");
        intent.putExtra("data", eventData);
        intent.putExtra("error", errorCode);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    /*
     * This method is calling to broadcast event data
     * */

    /*
     * This method is calling to broadcast event data
     * */
    public synchronized void broadCastResponseData(UpdateLocationResponse updateLocationData) {
        Intent intent = new Intent("location_update");
        Bundle args = new Bundle();
        args.putSerializable("data", (Serializable) updateLocationData);
        intent.putExtra("myvalue", args);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        isServiceRunning = false;

        LocalBroadcastManager.getInstance(this).unregisterReceiver(message);
        //  stopPedoMeter();
    }

    @Override
    public void step(long timeNs) {
        if (numSteps < 16)
            Toast.makeText(this, "" + numSteps, Toast.LENGTH_SHORT).show();
        saveStep();
        if (calculateSteps()) {
            stopRideAfter25step();
            stopPedoMeter();//this method is calling to stop ResultActivity
        } else if (Double.parseDouble(MySharedPreference.getInstance(this).getSpeedData()) > 10) {
            MySharedPreference.getInstance(this).setSteps(new ArrayList<StepHelper>());
            numSteps = 0;
        } else {
            Logger.e("stepsss " + numSteps);
            numSteps = numSteps + 1;
        }
    }

    private void stopRideAfter25step() {
        MySharedPreference.getInstance(this).setSteps(new ArrayList<StepHelper>());
        String speed = MySharedPreference.getInstance(this).getSpeedData();
        String direction = MySharedPreference.getInstance(this).getDirectionValue();
        String latitude = MySharedPreference.getInstance(this).getLatitude();
        String longitude = MySharedPreference.getInstance(this).getLongitude();
        String driverId = MySharedPreference.getInstance(this).getDriverId();
        String language = MyPreferences.newInstance(this).getLanguage();
        String speeding = MySharedPreference.getInstance(this).getSpeeding();
        long driveTime = FunctionHelper.getDifference(MySharedPreference.getInstance(this).getStartTime());
        //validate internet connection
        if (NetworkConnection.isConnection(this)) {
            stopRide("" + driveTime, language, speeding, driverId, latitude, longitude, AppConstant.STOP_RIDE, speed, direction);
        } else {
            Toast.makeText(this, getString(R.string.valid_please_check_network_connection), Toast.LENGTH_LONG).show();
        }
    }

    public void stopRide(final String driveTime, final String languageKey, final String speedLimit, final String driverId, final String latitude, final String longitude, String rideStatus, final String speed, final String direction) {
        String[] param = {driveTime, languageKey, speedLimit, driverId, speed, direction, latitude, longitude};
        new stopLoc(this).execute(param);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            simpleStepDetector.updateAccel(event.timestamp, event.values[0], event.values[1], event.values[2]);
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }

    private static class stopLoc extends AsyncTask<String[], Void, Void> {
        Context mContext;

        public stopLoc(Context mContext) {
            this.mContext = mContext;
        }

        @Override
        protected Void doInBackground(String[]... strings) {
            Logger.e("stepsss stopingggg");
            String driveTime = strings[0][0];
            String languageKey = strings[0][1];
            String speedLimit = strings[0][2];
            String driverId = strings[0][3];
            String speed = strings[0][4];
            String direction = strings[0][5];
            String latitude = strings[0][6];
            String longitude = strings[0][7];

            ApiUtils.getAPIService().stopTrip(driveTime, languageKey, speedLimit, driverId, AppConstant.STOP_RIDE, speed, direction, latitude, longitude).enqueue(new Callback<RideResultResponse>() {
                @Override
                public void onResponse(Call<RideResultResponse> call, Response<RideResultResponse> response) {
                    Logger.e("response----" + new Gson().toJson(response.body()));
                    if (response.isSuccessful()) {
                        String errorCode = response.body().getErrorCode();
                        if (errorCode.equalsIgnoreCase(AppConstant.ERROR_CODE)) {
                            tripSuccessData(response.body(), mContext);
                        } else {
                            Toast.makeText(mContext, "" + mContext.getString(R.string.text_some_erroroccurs), Toast.LENGTH_SHORT).show();
                        }
                    }
                }

                @Override
                public void onFailure(Call<RideResultResponse> call, Throwable t) {
                    Toast.makeText(mContext, t.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
            return null;
        }
    }

    public static void tripSuccessData(Object data, Context context) {
        RideResultResponse resultResponse = (RideResultResponse) data;
        if (resultResponse.getErrorCode().equalsIgnoreCase(AppConstant.ERROR_CODE)) {
            FunctionHelper.enableUserIntraction();
            HomeActivity.bSpeedStatus = false;
            Intent intent = new Intent("trip_ended");
            intent.putExtra("trip_info", resultResponse.getData().get(0));
            LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
            ((MyService) context).stopSelf();
        } else {
            Toast.makeText(context, resultResponse.getErrorMsg(), Toast.LENGTH_SHORT).show();
        }
    }


    private boolean calculateSteps() {
        ArrayList<StepHelper> arrayList = MySharedPreference.getInstance(this).getSteps();
        ArrayList<StepHelper> newList = new ArrayList<>();
        for (int i = 0; i < arrayList.size(); i++) {
            long seconds = FunctionHelper.getDifference(arrayList.get(i).getTime());
            if ((int) seconds < 180) {
                newList.add(arrayList.get(i));
            }
        }
        if (numSteps - newList.get(0).getSteps() >= FINAL_STEP) {
            return true;
        } else {
            MySharedPreference.getInstance(this).setSteps(newList);
            return false;
        }
    }

    private void saveStep() {
        ArrayList<StepHelper> arrayList = MySharedPreference.getInstance(this).getSteps();
        if (arrayList == null) {
            arrayList = new ArrayList<>();
        }
        arrayList.add(new StepHelper(FunctionHelper.getCurrentDateWitTime(), numSteps));
        MySharedPreference.getInstance(this).setSteps(arrayList);
    }

    private void statPedoMeter() {
//        Toast.makeText(this, "start count", Toast.LENGTH_SHORT).show();
        pedoMetterHasStarted = true;
        MySharedPreference.getInstance(this).setStartPedoMeterTime(FunctionHelper.getCurrentDateWitTime());//store current  time
        if (sensorManager != null)
            sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_NORMAL);
    }

    /*
     * This method is calling to stop pedo meter
     *
     * */
    private void stopPedoMeter() {
        numSteps = 0;
        pedoMetterHasStarted = false;
        sensorManager.unregisterListener(this, accelerometer);
        sensorManager.unregisterListener(this, accel);
        sensorManager.unregisterListener(this, magFieldSensor);
        sensorManager = null;

    }


    class TimeDisplayTimerTask extends TimerTask {

        @Override
        public void run() {
            // run on another thread
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    Logger.e("MyService --- " + "isRuning");
                    if (HomeActivity.bSpeedStatus) {
                        updateDriverLocation();
                    }
                }
            });
        }

    }


}

我的应用程序启动并仅使用170 MB,但启动此服务后,它变为220 MB,完成后仍为220,如果我再次打开它,则ram变为240,如果我完成它仍为240,如果我再次打开它变成260,依此类推,直到应用崩溃 服务有什么问题? 我确保它已停止,但不知道为什么在完成此服务后不减少ram

1 个答案:

答案 0 :(得分:0)

尝试这种方法,不要将stopSelf()放在静态方法中。相反,您应该再次调用startService并将操作添加到Intent

这就是示例可操作服务的外观:

public class ExampleService
    extends Service {

  public static final String START_SERVICE_ACTION = "com.example.action.START_SERVICE";

  public static final String STOP_SERVICE_ACTION = "com.example.action.STOP_SERVICE";

  @Override
  public void onCreate() {
    super.onCreate();
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    String intentAction = intent.getAction();
    switch (intentAction) {
        case START_SERVICE_ACTION:
            //
            break;
        case STOP_SERVICE_ACTION:
            stopSelf();
            break;
    }
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
  }

  @Override
  public IBinder onBind(Intent intent) {
    // Used only in case if services are bound (Bound Services).
    return null;
  }
}

Service在某处进行交互:

像这样开始:

Intent service = new Intent(context, ExampleService.class);
service.setAction(NotificationService.START_SERVICE_ACTION);
startService(service);

像这样停止它:

Intent service = new Intent(context, ExampleService.class);
service.setAction(NotificationService.STOP_SERVICE_ACTION);
startService(service);
  • 在此示例中,您实际上不需要传递START_SERVICE_ACTION,只需添加它即可更好地理解设计。