GPS работает нормально, но не работает, когда идет в фоновом режиме - PullRequest
0 голосов
/ 27 апреля 2019

Я разработчик Android и теперь я более свежий.Я работаю над проектом, который используется для отправки местоположения на сервер через x минут, и я использую Volly для отправки запроса.Когда я нажимаю на кнопку «A», вызывая метод с именем «locationService ()», он работает нормально, отправляет текущее местоположение и никаких проблем или ошибок не возникает, но когда я нажимаю на кнопку «B», это показывает мне это ...

NetworkDispatcher.processRequest: Unhandled exception java.lang.NullPointerException: Attempt to read from field 'double com.example.GPSTracker.latitude' on a null object reference
java.lang.NullPointerException: Attempt to read from field 'double com.example.GPSTracker.latitude' on a null object reference

Когда я нажимаю на кнопку «B», служба Android запускается в фоновом режиме в течение x минут, а в службе я вызываю тот же метод locationService (), теперь этот метод показывает ошибку, может »не понимаю, что со мной не так.Я много искал, но ничего не смог найти.

Я делюсь своим кодом, это мой первый вопрос.Надеюсь, я получу лучшее.

в текущем:

       LocalBroadcastManager.getInstance(this).registerReceiver(
            mMessageReceiver, new IntentFilter("GPSLocationUpdates"));

это другие методы:

  private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String Latitude = intent.getStringExtra("Latitude");
        String Longitude = intent.getStringExtra("Longitude");

        Location mLocation = new Location("");
        mLocation.setLatitude(Double.parseDouble(Latitude));
        mLocation.setLongitude(Double.parseDouble(Longitude));

        locationService(mLocation);

    }
};

  public void locationService(final Location mLocation) {

    String url
            = "http://something/";

    StringRequest jsonRequest = new StringRequest
            (Request.Method.POST, url, new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    try {
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                }
            }) {
        @Override
        public byte[] getBody() {
            HashMap<String, String> params2 = new HashMap<String, String>();
            double latitude;
            double longitude;
            // check if GPS enabled

            if (mLocation != null) {

                System.out.println("LatLong" + mLocation.getLatitude() + mLocation.getLongitude());

                latitude = mLocation.getLatitude();
                longitude = mLocation.getLongitude();
                params2.put("longitude", String.valueOf(longitude));
                params2.put("latitude", String.valueOf(latitude));
                params2.put("vehicle_no", vehicle);
                params2.put("driver_phno", mobile);
                return new JSONObject(params2).toString().getBytes();
            }
            return null;
        }

        @Override
        public String getBodyContentType() {
            return "application/json";
        }
    };
    AppController.getInstance().addToRequestQueue(jsonRequest);

}

Это нажатие кнопки, которая вызывает службу:

  public void b(View view){
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        ContextCompat.startForegroundService(DashboardActivity.this, new Intent(DashboardActivity.this, ServiceLocation.class));
    } else {
        startService(new Intent(DashboardActivity.this, ServiceLocation.class));
    }
   }

Это услуга:

  public class ServiceLocation extends Service implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener {

private static final String NOTIFICATION_CHANNEL_ID = "my_notification_location";
private static final long TIME_INTERVAL_GET_LOCATION = 1000 * 5; // 1 Minute
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 7; // meters

private Handler handlerSendLocation;
private Context mContext;

private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;

private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 5000;

Location locationData;

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

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();

    // Create the LocationRequest object
    mLocationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(TIME_INTERVAL_GET_LOCATION)    // 3 seconds, in milliseconds
            .setFastestInterval(TIME_INTERVAL_GET_LOCATION); // 1 second, in milliseconds

    mContext = this;


    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
            .setOngoing(false)
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setColor(getResources().getColor(R.color.colorPrimary))
            .setPriority(Notification.PRIORITY_MIN);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
        notificationChannel.setDescription(NOTIFICATION_CHANNEL_ID);
        notificationChannel.setSound(null, null);
        notificationManager.createNotificationChannel(notificationChannel);
        startForeground(1, builder.build());
    }
}

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

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    Log.w("Service Update Location", "BGS > Started");

    if (handlerSendLocation == null) {
        handlerSendLocation = new Handler();
        handlerSendLocation.post(runnableSendLocation);
        Log.w("Service Send Location", "BGS > handlerSendLocation Initialized");
    } else {
        Log.w("Service Send Location", "BGS > handlerSendLocation Already Initialized");
    }

    return START_STICKY;
}

