Мой сервис определения местоположения не отправляет местоположение после отключения - PullRequest
0 голосов
/ 07 января 2019

У меня есть простое приложение, которое собирает местоположения. он работает без нескольких минут или часов, но если я отключаюсь или теряю подключение к Интернету, или отключаю / включаю GPS 4-5 и более раз, он больше не отправляет обновления подключения. и мне приходится чаще всего перезагружать телефон или убивать это приложение и запускать его снова (иногда после перезапуска иногда не работает), чтобы снова найти местоположения.

Мое приложение имеет простое действие и сервис для запуска на переднем плане и сбора и отправки их на сервер.

Вот мой код:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.shetapp.ranandeg">

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="mydefaultnotificationchannel" />
    <application
        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">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize"
            android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

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

        <service android:name=".MyFirebaseInstanceIdService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>

        <service android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
    </application>
</manifest>

Это моя деятельность:

public class MainActivity extends AppCompatActivity {

    private final String TAG = "myapp-ma";
    public static final String _TAG = "myapp-ma";
    public static Context context;
    private WebView webViewBrowser;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate: main activity created.");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MainActivity.context = getApplicationContext();
        loadPrefs(getApplicationContext());
        getControles();
        setBrowser();

        startService(new Intent(this , MyLocationTrackerService.class));
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy: main activity destroyed.");
        super.onDestroy();
    }

    @Override
    protected void onResume() {
        Log.d(TAG, "onResume: main activity resumed.");
        super.onResume();

        loadPrefs(getApplicationContext());
        startService(new Intent(this , MyLocationTrackerService.class));
    }

    public void loadPrefs(Context context) {
        Log.d(TAG, "loadPrefs: fired!");
        SharedPreferences pref = getApplicationContext().getSharedPreferences(AppConfig.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
        MyLocationTrackerService.USER_TOKEN = pref.getString(AppConfig.SHARED_PREFERENCES_USER_TOKEN , "xxx");
    }

    protected void getControles() {
        Log.d(TAG, "getControles: fired!");
        webViewBrowser = (WebView) findViewById(R.id.activity_main_webViewBrowser);
        WebAppInterface.wv = webViewBrowser;
    }

    protected void setBrowser() {
        webViewBrowser.addJavascriptInterface(new WebAppInterface(this), "NativeInterface");
        WebSettings webSettings = webViewBrowser.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webViewBrowser.setWebViewClient(new MyWebViewClient());
        webViewBrowser.setWebChromeClient(new MyWebChromeClient());

        webViewBrowser.loadUrl("file:///android_asset/www/index.html");
    }

    @Override
    public void onBackPressed() {
        if(webViewBrowser.canGoBack() == true) {
            webViewBrowser.goBack();
        } else {
            MainActivity.super.onBackPressed();
        }
    }
}

Служба отслеживания местоположения:

public class MyLocationTrackerService extends Service
{
    private static final String TAG = "myapp-mlts";
    private LocationManager mLocationManager = null;
    private static final int LOCATION_INTERVAL = 1 * 60 * 1000; // MINUTES*60*1000
    private static final float LOCATION_DISTANCE = 0f; // 100f;
    public static String USER_TOKEN = "";

    private static final int NOTIF_ID = 1;
    private static final String NOTIF_CHANNEL_ID = "Channel_Id";

    private BroadcastReceiver mRegistrationBroadcastReceiver;

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

        public LocationListener(String provider)
        {
            mLastLocation = new Location(provider);
        }

        @Override
        public void onLocationChanged(Location location)
        {
            Log.d(TAG, "onLocationChanged: location change detected , "+location.getProvider());
            mLastLocation.set(location);
            updateServerLocation(getApplication() , location , AppConfig.SERVER_IP , MyLocationTrackerService.USER_TOKEN);
        }

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

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

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

