Сравнить коммиты
| Автор | SHA1 | Дата | |
|---|---|---|---|
|
|
1b0559c98a | ||
|
|
2e0e7ea453 | ||
|
|
ac6d677ff4 | ||
|
|
cbfe90757d | ||
|
|
a9f4390ae4 | ||
|
|
8a938701c8 | ||
|
|
2319834c5b | ||
|
|
1b93619e64 | ||
|
|
2a36e1aa6d | ||
|
|
64687b26c2 | ||
|
|
dcb60ab75e | ||
|
|
0b4c4cccc6 | ||
|
|
ef5bfff70a | ||
|
|
855efc7acb | ||
|
|
0ae47e65d4 |
@@ -9,8 +9,8 @@ android {
|
|||||||
buildConfigField "boolean", "HIDDEN_APP", "false"
|
buildConfigField "boolean", "HIDDEN_APP", "false"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 48
|
versionCode 52
|
||||||
versionName '5.11'
|
versionName '5.15'
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
@@ -35,12 +35,11 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.android.support:design:28.0.0-rc01'
|
implementation 'com.android.support:design:28.0.0-rc02'
|
||||||
implementation 'com.mapzen.android:lost:3.0.4'
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testImplementation 'org.robolectric:robolectric:3.8'
|
testImplementation 'org.robolectric:robolectric:3.8'
|
||||||
googleImplementation 'com.google.firebase:firebase-core:16.0.1'
|
googleImplementation 'com.google.firebase:firebase-core:16.0.3'
|
||||||
googleImplementation 'com.crashlytics.sdk.android:crashlytics:2.9.4'
|
googleImplementation 'com.crashlytics.sdk.android:crashlytics:2.9.5'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Google")) {
|
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Google")) {
|
||||||
|
|||||||
@@ -20,6 +20,10 @@
|
|||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
android:name=".MainApplication">
|
android:name=".MainApplication">
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="google_analytics_adid_collection_enabled"
|
||||||
|
android:value="false" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:launchMode="singleTask" />
|
android:launchMode="singleTask" />
|
||||||
|
|||||||
@@ -90,6 +90,11 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||||||
onCreate(db);
|
onCreate(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
db.execSQL("DROP TABLE IF EXISTS position;");
|
||||||
|
onCreate(db);
|
||||||
|
}
|
||||||
|
|
||||||
public void insertPosition(Position position) {
|
public void insertPosition(Position position) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put("deviceId", position.getDeviceId());
|
values.put("deviceId", position.getDeviceId());
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 Anton Tananaev (anton@traccar.org)
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
public final class DistanceCalculator {
|
|
||||||
|
|
||||||
private static final double EQUATORIAL_EARTH_RADIUS = 6378.1370;
|
|
||||||
private static final double DEG_TO_RAD = Math.PI / 180;
|
|
||||||
|
|
||||||
public static double distance(double lat1, double lon1, double lat2, double lon2) {
|
|
||||||
double dlong = (lon2 - lon1) * DEG_TO_RAD;
|
|
||||||
double dlat = (lat2 - lat1) * DEG_TO_RAD;
|
|
||||||
double a = Math.pow(Math.sin(dlat / 2), 2)
|
|
||||||
+ Math.cos(lat1 * DEG_TO_RAD) * Math.cos(lat2 * DEG_TO_RAD) * Math.pow(Math.sin(dlong / 2), 2);
|
|
||||||
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
||||||
double d = EQUATORIAL_EARTH_RADIUS * c;
|
|
||||||
return d * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -21,16 +21,15 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
|
import android.location.LocationListener;
|
||||||
|
import android.location.LocationManager;
|
||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.mapzen.android.lost.api.LocationListener;
|
public class PositionProvider implements LocationListener {
|
||||||
import com.mapzen.android.lost.api.LocationRequest;
|
|
||||||
import com.mapzen.android.lost.api.LocationServices;
|
|
||||||
import com.mapzen.android.lost.api.LostApiClient;
|
|
||||||
|
|
||||||
public class PositionProvider implements LostApiClient.ConnectionCallbacks, LocationListener {
|
|
||||||
|
|
||||||
private static final String TAG = PositionProvider.class.getSimpleName();
|
private static final String TAG = PositionProvider.class.getSimpleName();
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ public class PositionProvider implements LostApiClient.ConnectionCallbacks, Loca
|
|||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private SharedPreferences preferences;
|
private SharedPreferences preferences;
|
||||||
private LostApiClient apiClient;
|
private LocationManager locationManager;
|
||||||
|
|
||||||
private String deviceId;
|
private String deviceId;
|
||||||
private long interval;
|
private long interval;
|
||||||
@@ -53,12 +52,12 @@ public class PositionProvider implements LostApiClient.ConnectionCallbacks, Loca
|
|||||||
|
|
||||||
private Location lastLocation;
|
private Location lastLocation;
|
||||||
|
|
||||||
private boolean started;
|
|
||||||
|
|
||||||
public PositionProvider(Context context, PositionListener listener) {
|
public PositionProvider(Context context, PositionListener listener) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
|
|
||||||
|
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
deviceId = preferences.getString(MainFragment.KEY_DEVICE, "undefined");
|
deviceId = preferences.getString(MainFragment.KEY_DEVICE, "undefined");
|
||||||
@@ -67,33 +66,25 @@ public class PositionProvider implements LostApiClient.ConnectionCallbacks, Loca
|
|||||||
angle = Integer.parseInt(preferences.getString(MainFragment.KEY_ANGLE, "0"));
|
angle = Integer.parseInt(preferences.getString(MainFragment.KEY_ANGLE, "0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
public void startUpdates() {
|
public void startUpdates() {
|
||||||
started = true;
|
try {
|
||||||
apiClient = new LostApiClient.Builder(context).addConnectionCallbacks(this).build();
|
locationManager.requestLocationUpdates(
|
||||||
apiClient.connect();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPriority(String accuracy) {
|
public static String getProvider(String accuracy) {
|
||||||
switch (accuracy) {
|
switch (accuracy) {
|
||||||
case "high":
|
case "high":
|
||||||
return LocationRequest.PRIORITY_HIGH_ACCURACY;
|
return LocationManager.GPS_PROVIDER;
|
||||||
case "low":
|
case "low":
|
||||||
return LocationRequest.PRIORITY_LOW_POWER;
|
return LocationManager.PASSIVE_PROVIDER;
|
||||||
default:
|
default:
|
||||||
return LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
|
return LocationManager.NETWORK_PROVIDER;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
|
||||||
@Override
|
|
||||||
public void onConnected() {
|
|
||||||
if (started) {
|
|
||||||
LocationRequest request = LocationRequest.create()
|
|
||||||
.setPriority(getPriority(preferences.getString(MainFragment.KEY_ACCURACY, "medium")))
|
|
||||||
.setInterval(distance > 0 || angle > 0 ? MINIMUM_INTERVAL : interval);
|
|
||||||
LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, request, this);
|
|
||||||
} else {
|
|
||||||
apiClient.disconnect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +92,7 @@ public class PositionProvider implements LostApiClient.ConnectionCallbacks, Loca
|
|||||||
public void onLocationChanged(Location location) {
|
public void onLocationChanged(Location location) {
|
||||||
if (location != null && (lastLocation == null
|
if (location != null && (lastLocation == null
|
||||||
|| location.getTime() - lastLocation.getTime() >= interval
|
|| location.getTime() - lastLocation.getTime() >= interval
|
||||||
|| distance > 0 && DistanceCalculator.distance(location.getLatitude(), location.getLongitude(), lastLocation.getLatitude(), lastLocation.getLongitude()) >= distance
|
|| distance > 0 && location.distanceTo(lastLocation) >= distance
|
||||||
|| angle > 0 && Math.abs(location.getBearing() - lastLocation.getBearing()) >= angle)) {
|
|| angle > 0 && Math.abs(location.getBearing() - lastLocation.getBearing()) >= angle)) {
|
||||||
Log.i(TAG, "location new");
|
Log.i(TAG, "location new");
|
||||||
lastLocation = location;
|
lastLocation = location;
|
||||||
@@ -112,16 +103,19 @@ public class PositionProvider implements LostApiClient.ConnectionCallbacks, Loca
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConnectionSuspended() {
|
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||||
Log.i(TAG, "lost client suspended");
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderEnabled(String provider) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderDisabled(String provider) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopUpdates() {
|
public void stopUpdates() {
|
||||||
if (apiClient.isConnected()) {
|
locationManager.removeUpdates(this);
|
||||||
LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, this);
|
|
||||||
apiClient.disconnect();
|
|
||||||
}
|
|
||||||
started = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double getBatteryLevel(Context context) {
|
public static double getBatteryLevel(Context context) {
|
||||||
|
|||||||
@@ -15,10 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.traccar.client;
|
package org.traccar.client;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.location.Criteria;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
|
import android.location.LocationListener;
|
||||||
|
import android.location.LocationManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Looper;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
@@ -32,10 +38,7 @@ import android.widget.ArrayAdapter;
|
|||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.mapzen.android.lost.api.LocationServices;
|
public class ShortcutActivity extends AppCompatActivity {
|
||||||
import com.mapzen.android.lost.api.LostApiClient;
|
|
||||||
|
|
||||||
public class ShortcutActivity extends AppCompatActivity implements LostApiClient.ConnectionCallbacks {
|
|
||||||
|
|
||||||
public static final String EXTRA_ACTION = "action";
|
public static final String EXTRA_ACTION = "action";
|
||||||
public static final String ACTION_START = "start";
|
public static final String ACTION_START = "start";
|
||||||
@@ -44,8 +47,6 @@ public class ShortcutActivity extends AppCompatActivity implements LostApiClient
|
|||||||
|
|
||||||
private static final String ALARM_SOS = "sos";
|
private static final String ALARM_SOS = "sos";
|
||||||
|
|
||||||
private LostApiClient apiClient;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -102,20 +103,46 @@ public class ShortcutActivity extends AppCompatActivity implements LostApiClient
|
|||||||
setResult(RESULT_OK, ShortcutManagerCompat.createShortcutResultIntent(this, shortcut));
|
setResult(RESULT_OK, ShortcutManagerCompat.createShortcutResultIntent(this, shortcut));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("MissingPermission")
|
||||||
private void sendAlarm() {
|
private void sendAlarm() {
|
||||||
apiClient = new LostApiClient.Builder(this).addConnectionCallbacks(this).build();
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
apiClient.connect();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("MissingPermission")
|
|
||||||
@Override
|
@Override
|
||||||
public void onConnected() {
|
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);
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
|
||||||
Location location = LocationServices.FusedLocationApi.getLastLocation(apiClient);
|
|
||||||
|
|
||||||
if (location != null) {
|
|
||||||
|
|
||||||
Position position = new Position(
|
Position position = new Position(
|
||||||
preferences.getString(MainFragment.KEY_DEVICE, null),
|
preferences.getString(MainFragment.KEY_DEVICE, null),
|
||||||
location, PositionProvider.getBatteryLevel(this));
|
location, PositionProvider.getBatteryLevel(this));
|
||||||
@@ -133,16 +160,6 @@ public class ShortcutActivity extends AppCompatActivity implements LostApiClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
|
||||||
Toast.makeText(this, R.string.status_send_fail, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
apiClient.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnectionSuspended() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean executeAction(Intent intent) {
|
private boolean executeAction(Intent intent) {
|
||||||
@@ -168,7 +185,12 @@ public class ShortcutActivity extends AppCompatActivity implements LostApiClient
|
|||||||
Toast.makeText(this, R.string.status_service_destroy, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.status_service_destroy, Toast.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
case ACTION_SOS:
|
case ACTION_SOS:
|
||||||
|
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||||
|
&& ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||||
sendAlarm();
|
sendAlarm();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.status_send_fail, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
finish();
|
finish();
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class StatusActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void addMessage(String message) {
|
public static void addMessage(String message) {
|
||||||
DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT);
|
DateFormat format = DateFormat.getTimeInstance(DateFormat.MEDIUM);
|
||||||
message = format.format(new Date()) + " - " + message;
|
message = format.format(new Date()) + " - " + message;
|
||||||
messages.add(message);
|
messages.add(message);
|
||||||
while (messages.size() > LIMIT) {
|
while (messages.size() > LIMIT) {
|
||||||
|
|||||||
@@ -78,15 +78,18 @@ public class TrackingService extends Service {
|
|||||||
Log.i(TAG, "service create");
|
Log.i(TAG, "service create");
|
||||||
StatusActivity.addMessage(getString(R.string.status_service_create));
|
StatusActivity.addMessage(getString(R.string.status_service_create));
|
||||||
|
|
||||||
|
startForeground(NOTIFICATION_ID, createNotification(this));
|
||||||
|
|
||||||
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||||
&& ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
&& ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||||
trackingController = new TrackingController(this);
|
trackingController = new TrackingController(this);
|
||||||
trackingController.start();
|
trackingController.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
startForeground(NOTIFICATION_ID, createNotification(this));
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||||
ContextCompat.startForegroundService(this, new Intent(this, HideNotificationService.class));
|
ContextCompat.startForegroundService(this, new Intent(this, HideNotificationService.class));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user