Сравнить коммиты
| Автор | SHA1 | Дата | |
|---|---|---|---|
|
|
5d8f0dfb83 | ||
|
|
f42ecf9f09 | ||
|
|
556856ab5c | ||
|
|
f9f37ead08 | ||
|
|
b3ee99140e | ||
|
|
85f1e09308 | ||
|
|
20fd20f425 | ||
|
|
1ae7b27683 | ||
|
|
f5b12b9e74 | ||
|
|
d2f653034d | ||
|
|
ab5aec9721 | ||
|
|
1b0559c98a | ||
|
|
2e0e7ea453 | ||
|
|
ac6d677ff4 | ||
|
|
cbfe90757d | ||
|
|
a9f4390ae4 | ||
|
|
8a938701c8 | ||
|
|
2319834c5b | ||
|
|
1b93619e64 | ||
|
|
2a36e1aa6d | ||
|
|
64687b26c2 | ||
|
|
dcb60ab75e | ||
|
|
0b4c4cccc6 | ||
|
|
ef5bfff70a | ||
|
|
855efc7acb | ||
|
|
0ae47e65d4 | ||
|
|
e8d5e5c99b | ||
|
|
c3980780d8 | ||
|
|
3c11216334 | ||
|
|
bcde8388d6 | ||
|
|
7f18915514 | ||
|
|
42ad669fca | ||
|
|
3e2b508ea7 | ||
|
|
fd4d616812 | ||
|
|
4f6571e572 | ||
|
|
d3025b437b | ||
|
|
1e861ef0ac | ||
|
|
43afc57114 | ||
|
|
d47783808f | ||
|
|
3ef2272227 | ||
|
|
3625ee42db | ||
|
|
385826c3c1 | ||
|
|
1426926c8e | ||
|
|
4f680d33c9 | ||
|
|
2dad912da5 |
+17
-11
@@ -1,16 +1,15 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 27
|
compileSdkVersion 28
|
||||||
buildToolsVersion '27.0.3'
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.traccar.client"
|
applicationId "org.traccar.client"
|
||||||
buildConfigField "boolean", "HIDDEN_APP", "false"
|
buildConfigField "boolean", "HIDDEN_APP", "false"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 27
|
targetSdkVersion 28
|
||||||
versionCode 45
|
versionCode 54
|
||||||
versionName '5.8'
|
versionName '5.17'
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
@@ -26,19 +25,26 @@ android {
|
|||||||
buildConfigField "boolean", "HIDDEN_APP", "true"
|
buildConfigField "boolean", "HIDDEN_APP", "true"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testOptions {
|
||||||
|
unitTests {
|
||||||
|
includeAndroidResources = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.android.support:design:27.0.2'
|
implementation 'com.google.android.material:material:1.1.0-alpha02'
|
||||||
compile 'com.mapzen.android:lost:3.0.4'
|
testImplementation 'junit:junit:4.12'
|
||||||
testCompile 'junit:junit:4.12'
|
testImplementation 'org.robolectric:robolectric:4.1'
|
||||||
testCompile 'org.robolectric:robolectric:3.6.1'
|
googleImplementation 'com.google.firebase:firebase-core:16.0.6'
|
||||||
googleCompile 'com.google.firebase:firebase-core:11.8.0'
|
googleImplementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
|
||||||
googleCompile 'com.google.firebase:firebase-crash:11.8.0'
|
googleImplementation "com.google.android.gms:play-services-location:16.0.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Google")) {
|
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Google")) {
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
apply plugin: 'io.fabric'
|
||||||
|
|
||||||
task copyJson(type: Copy) {
|
task copyJson(type: Copy) {
|
||||||
from '../../traccar-shared/google-services'
|
from '../../traccar-shared/google-services'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2017 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.location.Location;
|
||||||
|
|
||||||
|
import com.google.android.gms.location.FusedLocationProviderClient;
|
||||||
|
import com.google.android.gms.location.LocationCallback;
|
||||||
|
import com.google.android.gms.location.LocationRequest;
|
||||||
|
import com.google.android.gms.location.LocationResult;
|
||||||
|
import com.google.android.gms.location.LocationServices;
|
||||||
|
import com.google.android.gms.tasks.OnSuccessListener;
|
||||||
|
|
||||||
|
public class GooglePositionProvider extends PositionProvider {
|
||||||
|
|
||||||
|
private FusedLocationProviderClient fusedLocationClient;
|
||||||
|
|
||||||
|
public GooglePositionProvider(Context context, PositionListener listener) {
|
||||||
|
super(context, listener);
|
||||||
|
fusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
public void startUpdates() {
|
||||||
|
LocationRequest locationRequest = new LocationRequest();
|
||||||
|
locationRequest.setPriority(getPriority(preferences.getString(MainFragment.KEY_ACCURACY, "medium")));
|
||||||
|
locationRequest.setInterval(distance > 0 || angle > 0 ? MINIMUM_INTERVAL : interval);
|
||||||
|
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopUpdates() {
|
||||||
|
fusedLocationClient.removeLocationUpdates(locationCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
public void requestSingleLocation() {
|
||||||
|
fusedLocationClient.getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Location location) {
|
||||||
|
if (location != null) {
|
||||||
|
listener.onPositionUpdate(new Position(deviceId, location, getBatteryLevel(context)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getPriority(String accuracy) {
|
||||||
|
switch (accuracy) {
|
||||||
|
case "high":
|
||||||
|
return LocationRequest.PRIORITY_HIGH_ACCURACY;
|
||||||
|
case "low":
|
||||||
|
return LocationRequest.PRIORITY_LOW_POWER;
|
||||||
|
default:
|
||||||
|
return LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocationCallback locationCallback = new LocationCallback() {
|
||||||
|
@Override
|
||||||
|
public void onLocationResult(LocationResult locationResult) {
|
||||||
|
if (locationResult != null) {
|
||||||
|
for (Location location : locationResult.getLocations()) {
|
||||||
|
processLocation(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class PositionProviderFactory {
|
||||||
|
|
||||||
|
public static PositionProvider create(Context context, PositionProvider.PositionListener listener) {
|
||||||
|
return new GooglePositionProvider(context, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
tools:replace="android:label">
|
tools:replace="android:label">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity">
|
android:name="org.traccar.client.MainActivity">
|
||||||
<intent-filter android:label="@string/app_name">
|
<intent-filter android:label="@string/app_name">
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class PositionProviderFactory {
|
||||||
|
|
||||||
|
public static PositionProvider create(Context context, PositionProvider.PositionListener listener) {
|
||||||
|
return new AndroidPositionProvider(context, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,15 +9,24 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||||
|
|
||||||
|
<uses-feature android:name="android.hardware.location.network" />
|
||||||
|
<uses-feature android:name="android.hardware.location.gps" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
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" />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2012 - 2017 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,7 +17,7 @@ package org.traccar.client;
|
|||||||
|
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
listener.onPositionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2013 - 2017 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2015 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -27,7 +27,7 @@ import java.util.Date;
|
|||||||
|
|
||||||
public class DatabaseHelper extends SQLiteOpenHelper {
|
public class DatabaseHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
public static final int DATABASE_VERSION = 2;
|
public static final int DATABASE_VERSION = 3;
|
||||||
public static final String DATABASE_NAME = "traccar.db";
|
public static final String DATABASE_NAME = "traccar.db";
|
||||||
|
|
||||||
public interface DatabaseHandler<T> {
|
public interface DatabaseHandler<T> {
|
||||||
@@ -80,7 +80,8 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||||||
"speed REAL," +
|
"speed REAL," +
|
||||||
"course REAL," +
|
"course REAL," +
|
||||||
"accuracy REAL," +
|
"accuracy REAL," +
|
||||||
"battery REAL)");
|
"battery REAL," +
|
||||||
|
"mock INTEGER)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -89,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());
|
||||||
@@ -100,6 +106,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||||||
values.put("course", position.getCourse());
|
values.put("course", position.getCourse());
|
||||||
values.put("accuracy", position.getAccuracy());
|
values.put("accuracy", position.getAccuracy());
|
||||||
values.put("battery", position.getBattery());
|
values.put("battery", position.getBattery());
|
||||||
|
values.put("mock", position.getMock() ? 1 : 0);
|
||||||
|
|
||||||
db.insertOrThrow("position", null, values);
|
db.insertOrThrow("position", null, values);
|
||||||
}
|
}
|
||||||
@@ -133,6 +140,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||||||
position.setCourse(cursor.getDouble(cursor.getColumnIndex("course")));
|
position.setCourse(cursor.getDouble(cursor.getColumnIndex("course")));
|
||||||
position.setAccuracy(cursor.getDouble(cursor.getColumnIndex("accuracy")));
|
position.setAccuracy(cursor.getDouble(cursor.getColumnIndex("accuracy")));
|
||||||
position.setBattery(cursor.getDouble(cursor.getColumnIndex("battery")));
|
position.setBattery(cursor.getDouble(cursor.getColumnIndex("battery")));
|
||||||
|
position.setMock(cursor.getInt(cursor.getColumnIndex("mock")) > 0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2015 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2017 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,8 +16,8 @@
|
|||||||
package org.traccar.client;
|
package org.traccar.client;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2012 - 2017 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,7 +17,6 @@ package org.traccar.client;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -28,14 +27,14 @@ import android.content.pm.PackageManager;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.CheckBoxPreference;
|
|
||||||
import android.preference.EditTextPreference;
|
import android.preference.EditTextPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.preference.TwoStatePreference;
|
import android.preference.TwoStatePreference;
|
||||||
import android.support.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.support.v4.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -43,9 +42,7 @@ import android.view.MenuItem;
|
|||||||
import android.webkit.URLUtil;
|
import android.webkit.URLUtil;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class MainFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
|
public class MainFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
@@ -150,13 +147,6 @@ public class MainFragment extends PreferenceFragment implements OnSharedPreferen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasPermission(String permission) {
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return ContextCompat.checkSelfPermission(getActivity(), permission) == PackageManager.PERMISSION_GRANTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
@@ -222,19 +212,11 @@ public class MainFragment extends PreferenceFragment implements OnSharedPreferen
|
|||||||
|
|
||||||
private void startTrackingService(boolean checkPermission, boolean permission) {
|
private void startTrackingService(boolean checkPermission, boolean permission) {
|
||||||
if (checkPermission) {
|
if (checkPermission) {
|
||||||
Set<String> missingPermissions = new HashSet<>();
|
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||||
if (!hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
|
|
||||||
missingPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
|
|
||||||
}
|
|
||||||
if (!hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) {
|
|
||||||
missingPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
|
|
||||||
}
|
|
||||||
if (missingPermissions.isEmpty()) {
|
|
||||||
permission = true;
|
permission = true;
|
||||||
} else {
|
} else {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
requestPermissions(missingPermissions.toArray(new String[missingPermissions.size()]),
|
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_LOCATION);
|
||||||
PERMISSIONS_REQUEST_LOCATION);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2015 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,6 +17,7 @@ package org.traccar.client;
|
|||||||
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@@ -37,6 +38,9 @@ public class Position {
|
|||||||
accuracy = location.getAccuracy();
|
accuracy = location.getAccuracy();
|
||||||
}
|
}
|
||||||
this.battery = battery;
|
this.battery = battery;
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||||
|
this.mock = location.isFromMockProvider();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long id;
|
private long id;
|
||||||
@@ -139,4 +143,14 @@ public class Position {
|
|||||||
this.battery = battery;
|
this.battery = battery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean mock;
|
||||||
|
|
||||||
|
public boolean getMock() {
|
||||||
|
return mock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMock(boolean mock) {
|
||||||
|
this.mock = mock;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2013 - 2019 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.traccar.client;
|
package org.traccar.client;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
@@ -25,35 +24,28 @@ import android.os.BatteryManager;
|
|||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.mapzen.android.lost.api.LocationListener;
|
public abstract class PositionProvider {
|
||||||
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();
|
||||||
|
|
||||||
private static final int MINIMUM_INTERVAL = 1000;
|
protected static final int MINIMUM_INTERVAL = 1000;
|
||||||
|
|
||||||
public interface PositionListener {
|
public interface PositionListener {
|
||||||
void onPositionUpdate(Position position);
|
void onPositionUpdate(Position position);
|
||||||
|
void onPositionError(Throwable error);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PositionListener listener;
|
protected final PositionListener listener;
|
||||||
|
|
||||||
private final Context context;
|
protected final Context context;
|
||||||
private SharedPreferences preferences;
|
protected SharedPreferences preferences;
|
||||||
private LostApiClient apiClient;
|
|
||||||
|
|
||||||
private String deviceId;
|
protected String deviceId;
|
||||||
private long interval;
|
protected long interval;
|
||||||
private double distance;
|
protected double distance;
|
||||||
private double angle;
|
protected double angle;
|
||||||
|
|
||||||
private Location lastLocation;
|
protected Location lastLocation;
|
||||||
|
|
||||||
private boolean started;
|
|
||||||
|
|
||||||
public PositionProvider(Context context, PositionListener listener) {
|
public PositionProvider(Context context, PositionListener listener) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@@ -67,41 +59,16 @@ 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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startUpdates() {
|
public abstract void startUpdates();
|
||||||
started = true;
|
|
||||||
apiClient = new LostApiClient.Builder(context).addConnectionCallbacks(this).build();
|
|
||||||
apiClient.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getPriority(String accuracy) {
|
public abstract void stopUpdates();
|
||||||
switch (accuracy) {
|
|
||||||
case "high":
|
|
||||||
return LocationRequest.PRIORITY_HIGH_ACCURACY;
|
|
||||||
case "low":
|
|
||||||
return LocationRequest.PRIORITY_LOW_POWER;
|
|
||||||
default:
|
|
||||||
return LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
public abstract void requestSingleLocation();
|
||||||
@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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
protected void processLocation(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;
|
||||||
@@ -111,20 +78,7 @@ public class PositionProvider implements LostApiClient.ConnectionCallbacks, Loca
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected static double getBatteryLevel(Context context) {
|
||||||
public void onConnectionSuspended() {
|
|
||||||
Log.i(TAG, "lost client suspended");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopUpdates() {
|
|
||||||
if (apiClient.isConnected()) {
|
|
||||||
LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, this);
|
|
||||||
apiClient.disconnect();
|
|
||||||
}
|
|
||||||
started = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double getBatteryLevel(Context context) {
|
|
||||||
Intent batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
Intent batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||||
if (batteryIntent != null) {
|
if (batteryIntent != null) {
|
||||||
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
|
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012 - 2016 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2012 - 2016 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -36,6 +36,10 @@ public class ProtocolFormatter {
|
|||||||
.appendQueryParameter("accuracy", String.valueOf(position.getAccuracy()))
|
.appendQueryParameter("accuracy", String.valueOf(position.getAccuracy()))
|
||||||
.appendQueryParameter("batt", String.valueOf(position.getBattery()));
|
.appendQueryParameter("batt", String.valueOf(position.getBattery()));
|
||||||
|
|
||||||
|
if (position.getMock()) {
|
||||||
|
builder.appendQueryParameter("mock", String.valueOf(position.getMock()));
|
||||||
|
}
|
||||||
|
|
||||||
if (alarm != null) {
|
if (alarm != null) {
|
||||||
builder.appendQueryParameter("alarm", alarm);
|
builder.appendQueryParameter("alarm", alarm);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2015 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,25 +17,23 @@ package org.traccar.client;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.location.Location;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.DrawableRes;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.support.v4.content.pm.ShortcutInfoCompat;
|
|
||||||
import android.support.v4.content.pm.ShortcutManagerCompat;
|
|
||||||
import android.support.v4.graphics.drawable.IconCompat;
|
|
||||||
import android.support.v7.app.AppCompatActivity;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
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;
|
import androidx.annotation.DrawableRes;
|
||||||
import com.mapzen.android.lost.api.LostApiClient;
|
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 implements LostApiClient.ConnectionCallbacks {
|
public class ShortcutActivity extends AppCompatActivity {
|
||||||
|
|
||||||
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 +42,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,47 +98,32 @@ public class ShortcutActivity extends AppCompatActivity implements LostApiClient
|
|||||||
setResult(RESULT_OK, ShortcutManagerCompat.createShortcutResultIntent(this, shortcut));
|
setResult(RESULT_OK, ShortcutManagerCompat.createShortcutResultIntent(this, shortcut));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendAlarm() {
|
|
||||||
apiClient = new LostApiClient.Builder(this).addConnectionCallbacks(this).build();
|
|
||||||
apiClient.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("MissingPermission")
|
@SuppressWarnings("MissingPermission")
|
||||||
@Override
|
private void sendAlarm() {
|
||||||
public void onConnected() {
|
PositionProviderFactory.create(this, new PositionProvider.PositionListener() {
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
@Override
|
||||||
|
public void onPositionUpdate(Position position) {
|
||||||
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ShortcutActivity.this);
|
||||||
|
String request = ProtocolFormatter.formatRequest(
|
||||||
|
preferences.getString(MainFragment.KEY_URL, null), position, ALARM_SOS);
|
||||||
|
|
||||||
Location location = LocationServices.FusedLocationApi.getLastLocation(apiClient);
|
RequestManager.sendRequestAsync(request, new RequestManager.RequestHandler() {
|
||||||
|
@Override
|
||||||
if (location != null) {
|
public void onComplete(boolean success) {
|
||||||
|
if (success) {
|
||||||
Position position = new Position(
|
Toast.makeText(ShortcutActivity.this, R.string.status_send_success, Toast.LENGTH_SHORT).show();
|
||||||
preferences.getString(MainFragment.KEY_DEVICE, null),
|
} else {
|
||||||
location, PositionProvider.getBatteryLevel(this));
|
Toast.makeText(ShortcutActivity.this, R.string.status_send_fail, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
} else {
|
@Override
|
||||||
Toast.makeText(this, R.string.status_send_fail, Toast.LENGTH_SHORT).show();
|
public void onPositionError(Throwable error) {
|
||||||
}
|
Toast.makeText(ShortcutActivity.this, error.getMessage(), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
apiClient.disconnect();
|
}).requestSingleLocation();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnectionSuspended() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean executeAction(Intent intent) {
|
private boolean executeAction(Intent intent) {
|
||||||
@@ -168,7 +149,11 @@ 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:
|
||||||
sendAlarm();
|
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
sendAlarm();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.status_send_fail, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
finish();
|
finish();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2012 - 2017 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,7 +22,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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;
|
this.context = context;
|
||||||
handler = new Handler();
|
handler = new Handler();
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
positionProvider = new PositionProvider(context, this);
|
positionProvider = PositionProviderFactory.create(context, this);
|
||||||
databaseHelper = new DatabaseHelper(context);
|
databaseHelper = new DatabaseHelper(context);
|
||||||
networkManager = new NetworkManager(context, this);
|
networkManager = new NetworkManager(context, this);
|
||||||
isOnline = networkManager.isOnline();
|
isOnline = networkManager.isOnline();
|
||||||
@@ -98,9 +98,14 @@ public class TrackingController implements PositionProvider.PositionListener, Ne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPositionError(Throwable error) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNetworkUpdate(boolean isOnline) {
|
public void onNetworkUpdate(boolean isOnline) {
|
||||||
StatusActivity.addMessage(context.getString(R.string.status_connectivity_change));
|
int message = isOnline ? R.string.status_network_online : R.string.status_network_offline;
|
||||||
|
StatusActivity.addMessage(context.getString(message));
|
||||||
if (!this.isOnline && isOnline) {
|
if (!this.isOnline && isOnline) {
|
||||||
read();
|
read();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
|
* Copyright 2012 - 2017 Anton Tananaev (anton@traccar.org)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,10 +21,11 @@ import android.app.PendingIntent;
|
|||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import android.support.v4.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class TrackingService extends Service {
|
public class TrackingService extends Service {
|
||||||
@@ -77,11 +78,16 @@ 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));
|
||||||
|
|
||||||
trackingController = new TrackingController(this);
|
|
||||||
trackingController.start();
|
|
||||||
|
|
||||||
startForeground(NOTIFICATION_ID, createNotification(this));
|
startForeground(NOTIFICATION_ID, createNotification(this));
|
||||||
ContextCompat.startForegroundService(this, new Intent(this, HideNotificationService.class));
|
|
||||||
|
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
trackingController = new TrackingController(this);
|
||||||
|
trackingController.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||||
|
ContextCompat.startForegroundService(this, new Intent(this, HideNotificationService.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.support.v4.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
public abstract class WakefulBroadcastReceiver extends BroadcastReceiver {
|
public abstract class WakefulBroadcastReceiver extends BroadcastReceiver {
|
||||||
|
|||||||
@@ -39,7 +39,8 @@
|
|||||||
<string name="status_send_success">Send successfully</string>
|
<string name="status_send_success">Send successfully</string>
|
||||||
<string name="status_send_fail">Send failed</string>
|
<string name="status_send_fail">Send failed</string>
|
||||||
<string name="status_location_update">Location update</string>
|
<string name="status_location_update">Location update</string>
|
||||||
<string name="status_connectivity_change">Connectivity change</string>
|
<string name="status_network_online">Network online</string>
|
||||||
|
<string name="status_network_offline">Network offline</string>
|
||||||
<string name="hidden_app_name">Device Settings</string>
|
<string name="hidden_app_name">Device Settings</string>
|
||||||
<string name="hidden_alert">The app has been hidden. To open it again please dial 8722227 (TRACCAR).</string>
|
<string name="hidden_alert">The app has been hidden. To open it again please dial 8722227 (TRACCAR).</string>
|
||||||
<string name="error_msg_invalid_url">Please enter a valid http:// or https:// URL</string>
|
<string name="error_msg_invalid_url">Please enter a valid http:// or https:// URL</string>
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<network-security-config>
|
||||||
|
<base-config cleartextTrafficPermitted="true" />
|
||||||
|
</network-security-config>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class PositionProviderFactory {
|
||||||
|
|
||||||
|
public static PositionProvider create(Context context, PositionProvider.PositionListener listener) {
|
||||||
|
return new AndroidPositionProvider(context, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,7 +15,6 @@ import static org.junit.Assert.assertNotNull;
|
|||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(constants = BuildConfig.class, sdk = 21)
|
|
||||||
public class DatabaseHelperTest {
|
public class DatabaseHelperTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import java.util.Date;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(constants = BuildConfig.class, sdk = 21)
|
|
||||||
public class ProtocolFormatterTest {
|
public class ProtocolFormatterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import org.robolectric.annotation.Config;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(constants = BuildConfig.class, sdk = 21)
|
|
||||||
public class RequestManagerTest {
|
public class RequestManagerTest {
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
|
|||||||
+6
-3
@@ -1,16 +1,19 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven { url 'https://maven.fabric.io/public' }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||||
classpath 'com.google.gms:google-services:3.1.1'
|
classpath 'com.google.gms:google-services:4.2.0'
|
||||||
|
classpath 'io.fabric.tools:gradle:1.26.1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
|
||||||
google()
|
google()
|
||||||
|
jcenter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
android.enableJetifier=true
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableUnitTestBinaryResources=true
|
||||||
+1
-1
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user