private Runnable runnableSendLocation = new Runnable() {

    @Override
    public void run() {


        // You can get Location
        //locationData and Send Location X Minutes

        Intent intent = new Intent("GPSLocationUpdates");
        intent.putExtra("Latitude", ""+ locationData.getLatitude());
        intent.putExtra("Longitude", "" + locationData.getLongitude());
        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);

        Log.w("==>UpdateLocation<==", "" + String.format("%.6f", locationData.getLatitude()) + "," +
                String.format("%.6f", locationData.getLongitude()));

        Log.w("Service Send Location", "BGS >> Location Updated");

        if (handlerSendLocation != null && runnableSendLocation != null)
            handlerSendLocation.postDelayed(runnableSendLocation, TIME_INTERVAL_GET_LOCATION);
    }
};



@Override
public void onConnected(@Nullable Bundle bundle) {
    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

        return;
    }

    FusedLocationProviderClient mFusedLocationClient  = LocationServices.getFusedLocationProviderClient(this);
    mFusedLocationClient.requestLocationUpdates(mLocationRequest,new LocationCallback(){
        @Override
        public void onLocationResult(LocationResult locationResult) {
            locationData = locationResult.getLastLocation();
        }
    },null);
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    if (connectionResult.hasResolution() && mContext instanceof Activity) {
        try {
            Activity activity = (Activity) mContext;
            connectionResult.startResolutionForResult(activity, CONNECTION_FAILURE_RESOLUTION_REQUEST);
        } catch (Exception e) {
            e.printStackTrace();
        }
    } else {
        Log.i("", "Location services connection failed with code " + connectionResult.getErrorCode());
    }
}

@Override
public void onLocationChanged(Location location) {
    Log.w("==>UpdateLocation<==", "" + String.format("%.6f", location.getLatitude()) + "," + String.format("%.6f", location.getLongitude()));
    locationData = location;

}

@Override
public void onDestroy() {

    if (handlerSendLocation != null)
        handlerSendLocation.removeCallbacks(runnableSendLocation);


    Log.w("Service Update Info", "BGS > Stopped");

    stopSelf();
    super.onDestroy();
}

}

Это проявление:

 <uses-permission
    android:name="android.permission.ACCESS_COARSE_LOCATION"
    android:maxSdkVersion="22" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>

<application
    android:name=".AppController"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
<service
        android:name=".MyLocatioService"
        android:enabled="true" />
    <receiver android:name=".BootCompletedIntentReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
</application>

1 Ответ

0 голосов
/ 27 апреля 2019

Пожалуйста, используйте эту услугу:

Gradle

implementation 'com.google.android.gms:play-services:12.0.1'
implementation 'gun0912.ted:tedpermission:2.1.0'

onCreate In Activity Class

TedPermission.with(getActivity())
                .setPermissionListener(permissionlistener)
                .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
                .setPermissions(Manifest.permission.ACCESS_FINE_LOCATION)
                .check();

LocalBroadcastManager.getInstance(this).registerReceiver(
                mMessageReceiver, new IntentFilter("GPSLocationUpdates"));


PermissionListener permissionlistener = new PermissionListener() {
        @Override
        public void onPermissionGranted() {

        }

        @Override
        public void onPermissionDenied(ArrayList<String> deniedPermissions) {
        }
    };

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String Latitude = intent.getStringExtra("Latitude");
            String Longitude = intent.getStringExtra("Longitude");

            Location mLocation = new Location("");
            mLocation.setLatitude(Double.parseDouble(Latitude));
            mLocation.setLongitude(Double.parseDouble(Longitude));

            locationService(mLocation);

        }
    };