        protected void updateServerLocation(Context context, final Location location , final String ip , final String userToken)
        {
            Log.d(TAG, "LocationListener updateServerLocation, token/server : "+userToken+"/"+ip);
            if(ip.equals("")){
                Log.d(TAG , "ip of server is empty string. returned.");
            } else if(!isConnected()){
                Log.d(TAG, "updateServerLocation: not connected!");
            } else if(userToken.length() < 1){
                Log.d(TAG, "updateServerLocation: userToken.length() < 1 , userToken is : "+userToken);
            } else {
                String url = ip + "/app/ranande/location";

                StringRequest request = new StringRequest(
                        Request.Method.POST,
                        url,
                        new Response.Listener<String>() {
                            @Override
                            public void onResponse(String response) {
                                try{
                                    Log.d(TAG, "onResponse: " + response);
                                } catch (Exception e){
                                    Log.d(TAG, "onResponse: " + e.getMessage().toString());
                                }
                            }
                        },
                        new Response.ErrorListener(){
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                Log.d(TAG, "onErrorResponse: " + error.toString());
                            }
                        }
                ){
                    @Override
                    protected Map<String, String> getParams() throws AuthFailureError {
                        Map<String, String>  params = new HashMap<String, String>();

                        String token = userToken;
                        if( token.equals(null) || token.equals("") ){
                            Log.d(TAG , "token is empty string, returned.");
                        }

                        params.put("token", token);
                        params.put("latitude", String.valueOf(location.getLatitude()));
                        params.put("longitude", String.valueOf(location.getLongitude()));

                        return  params;
                    }
                };
                VolleyController.getInstance(context).addToRequestQueue(request);
            }
        }
    }

    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.d(TAG, "MyLocationTrackerService onStartCommand fired.");
        startForeground();

        try{
            Log.d(TAG, "MyLocationTrackerService onStartCommand: token/ip are "+MyLocationTrackerService.USER_TOKEN+"/"+AppConfig.SERVER_IP);
        } catch (Exception ex){
            Log.d(TAG, "onStartCommand: Exception! : "+ex.toString());
        }

        try{
            super.onStartCommand(intent, flags, startId);
        } catch (Exception ex){
            Log.e(TAG, "onStartCommand: Exception on calling super.onStartCommand," +ex.toString());
        }

        return START_STICKY;
    }

    @Override
    public void onCreate()
    {
        Log.d(TAG, "MyLocationTrackerService created.");
        initializeLocationManager();
        try {
            if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
                //use checkSelfPermission()
                mLocationManager.requestLocationUpdates(
                        LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                        mLocationListeners[1]);
            } else {
                //simply use the required feature
                //as the user has already granted permission to them during installation
                mLocationManager.requestLocationUpdates(
                        LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                        mLocationListeners[1]);
            }
        } catch (java.lang.SecurityException ex) {
            Log.d(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.d(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.d(TAG, "MyLocationTrackerService destroyed.");
        super.onDestroy();
        if (mLocationManager != null) {
            for (int i = 0; i < mLocationListeners.length; i++) {
                try {
                    mLocationManager.removeUpdates(mLocationListeners[i]);
                } catch (Exception ex) {
                    Log.d(TAG, "fail to remove location listners, ignore", ex);
                }
            }
        }
    }

    private void initializeLocationManager() {
        try{
            if (mLocationManager == null) {
                mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
            }
        } catch (Exception ex) {
            Log.d(TAG, "initializeLocationManager: error : "+ex.toString());
        }

    }


    public Boolean isConnected(){
        ConnectivityManager connectivityManager = (ConnectivityManager)getApplicationContext().getSystemService(MainActivity.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        if(networkInfo != null && networkInfo.isConnected()){
            return true;
        }
        return false;
    }


    private void startForeground() {
        Intent notificationIntent = new Intent(this, MainActivity.class);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                notificationIntent, 0);

        startForeground(NOTIF_ID, new NotificationCompat.Builder(this,
                NOTIF_CHANNEL_ID) // don't forget create a notification channel first
                .setOngoing(true)
                .setContentTitle(getString(R.string.app_name))
                .setContentText("running ...")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.mipmap.globe)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher_round))
                .build());
    }
}

После перезагрузки телефона мое приложение работает без проблем, иногда мне приходится убивать Приложение из диспетчера приложений и запускать его снова, но иногда мне приходится перезагружать телефон.

Я думаю, может быть, есть ошибка с телефонами GPS или ОС Android не мое приложение.

В моем коде есть какая-нибудь ошибка? или как я мог изменить и решить эту проблему? Стоит ли использовать вместо этого службу fuse / google?

...