Сравнить коммиты

..
48 Коммитов
Автор SHA1 Сообщение Дата
Anton Tananaev e8d5e5c99b Update robolectric library 2018-08-09 14:46:02 +12:00
Anton Tananaev c3980780d8 Update project and dependencies 2018-08-09 14:33:05 +12:00
Anton Tananaev 3c11216334 Check API version 2018-05-06 16:44:56 -07:00
Anton Tananaev bcde8388d6 Update database version 2018-05-01 10:01:57 +12:00
Anton Tananaev 7f18915514 Merge pull request #327 from oliv3/mock_locations
Report mock locations
2018-04-30 13:54:15 +12:00
Olivier Girondel 42ad669fca Tell if a location is a mock 2018-04-30 02:16:10 +02:00
Anton Tananaev 3e2b508ea7 Update version number 2018-03-19 22:23:05 +13:00
Anton Tananaev fd4d616812 Check permissions in service 2018-03-19 22:22:45 +13:00
Anton Tananaev 4f6571e572 Update app version number 2018-03-18 21:28:11 +13:00
Anton Tananaev d3025b437b Replace firebase old crash reporting 2018-03-18 21:27:27 +13:00
Anton Tananaev 1e861ef0ac Fix hidden app URL open issue (fix #321) 2018-02-19 09:49:50 +13:00
Anton Tananaev 43afc57114 Merge pull request #318 from garyvdm/online_status
Show online/offline in connection changed status messages
2018-02-15 23:03:55 +13:00
Gary van der Merwe d47783808f Show online/offline in connection changed status messages. 2018-02-15 12:03:09 +02:00
Anton Tananaev 3ef2272227 Merge pull request #320 from garyvdm/revert-301-vector
Revert "Use vector icons"
2018-02-15 22:24:54 +13:00
Gary van der Merwe 3625ee42db Revert "Use vector icons." 2018-02-15 11:04:38 +02:00
Anton Tananaev 385826c3c1 Merge pull request #301 from garyvdm/vector
Use vector icons
2018-02-14 09:42:29 +13:00
Gary van der Merwe 1426926c8e Use vector icons. 2018-02-13 18:33:01 +02:00
Anton Tananaev 4f680d33c9 Merge pull request #311 from Bubu/patch-1
Add google maven repo
2018-01-23 08:20:51 +13:00
Marcus Hoffmann 2dad912da5 Add google() repo
This is required to build the app outside of Android Studio.

Fixes:
 > Could not find com.android.tools.build:gradle:3.0.1.
     Searched in the following locations:
         https://jcenter.bintray.com/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.pom
         https://jcenter.bintray.com/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.jar
2018-01-22 20:15:20 +01:00
Anton Tananaev 290a7d80eb Update app version number 2018-01-19 17:43:43 +13:00
Anton Tananaev 44228feb2f Fix SOS functionality 2018-01-19 17:43:18 +13:00
Anton Tananaev d887bc4119 Update version number 2018-01-09 08:26:19 +13:00
Anton Tananaev c892a20104 Fix lost API connection logic 2018-01-09 08:25:57 +13:00
Anton Tananaev 2719b57f7c Use color code directly 2018-01-07 09:26:55 +13:00
Anton Tananaev cc6c8a23f6 Update project files 2018-01-07 09:23:14 +13:00
Anton Tananaev 1e82cbbbf6 Merge pull request #305 from Alpha200/fixAccuracy
Fix reading accuracy property
2017-12-30 10:40:06 +13:00
Daniel Sendzik 4b8fde36d7 Fix reading accuracy property 2017-12-29 19:34:14 +01:00
Anton Tananaev b8cd56439a Merge pull request #304 from garyvdm/restore_startWakefulForegroundService
Restore fix auto-start issue on Android O
2017-12-21 23:03:37 +13:00
Gary van der Merwe edb1f696df Restore fix auto-start issue on Android O.
Also rename startWakefulService to startWakefulForegroundService to highlight
that it's different to the SDK version.
2017-12-21 11:54:14 +02:00
Anton Tananaev 56d2f2ef53 Merge pull request #303 from garyvdm/cleanup
Remove unnecessary code
2017-12-21 09:52:43 +13:00
Gary van der Merwe 59e6a5ae65 Remove code that was originally included for supporting older SDK APIs that are now older than our minSdkVersion. 2017-12-20 14:17:51 +02:00
Anton Tananaev 319fab647b Merge pull request #302 from garyvdm/hidden_notification
For hidden flavor, make notificaion not open the app when clicked, use different icon
2017-12-16 09:47:04 +13:00
Gary van der Merwe 42429f3496 For hidden flavor, make notification open system settings activity. 2017-12-15 12:38:56 +02:00
Gary van der Merwe 841d3e581c For hidden flavor, make notificaion not open the app when clicked, use different icon.
This only apply to when the notificaion can't be hidden, i.e. SDK >= 25.
2017-12-15 09:09:25 +02:00
Anton Tananaev dac43ccbc1 Merge pull request #300 from garyvdm/notification
Get service notification to show. Tweek settings.
2017-12-14 13:53:22 +13:00
Gary van der Merwe 3c9ae512bd Get service notification to show. Tweek settings. 2017-12-13 08:11:11 +02:00
Anton Tananaev d3e600d81d Gracefully stop location updates 2017-11-23 00:03:17 +13:00
Anton Tananaev e0296a9c65 Use fused location provider 2017-11-22 23:59:52 +13:00
Anton Tananaev e51f590e19 Merge pull request #297 from Mantas0726/master
Update PositionProvider.java
2017-11-15 09:57:45 +13:00
Mantas0726 6e3812320c Update PositionProvider.java 2017-11-14 22:20:11 +02:00
Anton Tananaev c45c8ea797 Update version number 2017-09-25 15:08:10 +13:00
Anton Tananaev ed0aa53aa3 Fix null pointer crash 2017-09-25 15:04:19 +13:00
Anton Tananaev f88891be2b Add another hidden intent filter 2017-09-25 15:01:56 +13:00
Anton Tananaev 3f83684d02 Update version number 2017-09-20 05:23:51 +12:00
Anton Tananaev a9d772bfda Restart service after upgrade 2017-09-20 05:23:27 +12:00
Anton Tananaev 2bc3c78a91 Update version number 2017-09-12 23:22:33 +12:00
Anton Tananaev 8fab55552d Handle no network provider 2017-09-12 23:21:58 +12:00
Anton Tananaev 979963f6a2 Fix auto-start issue on Android O 2017-09-07 19:04:10 +12:00
23 изменённых файлов: 291 добавлений и 304 удалений
+17 -15
Просмотреть файл
@@ -1,22 +1,23 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 26 compileSdkVersion 28
buildToolsVersion '26.0.1' buildToolsVersion '28.0.2'
defaultConfig { defaultConfig {
applicationId "org.traccar.client" applicationId "org.traccar.client"
buildConfigField "boolean", "HIDDEN_APP", "false" buildConfigField "boolean", "HIDDEN_APP", "false"
minSdkVersion 14 minSdkVersion 15
targetSdkVersion 26 targetSdkVersion 28
versionCode 39 versionCode 48
versionName '5.2' versionName '5.11'
} }
lintOptions { lintOptions {
checkReleaseBuilds false checkReleaseBuilds false
} }
flavorDimensions "default"
productFlavors { productFlavors {
regular regular
google google
@@ -26,24 +27,25 @@ android {
} }
} }
buildTypes { testOptions {
release { unitTests {
minifyEnabled false includeAndroidResources = true
proguardFiles getDefaultProguardFile('proguard-android.txt')
} }
} }
} }
dependencies { dependencies {
compile 'com.android.support:design:26.0.1' implementation 'com.android.support:design:28.0.0-rc01'
testCompile 'junit:junit:4.12' implementation 'com.mapzen.android:lost:3.0.4'
testCompile 'org.robolectric:robolectric:3.4.2' testImplementation 'junit:junit:4.12'
googleCompile 'com.google.firebase:firebase-core:11.2.0' testImplementation 'org.robolectric:robolectric:3.8'
googleCompile 'com.google.firebase:firebase-crash:11.2.0' googleImplementation 'com.google.firebase:firebase-core:16.0.1'
googleImplementation 'com.crashlytics.sdk.android:crashlytics:2.9.4'
} }
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'
+10
Просмотреть файл
@@ -8,6 +8,16 @@
android:label="@string/hidden_app_name" android:label="@string/hidden_app_name"
tools:replace="android:label"> tools:replace="android:label">
<activity
android:name="org.traccar.client.MainActivity">
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="www.traccar.org" android:pathPrefix="/hidden" />
</intent-filter>
</activity>
<receiver android:name="org.traccar.client.DialLaunchReceiver" > <receiver android:name="org.traccar.client.DialLaunchReceiver" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" /> <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
+9
Просмотреть файл
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM17.25,12c0,0.23 -0.02,0.46 -0.05,0.68l1.48,1.16c0.13,0.11 0.17,0.3 0.08,0.45l-1.4,2.42c-0.09,0.15 -0.27,0.21 -0.43,0.15l-1.74,-0.7c-0.36,0.28 -0.76,0.51 -1.18,0.69l-0.26,1.85c-0.03,0.17 -0.18,0.3 -0.35,0.3h-2.8c-0.17,0 -0.32,-0.13 -0.35,-0.29l-0.26,-1.85c-0.43,-0.18 -0.82,-0.41 -1.18,-0.69l-1.74,0.7c-0.16,0.06 -0.34,0 -0.43,-0.15l-1.4,-2.42c-0.09,-0.15 -0.05,-0.34 0.08,-0.45l1.48,-1.16c-0.03,-0.23 -0.05,-0.46 -0.05,-0.69 0,-0.23 0.02,-0.46 0.05,-0.68l-1.48,-1.16c-0.13,-0.11 -0.17,-0.3 -0.08,-0.45l1.4,-2.42c0.09,-0.15 0.27,-0.21 0.43,-0.15l1.74,0.7c0.36,-0.28 0.76,-0.51 1.18,-0.69l0.26,-1.85c0.03,-0.17 0.18,-0.3 0.35,-0.3h2.8c0.17,0 0.32,0.13 0.35,0.29l0.26,1.85c0.43,0.18 0.82,0.41 1.18,0.69l1.74,-0.7c0.16,-0.06 0.34,0 0.43,0.15l1.4,2.42c0.09,0.15 0.05,0.34 -0.08,0.45l-1.48,1.16c0.03,0.23 0.05,0.46 0.05,0.69z"/>
</vector>
+5
Просмотреть файл
@@ -9,10 +9,12 @@
<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" />
<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"
@@ -55,6 +57,9 @@
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver> </receiver>
</application> </application>
+2 -3
Просмотреть файл
@@ -1,5 +1,5 @@
/* /*
* Copyright 2013 Anton Tananaev (anton.tananaev@gmail.com) * Copyright 2013 - 2017 Anton Tananaev (anton.tananaev@gmail.com)
* *
* 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.
@@ -19,7 +19,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.content.WakefulBroadcastReceiver;
public class AutostartReceiver extends WakefulBroadcastReceiver { public class AutostartReceiver extends WakefulBroadcastReceiver {
@@ -27,7 +26,7 @@ public class AutostartReceiver extends WakefulBroadcastReceiver {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
if (sharedPreferences.getBoolean(MainFragment.KEY_STATUS, false)) { if (sharedPreferences.getBoolean(MainFragment.KEY_STATUS, false)) {
startWakefulService(context, new Intent(context, TrackingService.class)); startWakefulForegroundService(context, new Intent(context, TrackingService.class));
} }
} }
+6 -3
Просмотреть файл
@@ -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
@@ -98,8 +99,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
values.put("altitude", position.getAltitude()); values.put("altitude", position.getAltitude());
values.put("speed", position.getSpeed()); values.put("speed", position.getSpeed());
values.put("course", position.getCourse()); values.put("course", position.getCourse());
values.put("accuracy", position.getCourse()); 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 +135,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;
+4 -16
Просмотреть файл
@@ -58,7 +58,7 @@ public class MainFragment extends PreferenceFragment implements OnSharedPreferen
public static final String KEY_INTERVAL = "interval"; public static final String KEY_INTERVAL = "interval";
public static final String KEY_DISTANCE = "distance"; public static final String KEY_DISTANCE = "distance";
public static final String KEY_ANGLE = "angle"; public static final String KEY_ANGLE = "angle";
public static final String KEY_PROVIDER = "provider"; public static final String KEY_ACCURACY = "accuracy";
public static final String KEY_STATUS = "status"; public static final String KEY_STATUS = "status";
private static final int PERMISSIONS_REQUEST_LOCATION = 2; private static final int PERMISSIONS_REQUEST_LOCATION = 2;
@@ -150,13 +150,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();
@@ -175,7 +168,7 @@ public class MainFragment extends PreferenceFragment implements OnSharedPreferen
findPreference(KEY_INTERVAL).setEnabled(enabled); findPreference(KEY_INTERVAL).setEnabled(enabled);
findPreference(KEY_DISTANCE).setEnabled(enabled); findPreference(KEY_DISTANCE).setEnabled(enabled);
findPreference(KEY_ANGLE).setEnabled(enabled); findPreference(KEY_ANGLE).setEnabled(enabled);
findPreference(KEY_PROVIDER).setEnabled(enabled); findPreference(KEY_ACCURACY).setEnabled(enabled);
} }
@Override @Override
@@ -223,10 +216,10 @@ 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<>(); Set<String> missingPermissions = new HashSet<>();
if (!hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)) { if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
missingPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION); missingPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
} }
if (!hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) { if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
missingPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION); missingPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
} }
if (missingPermissions.isEmpty()) { if (missingPermissions.isEmpty()) {
@@ -247,13 +240,8 @@ public class MainFragment extends PreferenceFragment implements OnSharedPreferen
ALARM_MANAGER_INTERVAL, ALARM_MANAGER_INTERVAL, alarmIntent); ALARM_MANAGER_INTERVAL, ALARM_MANAGER_INTERVAL, alarmIntent);
} else { } else {
sharedPreferences.edit().putBoolean(KEY_STATUS, false).apply(); sharedPreferences.edit().putBoolean(KEY_STATUS, false).apply();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TwoStatePreference preference = (TwoStatePreference) findPreference(KEY_STATUS); TwoStatePreference preference = (TwoStatePreference) findPreference(KEY_STATUS);
preference.setChecked(false); preference.setChecked(false);
} else {
CheckBoxPreference preference = (CheckBoxPreference) findPreference(KEY_STATUS);
preference.setChecked(false);
}
} }
} }
-122
Просмотреть файл
@@ -1,122 +0,0 @@
/*
* Copyright 2015 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;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
@SuppressWarnings("MissingPermission")
public class MixedPositionProvider extends PositionProvider implements LocationListener, GpsStatus.Listener {
private static final int FIX_TIMEOUT = 30 * 1000;
private LocationListener backupListener;
private long lastFixTime;
public MixedPositionProvider(Context context, PositionListener listener) {
super(context, listener);
}
public void startUpdates() {
lastFixTime = System.currentTimeMillis();
locationManager.addGpsStatusListener(this);
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, requestInterval, 0, this);
} catch (IllegalArgumentException e) {
Log.w(TAG, e);
}
}
public void stopUpdates() {
locationManager.removeUpdates(this);
locationManager.removeGpsStatusListener(this);
stopBackupProvider();
}
private void startBackupProvider() {
Log.i(TAG, "backup provider start");
if (backupListener == null) {
backupListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.i(TAG, "backup provider location");
updateLocation(location);
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
};
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, requestInterval, 0, backupListener);
}
}
private void stopBackupProvider() {
Log.i(TAG, "backup provider stop");
if (backupListener != null) {
locationManager.removeUpdates(backupListener);
backupListener = null;
}
}
@Override
public void onLocationChanged(Location location) {
Log.i(TAG, "provider location");
stopBackupProvider();
lastFixTime = System.currentTimeMillis();
updateLocation(location);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
Log.i(TAG, "provider enabled");
stopBackupProvider();
}
@Override
public void onProviderDisabled(String provider) {
Log.i(TAG, "provider disabled");
startBackupProvider();
}
@Override
public void onGpsStatusChanged(int event) {
if (backupListener == null && System.currentTimeMillis() - lastFixTime - requestInterval > FIX_TIMEOUT) {
startBackupProvider();
}
}
}
+15 -1
Просмотреть файл
@@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2017 Anton Tananaev (anton.tananaev@gmail.com) * Copyright 2015 - 2018 Anton Tananaev (anton.tananaev@gmail.com)
* *
* 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;
}
} }
+63 -23
Просмотреть файл
@@ -15,19 +15,24 @@
*/ */
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;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.location.Location; import android.location.Location;
import android.location.LocationManager;
import android.os.BatteryManager; import android.os.BatteryManager;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
public abstract class PositionProvider { import com.mapzen.android.lost.api.LocationListener;
import com.mapzen.android.lost.api.LocationRequest;
import com.mapzen.android.lost.api.LocationServices;
import com.mapzen.android.lost.api.LostApiClient;
protected static final String TAG = PositionProvider.class.getSimpleName(); public class PositionProvider implements LostApiClient.ConnectionCallbacks, LocationListener {
private static final String TAG = PositionProvider.class.getSimpleName();
private static final int MINIMUM_INTERVAL = 1000; private static final int MINIMUM_INTERVAL = 1000;
@@ -38,46 +43,65 @@ public abstract class PositionProvider {
private final PositionListener listener; private final PositionListener listener;
private final Context context; private final Context context;
protected final LocationManager locationManager; private SharedPreferences preferences;
private LostApiClient apiClient;
private String deviceId; private String deviceId;
protected String type; private long interval;
protected long requestInterval; private double distance;
protected long interval; private double angle;
protected double distance;
protected double angle;
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;
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); preferences = PreferenceManager.getDefaultSharedPreferences(context);
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
deviceId = preferences.getString(MainFragment.KEY_DEVICE, "undefined"); deviceId = preferences.getString(MainFragment.KEY_DEVICE, "undefined");
interval = Long.parseLong(preferences.getString(MainFragment.KEY_INTERVAL, "600")) * 1000; interval = Long.parseLong(preferences.getString(MainFragment.KEY_INTERVAL, "600")) * 1000;
distance = Integer.parseInt(preferences.getString(MainFragment.KEY_DISTANCE, "0")); distance = Integer.parseInt(preferences.getString(MainFragment.KEY_DISTANCE, "0"));
angle = Integer.parseInt(preferences.getString(MainFragment.KEY_ANGLE, "0")); angle = Integer.parseInt(preferences.getString(MainFragment.KEY_ANGLE, "0"));
}
if (distance > 0 || angle > 0) { public void startUpdates() {
requestInterval = MINIMUM_INTERVAL; started = true;
apiClient = new LostApiClient.Builder(context).addConnectionCallbacks(this).build();
apiClient.connect();
}
private 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;
}
}
@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 { } else {
requestInterval = interval; apiClient.disconnect();
}
} }
type = preferences.getString(MainFragment.KEY_PROVIDER, "gps"); @Override
} public void onLocationChanged(Location location) {
public abstract void startUpdates();
public abstract void stopUpdates();
protected void updateLocation(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(), location.getLongitude()) >= distance || distance > 0 && DistanceCalculator.distance(location.getLatitude(), location.getLongitude(), lastLocation.getLatitude(), lastLocation.getLongitude()) >= 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;
@@ -87,11 +111,27 @@ public abstract class PositionProvider {
} }
} }
@Override
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) { 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) {
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1); int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
return (level * 100.0) / scale; return (level * 100.0) / scale;
} }
return 0;
}
} }
+4
Просмотреть файл
@@ -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);
} }
+20 -10
Просмотреть файл
@@ -15,11 +15,9 @@
*/ */
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.location.Location; import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
@@ -34,7 +32,10 @@ import android.widget.ArrayAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.Toast; import android.widget.Toast;
public class ShortcutActivity extends AppCompatActivity { import com.mapzen.android.lost.api.LocationServices;
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";
@@ -43,6 +44,8 @@ public class ShortcutActivity extends AppCompatActivity {
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);
@@ -99,16 +102,17 @@ public class ShortcutActivity extends AppCompatActivity {
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();
apiClient.connect();
}
@SuppressWarnings("MissingPermission")
@Override
public void onConnected() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Location location = LocationServices.FusedLocationApi.getLastLocation(apiClient);
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location == null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if (location != null) { if (location != null) {
@@ -133,6 +137,12 @@ public class ShortcutActivity extends AppCompatActivity {
} else { } else {
Toast.makeText(this, R.string.status_send_fail, Toast.LENGTH_SHORT).show(); 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) {
-64
Просмотреть файл
@@ -1,64 +0,0 @@
/*
* Copyright 2015 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;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
@SuppressWarnings("MissingPermission")
public class SimplePositionProvider extends PositionProvider implements LocationListener {
public SimplePositionProvider(Context context, PositionListener listener) {
super(context, listener);
if (!type.equals(LocationManager.NETWORK_PROVIDER)) {
type = LocationManager.GPS_PROVIDER;
}
}
public void startUpdates() {
try {
locationManager.requestLocationUpdates(type, requestInterval, 0, this);
} catch (IllegalArgumentException e) {
Log.w(TAG, e);
}
}
public void stopUpdates() {
locationManager.removeUpdates(this);
}
@Override
public void onLocationChanged(Location location) {
updateLocation(location);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
}
+3 -6
Просмотреть файл
@@ -57,11 +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);
if (preferences.getString(MainFragment.KEY_PROVIDER, "gps").equals("mixed")) { positionProvider = new PositionProvider(context, this);
positionProvider = new MixedPositionProvider(context, this);
} else {
positionProvider = new SimplePositionProvider(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();
@@ -104,7 +100,8 @@ public class TrackingController implements PositionProvider.PositionListener, Ne
@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();
} }
+20 -8
Просмотреть файл
@@ -21,6 +21,7 @@ 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 android.support.v4.app.NotificationCompat;
@@ -35,16 +36,24 @@ public class TrackingService extends Service {
private TrackingController trackingController; private TrackingController trackingController;
private static Notification createNotification(Context context) { private static Notification createNotification(Context context) {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0); NotificationCompat.Builder builder = new NotificationCompat.Builder(context, MainApplication.PRIMARY_CHANNEL)
return new NotificationCompat.Builder(context, MainApplication.PRIMARY_CHANNEL) .setSmallIcon(R.drawable.ic_stat_notify)
.setContentTitle(context.getString(R.string.app_name)) .setPriority(NotificationCompat.PRIORITY_LOW)
.setContentText(context.getString(R.string.settings_status_on_summary)) .setCategory(Notification.CATEGORY_SERVICE);
.setContentIntent(pendingIntent) Intent intent;
.setPriority(NotificationCompat.PRIORITY_MIN) if (!BuildConfig.HIDDEN_APP) {
.build(); intent = new Intent(context, MainActivity.class);
builder
.setContentTitle(context.getString(R.string.settings_status_on_summary))
.setTicker(context.getString(R.string.settings_status_on_summary))
.setColor(ContextCompat.getColor(context, R.color.primary_dark));
} else {
intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
}
builder.setContentIntent(PendingIntent.getActivity(context, 0, intent, 0));
return builder.build();
} }
@TargetApi(Build.VERSION_CODES.ECLAIR)
public static class HideNotificationService extends Service { public static class HideNotificationService extends Service {
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
@@ -69,8 +78,11 @@ 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));
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) {
trackingController = new TrackingController(this); trackingController = new TrackingController(this);
trackingController.start(); trackingController.start();
}
startForeground(NOTIFICATION_ID, createNotification(this)); startForeground(NOTIFICATION_ID, createNotification(this));
ContextCompat.startForegroundService(this, new Intent(this, HideNotificationService.class)); ContextCompat.startForegroundService(this, new Intent(this, HideNotificationService.class));
+62
Просмотреть файл
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.support.v4.content.ContextCompat;
import android.util.SparseArray;
public abstract class WakefulBroadcastReceiver extends BroadcastReceiver {
private static final String EXTRA_WAKE_LOCK_ID = "android.support.content.wakelockid";
private static final SparseArray<PowerManager.WakeLock> mActiveWakeLocks = new SparseArray<>();
private static int mNextId = 1;
public static void startWakefulForegroundService(Context context, Intent intent) {
synchronized (mActiveWakeLocks) {
int id = mNextId;
mNextId++;
if (mNextId <= 0) {
mNextId = 1;
}
intent.putExtra(EXTRA_WAKE_LOCK_ID, id);
ContextCompat.startForegroundService(context, intent);
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
WakefulBroadcastReceiver.class.getSimpleName());
wl.setReferenceCounted(false);
wl.acquire(60*1000);
mActiveWakeLocks.put(id, wl);
}
}
public static boolean completeWakefulIntent(Intent intent) {
final int id = intent.getIntExtra(EXTRA_WAKE_LOCK_ID, 0);
if (id == 0) {
return false;
}
synchronized (mActiveWakeLocks) {
PowerManager.WakeLock wl = mActiveWakeLocks.get(id);
if (wl != null) {
wl.release();
mActiveWakeLocks.remove(id);
return true;
}
return true;
}
}
}
+10
Просмотреть файл
@@ -0,0 +1,10 @@
<vector
android:width="24dp"
android:height="24dp"
android:viewportHeight="72.0"
android:viewportWidth="72.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="#FF000000"
android:pathData="M36,0A36,36 0,0 0,0 36A36,36 0,0 0,36 72A36,36 0,0 0,72 36A36,36 0,0 0,36 0zM50.51,14.66C53.41,16.89 55.93,19.68 57.88,23.05C59.83,26.42 60.99,30 61.46,33.63L55.09,34.55C54.72,31.74 53.87,28.85 52.36,26.24C50.85,23.63 48.78,21.45 46.53,19.72L50.51,14.66zM42.82,24.85C44.4,26.08 45.77,27.58 46.84,29.43C47.91,31.27 48.52,33.21 48.79,35.2L42.42,36.12C42.25,34.95 41.95,33.7 41.32,32.61C40.69,31.53 39.77,30.64 38.84,29.91L42.82,24.85zM18.38,31.13L24.76,42.17L31.13,53.21A12.75,12.75 37.68,0 1,18.38 53.21A12.75,12.75 37.68,0 1,12.01 42.17A12.75,12.75 37.68,0 1,18.38 31.13zM32.96,34.21A3.19,3.19 60,0 1,35.8 35.8A3.19,3.19 60,0 1,34.63 40.15A3.19,3.19 60,0 1,30.28 38.99A3.19,3.19 60,0 1,31.45 34.63A3.19,3.19 60,0 1,32.96 34.21z"/>
</vector>
+7 -6
Просмотреть файл
@@ -20,11 +20,11 @@
<string name="settings_status_on">Stop</string> <string name="settings_status_on">Stop</string>
<string name="settings_status_off_summary">Service stopped</string> <string name="settings_status_off_summary">Service stopped</string>
<string name="settings_status_on_summary">Service running</string> <string name="settings_status_on_summary">Service running</string>
<string name="settings_provider_title">Location provider</string> <string name="settings_accuracy_title">Location accuracy</string>
<string name="settings_provider_summary">Source of location data</string> <string name="settings_accuracy_summary">Desired location accuracy</string>
<string name="settings_provider_gps">GPS provider</string> <string name="settings_accuracy_high">High</string>
<string name="settings_provider_network">Network provider</string> <string name="settings_accuracy_medium">Medium</string>
<string name="settings_provider_mixed">Mixed provider</string> <string name="settings_accuracy_low">Low</string>
<string name="settings_foreground_title">Foreground service</string> <string name="settings_foreground_title">Foreground service</string>
<string name="settings_foreground_summary">Increase service priority</string> <string name="settings_foreground_summary">Increase service priority</string>
<string name="menu_status">Status</string> <string name="menu_status">Status</string>
@@ -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>
+8 -8
Просмотреть файл
@@ -3,16 +3,16 @@
<string name="settings_url_default_value" translatable="false">http://demo.traccar.org:5055</string> <string name="settings_url_default_value" translatable="false">http://demo.traccar.org:5055</string>
<string-array name="settings_provider_values" translatable="false"> <string-array name="settings_accuracy_values" translatable="false">
<item>gps</item> <item>high</item>
<item>network</item> <item>medium</item>
<item>mixed</item> <item>low</item>
</string-array> </string-array>
<string-array name="settings_provider_names"> <string-array name="settings_accuracy_names">
<item>@string/settings_provider_gps</item> <item>@string/settings_accuracy_high</item>
<item>@string/settings_provider_network</item> <item>@string/settings_accuracy_medium</item>
<item>@string/settings_provider_mixed</item> <item>@string/settings_accuracy_low</item>
</string-array> </string-array>
</resources> </resources>
+4
Просмотреть файл
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
+8 -8
Просмотреть файл
@@ -20,6 +20,14 @@
android:summary="@string/settings_url_summary" android:summary="@string/settings_url_summary"
android:title="@string/settings_url_title" /> android:title="@string/settings_url_title" />
<ListPreference
android:defaultValue="medium"
android:entries="@array/settings_accuracy_names"
android:entryValues="@array/settings_accuracy_values"
android:key="accuracy"
android:summary="@string/settings_accuracy_summary"
android:title="@string/settings_accuracy_title" />
<EditTextPreference <EditTextPreference
android:defaultValue="300" android:defaultValue="300"
android:key="interval" android:key="interval"
@@ -41,12 +49,4 @@
android:summary="@string/settings_angle_summary" android:summary="@string/settings_angle_summary"
android:title="@string/settings_angle_title" /> android:title="@string/settings_angle_title" />
<ListPreference
android:defaultValue="gps"
android:entries="@array/settings_provider_names"
android:entryValues="@array/settings_provider_values"
android:key="provider"
android:summary="@string/settings_provider_summary"
android:title="@string/settings_provider_title" />
</PreferenceScreen> </PreferenceScreen>
+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:2.3.3' classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'com.google.gms:google-services:3.1.0' classpath 'com.google.gms:google-services:4.0.2'
classpath 'io.fabric.tools:gradle:1.25.4'
} }
} }
allprojects { allprojects {
repositories { repositories {
jcenter()
google() google()
jcenter()
} }
} }
+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.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-all.zip