diff --git a/app/build.gradle b/app/build.gradle index 446c23e..20ced17 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,6 +39,7 @@ dependencies { testImplementation 'org.robolectric:robolectric:4.1' googleImplementation 'com.google.firebase:firebase-core:16.0.6' googleImplementation 'com.crashlytics.sdk.android:crashlytics:2.9.8' + googleImplementation "com.google.android.gms:play-services-location:16.0.0" } if (getGradle().getStartParameter().getTaskRequests().toString().contains("Google")) { diff --git a/app/src/google/java/org/traccar/client/PositionProviderFactory.java b/app/src/google/java/org/traccar/client/PositionProviderFactory.java new file mode 100644 index 0000000..359194b --- /dev/null +++ b/app/src/google/java/org/traccar/client/PositionProviderFactory.java @@ -0,0 +1,26 @@ +/* + * Copyright 2019 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.client; + +import android.content.Context; + +public class PositionProviderFactory { + + public static PositionProvider create(Context context, PositionProvider.PositionListener listener) { + return new AndroidPositionProvider(context, listener); + } + +} diff --git a/app/src/hidden/java/org/traccar/client/PositionProviderFactory.java b/app/src/hidden/java/org/traccar/client/PositionProviderFactory.java new file mode 100644 index 0000000..359194b --- /dev/null +++ b/app/src/hidden/java/org/traccar/client/PositionProviderFactory.java @@ -0,0 +1,26 @@ +/* + * Copyright 2019 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.client; + +import android.content.Context; + +public class PositionProviderFactory { + + public static PositionProvider create(Context context, PositionProvider.PositionListener listener) { + return new AndroidPositionProvider(context, listener); + } + +} diff --git a/app/src/main/java/org/traccar/client/AndroidPositionProvider.java b/app/src/main/java/org/traccar/client/AndroidPositionProvider.java new file mode 100644 index 0000000..86d1556 --- /dev/null +++ b/app/src/main/java/org/traccar/client/AndroidPositionProvider.java @@ -0,0 +1,96 @@ +package org.traccar.client; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Bundle; +import android.os.Looper; +import android.widget.Toast; + +public class AndroidPositionProvider extends PositionProvider implements LocationListener { + + private LocationManager locationManager; + private String provider; + + public AndroidPositionProvider(Context context, PositionListener listener) { + super(context, listener); + locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + provider = getProvider(preferences.getString(MainFragment.KEY_ACCURACY, "medium")); + } + + @SuppressLint("MissingPermission") + public void startUpdates() { + try { + locationManager.requestLocationUpdates( + provider, distance > 0 || angle > 0 ? MINIMUM_INTERVAL : interval, 0, this); + } catch (RuntimeException e) { + Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show(); + } + } + + public void stopUpdates() { + locationManager.removeUpdates(this); + } + + @SuppressLint("MissingPermission") + public void requestSingleLocation() { + try { + Location location = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER); + if (location != null) { + listener.onPositionUpdate(new Position(deviceId, location, getBatteryLevel(context))); + } else { + locationManager.requestSingleUpdate(provider, new LocationListener() { + @Override + public void onLocationChanged(Location location) { + listener.onPositionUpdate(new Position(deviceId, location, getBatteryLevel(context))); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + } + + @Override + public void onProviderEnabled(String provider) { + } + + @Override + public void onProviderDisabled(String provider) { + } + }, Looper.myLooper()); + } + } catch (RuntimeException e) { + listener.onPositionError(e); + } + } + + private static String getProvider(String accuracy) { + switch (accuracy) { + case "high": + return LocationManager.GPS_PROVIDER; + case "low": + return LocationManager.PASSIVE_PROVIDER; + default: + return LocationManager.NETWORK_PROVIDER; + } + } + + @Override + public void onLocationChanged(Location location) { + processLocation(location); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + } + + @Override + public void onProviderEnabled(String provider) { + } + + @Override + public void onProviderDisabled(String provider) { + } + +} diff --git a/app/src/main/java/org/traccar/client/PositionProvider.java b/app/src/main/java/org/traccar/client/PositionProvider.java index b0c7b98..5dfe7bc 100644 --- a/app/src/main/java/org/traccar/client/PositionProvider.java +++ b/app/src/main/java/org/traccar/client/PositionProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 - 2017 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2013 - 2019 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,49 +15,42 @@ */ package org.traccar.client; -import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; import android.os.BatteryManager; -import android.os.Bundle; import android.preference.PreferenceManager; import android.util.Log; -import android.widget.Toast; -public class PositionProvider implements LocationListener { +public abstract class PositionProvider { private static final String TAG = PositionProvider.class.getSimpleName(); - private static final int MINIMUM_INTERVAL = 1000; + protected static final int MINIMUM_INTERVAL = 1000; public interface PositionListener { void onPositionUpdate(Position position); + void onPositionError(Throwable error); } - private final PositionListener listener; + protected final PositionListener listener; - private final Context context; - private SharedPreferences preferences; - private LocationManager locationManager; + protected final Context context; + protected SharedPreferences preferences; - private String deviceId; - private long interval; - private double distance; - private double angle; + protected String deviceId; + protected long interval; + protected double distance; + protected double angle; - private Location lastLocation; + protected Location lastLocation; public PositionProvider(Context context, PositionListener listener) { this.context = context; this.listener = listener; - locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); - preferences = PreferenceManager.getDefaultSharedPreferences(context); deviceId = preferences.getString(MainFragment.KEY_DEVICE, "undefined"); @@ -66,30 +59,13 @@ public class PositionProvider implements LocationListener { angle = Integer.parseInt(preferences.getString(MainFragment.KEY_ANGLE, "0")); } - @SuppressLint("MissingPermission") - public void startUpdates() { - try { - locationManager.requestLocationUpdates( - getProvider(preferences.getString(MainFragment.KEY_ACCURACY, "medium")), - distance > 0 || angle > 0 ? MINIMUM_INTERVAL : interval, 0, this); - } catch (RuntimeException e) { - Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show(); - } - } + public abstract void startUpdates(); - public static String getProvider(String accuracy) { - switch (accuracy) { - case "high": - return LocationManager.GPS_PROVIDER; - case "low": - return LocationManager.PASSIVE_PROVIDER; - default: - return LocationManager.NETWORK_PROVIDER; - } - } + public abstract void stopUpdates(); - @Override - public void onLocationChanged(Location location) { + public abstract void requestSingleLocation(); + + protected void processLocation(Location location) { if (location != null && (lastLocation == null || location.getTime() - lastLocation.getTime() >= interval || distance > 0 && location.distanceTo(lastLocation) >= distance @@ -102,23 +78,7 @@ public class PositionProvider implements LocationListener { } } - @Override - public void onStatusChanged(String provider, int status, Bundle extras) { - } - - @Override - public void onProviderEnabled(String provider) { - } - - @Override - public void onProviderDisabled(String provider) { - } - - public void stopUpdates() { - locationManager.removeUpdates(this); - } - - public static double getBatteryLevel(Context context) { + protected static double getBatteryLevel(Context context) { Intent batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); if (batteryIntent != null) { int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); diff --git a/app/src/main/java/org/traccar/client/ShortcutActivity.java b/app/src/main/java/org/traccar/client/ShortcutActivity.java index ecde554..9050b26 100644 --- a/app/src/main/java/org/traccar/client/ShortcutActivity.java +++ b/app/src/main/java/org/traccar/client/ShortcutActivity.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2017 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2016 - 2019 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,28 +15,24 @@ */ package org.traccar.client; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; import android.os.Bundle; -import android.os.Looper; import android.preference.PreferenceManager; -import androidx.annotation.DrawableRes; -import androidx.core.content.ContextCompat; -import androidx.core.content.pm.ShortcutInfoCompat; -import androidx.core.content.pm.ShortcutManagerCompat; -import androidx.core.graphics.drawable.IconCompat; -import androidx.appcompat.app.AppCompatActivity; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; +import androidx.annotation.DrawableRes; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.ContextCompat; +import androidx.core.content.pm.ShortcutInfoCompat; +import androidx.core.content.pm.ShortcutManagerCompat; +import androidx.core.graphics.drawable.IconCompat; + public class ShortcutActivity extends AppCompatActivity { public static final String EXTRA_ACTION = "action"; @@ -104,61 +100,30 @@ public class ShortcutActivity extends AppCompatActivity { @SuppressWarnings("MissingPermission") private void sendAlarm() { - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); - - String provider = PositionProvider.getProvider( - preferences.getString(MainFragment.KEY_ACCURACY, "medium")); - - try { - Location location = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER); - if (location != null) { - sendAlarmLocation(location); - } else { - locationManager.requestSingleUpdate(provider, new LocationListener() { - @Override - public void onLocationChanged(Location location) { - sendAlarmLocation(location); - } - - @Override - public void onStatusChanged(String provider, int status, Bundle extras) { - } - - @Override - public void onProviderEnabled(String provider) { - } - - @Override - public void onProviderDisabled(String provider) { - } - }, Looper.myLooper()); - } - } catch (RuntimeException e) { - Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); - } - } - - private void sendAlarmLocation(Location location) { - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - - Position position = new Position( - preferences.getString(MainFragment.KEY_DEVICE, null), - location, PositionProvider.getBatteryLevel(this)); - - String request = ProtocolFormatter.formatRequest( - preferences.getString(MainFragment.KEY_URL, null), position, ALARM_SOS); - - RequestManager.sendRequestAsync(request, new RequestManager.RequestHandler() { + PositionProviderFactory.create(this, new PositionProvider.PositionListener() { @Override - public void onComplete(boolean success) { - if (success) { - Toast.makeText(ShortcutActivity.this, R.string.status_send_success, Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(ShortcutActivity.this, R.string.status_send_fail, Toast.LENGTH_SHORT).show(); - } + public void onPositionUpdate(Position position) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ShortcutActivity.this); + String request = ProtocolFormatter.formatRequest( + preferences.getString(MainFragment.KEY_URL, null), position, ALARM_SOS); + + RequestManager.sendRequestAsync(request, new RequestManager.RequestHandler() { + @Override + public void onComplete(boolean success) { + if (success) { + Toast.makeText(ShortcutActivity.this, R.string.status_send_success, Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(ShortcutActivity.this, R.string.status_send_fail, Toast.LENGTH_SHORT).show(); + } + } + }); } - }); + + @Override + public void onPositionError(Throwable error) { + Toast.makeText(ShortcutActivity.this, error.getMessage(), Toast.LENGTH_LONG).show(); + } + }).requestSingleLocation(); } private boolean executeAction(Intent intent) { diff --git a/app/src/main/java/org/traccar/client/TrackingController.java b/app/src/main/java/org/traccar/client/TrackingController.java index 37626f0..ab21542 100644 --- a/app/src/main/java/org/traccar/client/TrackingController.java +++ b/app/src/main/java/org/traccar/client/TrackingController.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2015 - 2019 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,7 +57,7 @@ public class TrackingController implements PositionProvider.PositionListener, Ne this.context = context; handler = new Handler(); preferences = PreferenceManager.getDefaultSharedPreferences(context); - positionProvider = new PositionProvider(context, this); + positionProvider = PositionProviderFactory.create(context, this); databaseHelper = new DatabaseHelper(context); networkManager = new NetworkManager(context, this); isOnline = networkManager.isOnline(); @@ -98,6 +98,10 @@ public class TrackingController implements PositionProvider.PositionListener, Ne } } + @Override + public void onPositionError(Throwable error) { + } + @Override public void onNetworkUpdate(boolean isOnline) { int message = isOnline ? R.string.status_network_online : R.string.status_network_offline; diff --git a/app/src/regular/java/org/traccar/client/PositionProviderFactory.java b/app/src/regular/java/org/traccar/client/PositionProviderFactory.java new file mode 100644 index 0000000..359194b --- /dev/null +++ b/app/src/regular/java/org/traccar/client/PositionProviderFactory.java @@ -0,0 +1,26 @@ +/* + * Copyright 2019 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.client; + +import android.content.Context; + +public class PositionProviderFactory { + + public static PositionProvider create(Context context, PositionProvider.PositionListener listener) { + return new AndroidPositionProvider(context, listener); + } + +}