我正在开发一个安卓应用程序,目的是获取手机的位置。我使用AlarmManager来反复触发BroadcastReceiver来获取坐标。当我用api 23在虚拟设备上运行时,一切正常。但是当我尝试用api 29在虚拟设备上运行时,警报没有被触发,什么都没有发生。当我在真实设备(小米)上使用api 29运行应用程序时,同样的错误行为也会发生。下面是所有实现的代码。谁能帮我解决这个问题?
谢谢你的帮助
build.gradle (:app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "br.com.detectx.android.locator"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'br.com.detectx.android:celulatronco-android:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.detectx.android.locator">
<uses-permission android:name="android.permission.INTERNET" android:required="true"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" android:required="true"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:required="true"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" android:required="true"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:required="true"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:required="true"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:required="true"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="br.com.detectx.android.locator.receiver.GPSReciver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>
LocationTracker.java
public class LocationTracker extends Service implements LocationListener {
public static final String TAG = "LocationTracker";
private static final long MIN_TIME_BW_UPDATES = 60000;
private final Context mContext;
private Location location = null;
private double latitude;
private double longitude;
public LocationTracker(Context context) {
this.mContext = context;
Log.e("Get", "GPS");
updateLocation();
}
public void onCreate() {
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_NOT_STICKY;
}
public void updateLocation() {
try {
LocationManager locationManager = (LocationManager) this.mContext.getSystemService(Context.LOCATION_SERVICE);
boolean gpsEnabled = locationManager.isProviderEnabled("gps");
boolean networkEnabled = locationManager.isProviderEnabled("network");
if (!gpsEnabled && !networkEnabled) {
Log.i(TAG, "no network provider is enabled");
} else {
if (networkEnabled) {
if (ActivityCompat.checkSelfPermission(this.mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this.mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Log.e(TAG, "Not allowed to ACCESS_FINE_LOCATION");
return;
}
locationManager.requestLocationUpdates("network", MIN_TIME_BW_UPDATES, 30.0f, this);
Log.d("Network", "G");
if (locationManager != null) {
this.location = locationManager.getLastKnownLocation("network");
if (this.location != null) {
this.latitude = this.location.getLatitude();
this.longitude = this.location.getLongitude();
}
}
} else if (gpsEnabled) {
if (this.location == null) {
locationManager.requestLocationUpdates("gps", MIN_TIME_BW_UPDATES, 30.0f, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
this.location = locationManager.getLastKnownLocation("gps");
if (this.location != null) {
this.latitude = this.location.getLatitude();
this.longitude = this.location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public double getLatitude() {
Location location = this.location;
if (location != null) {
this.latitude = location.getLatitude();
}
return this.latitude;
}
public double getLongitude() {
Location location = this.location;
if (location != null) {
this.longitude = location.getLongitude();
}
return this.longitude;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onLocationChanged(Location location) {
this.latitude = location.getLatitude();
this.longitude = location.getLongitude();
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
}
GPSReciver.java
public class GPSReciver extends BroadcastReceiver {
private static final String TAG = "GPSReciver";
@Override
public void onReceive(Context context, Intent intent) {
LocationTracker gps = new LocationTracker(context);
String slat = String.valueOf(gps.getLatitude());
String slon = String.valueOf(gps.getLongitude());
Log.i(TAG, String.format("lat: %s", slat));
Log.i(TAG, String.format("lon: %s", slon));
if (!slat.equals("0.0") && !slon.equals("0.0")) {
//TODO
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, ConstantsApp.PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case ConstantsApp.PERMISSIONS_REQUEST_READ_PHONE_STATE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, ConstantsApp.PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
} else {
finish();
}
return;
}
case ConstantsApp.PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, ConstantsApp.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
} else {
finish();
}
return;
}
case ConstantsApp.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT < 29) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), (long) 300000, PendingIntent.getBroadcast(this, 0, new Intent(this, GPSReciver.class), 0));
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, ConstantsApp.PERMISSIONS_REQUEST_ACCESS_BACKGROUND_LOCATION);
}
} else {
finish();
}
return;
}
case ConstantsApp.PERMISSIONS_REQUEST_ACCESS_BACKGROUND_LOCATION: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), (long) 300000, PendingIntent.getBroadcast(this, 0, new Intent(this, GPSReciver.class), 0));
} else {
finish();
}
return;
}
}
}
}
对于API 29+,你需要一个新的权限来在后台访问位置。
从文档中。
如果您的应用以Android 10(API级别29)或更高版本为目标,还要检查ACCESS_BACKGROUND_LOCATION。