public void locationService(final Location mLocation)) {

        String url
                = "http://something/";

        StringRequest jsonRequest = new StringRequest
                (Request.Method.POST, url, new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        try {
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                    }
                }) {
            @Override
            public byte[] getBody() {
                HashMap<String, String> params2 = new HashMap<String, String>();
                double latitude;
                double longitude;
                // check if GPS enabled

                if (mLocation != null) {

                    System.out.println("LatLong" + mLocation.getLatitude() + mLocation.getLongitude());

                    latitude = mLocation.getLatitude();
                    longitude = mLocation.getLongitude();
                    params2.put("longitude", String.valueOf(longitude));
                    params2.put("latitude", String.valueOf(latitude));
                    params2.put("vehicle_no", vehicle);
                    params2.put("driver_phno", mobile);
                    return new JSONObject(params2).toString().getBytes();
                }
                return null;
            }

            @Override
            public String getBodyContentType() {
                return "application/json";
            }
        };
        AppController.getInstance().addToRequestQueue(jsonRequest);

    }

Запуск службы

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
     ContextCompat.startForegroundService(MainActivity.this, new Intent(MainActivity.this, ServiceLocation.class));
 } else {
     startService(new Intent(MainActivity.this, ServiceLocation.class));
 }

Класс обслуживания

public class ServiceLocation extends Service implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener {

    private static final String NOTIFICATION_CHANNEL_ID = "my_notification_location";
    private static final long TIME_INTERVAL_GET_LOCATION = 1000 * 5; // 1 Minute
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 7; // meters

    private Handler handlerSendLocation;
    private Context mContext;

    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;

    private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 5000;

    Location locationData;

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

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        // Create the LocationRequest object
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(TIME_INTERVAL_GET_LOCATION)    // 3 seconds, in milliseconds
                .setFastestInterval(TIME_INTERVAL_GET_LOCATION); // 1 second, in milliseconds

        mContext = this;


        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setOngoing(false)
                .setSmallIcon(R.drawable.ic_notification)
                .setColor(getResources().getColor(R.color.fontColorDarkGray))
                .setPriority(Notification.PRIORITY_MIN);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                    NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
            notificationChannel.setDescription(NOTIFICATION_CHANNEL_ID);
            notificationChannel.setSound(null, null);
            notificationManager.createNotificationChannel(notificationChannel);
            startForeground(1, builder.build());
        }
    }

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Log.w("Service Update Location", "BGS > Started");

        if (handlerSendLocation == null) {
            handlerSendLocation = new Handler();
            handlerSendLocation.post(runnableSendLocation);
            Log.w("Service Send Location", "BGS > handlerSendLocation Initialized");
        } else {
            Log.w("Service Send Location", "BGS > handlerSendLocation Already Initialized");
        }

        return START_STICKY;
    }

    private Runnable runnableSendLocation = new Runnable() {

        @Override
        public void run() {


            // You can get Location
            //locationData and Send Location X Minutes
            if (locationData != null) {
                Intent intent = new Intent("GPSLocationUpdates");
                intent.putExtra("Latitude", "" + locationData.getLatitude());
                intent.putExtra("Longitude", "" + locationData.getLongitude());


                LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);

                Log.w("==>UpdateLocation<==", "" + String.format("%.6f", locationData.getLatitude()) + "," +
                        String.format("%.6f", locationData.getLongitude()));

                Log.w("Service Send Location", "BGS >> Location Updated");
            }
            if (handlerSendLocation != null && runnableSendLocation != null)
                handlerSendLocation.postDelayed(runnableSendLocation, TIME_INTERVAL_GET_LOCATION);
        }
    };


    @Override
    public void onConnected(@Nullable Bundle bundle) {
        if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }


        FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        mFusedLocationClient.requestLocationUpdates(mLocationRequest, new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                locationData = locationResult.getLastLocation();
            }
        }, null);
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        if (connectionResult.hasResolution() && mContext instanceof Activity) {
            try {
                Activity activity = (Activity) mContext;
                connectionResult.startResolutionForResult(activity, CONNECTION_FAILURE_RESOLUTION_REQUEST);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            Log.i("", "Location services connection failed with code " + connectionResult.getErrorCode());
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.w("==>UpdateLocation<==", "" + String.format("%.6f", location.getLatitude()) + "," + String.format("%.6f", location.getLongitude()));
        locationData = location;

    }

    @Override
    public void onDestroy() {

        if (handlerSendLocation != null)
            handlerSendLocation.removeCallbacks(runnableSendLocation);


        Log.w("Service Update Info", "BGS > Stopped");

        stopSelf();
        super.onDestroy();
    }


}

AndroidManifest.xml

<service
            android:name=".ServiceLocation"
            android:enabled="true"
            android:exported="true" />
...