我有一个收集位置的简单应用程序。它可以工作几分钟或几小时,但是如果我断开连接或断开Internet连接,或者禁用/启用GPS 4-5或更多次,它将不再发送连接更新。而且我通常必须重启手机或杀死该应用,然后重新启动(有时重启后有时无法正常工作)才能再次获得位置。
我的应用程序有一个简单的活动,以及一个用于在前台运行和收集并将其发送到服务器的服务。
这是我的代码:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shetapp.ranandeg">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="mydefaultnotificationchannel" />
<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"
android:configChanges="orientation|screenSize"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyLocationTrackerService"
android:enabled="true"
android:exported="true" />
<service android:name=".MyFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
这是我的活动:
public class MainActivity extends AppCompatActivity {
private final String TAG = "myapp-ma";
public static final String _TAG = "myapp-ma";
public static Context context;
private WebView webViewBrowser;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: main activity created.");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivity.context = getApplicationContext();
loadPrefs(getApplicationContext());
getControles();
setBrowser();
startService(new Intent(this , MyLocationTrackerService.class));
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy: main activity destroyed.");
super.onDestroy();
}
@Override
protected void onResume() {
Log.d(TAG, "onResume: main activity resumed.");
super.onResume();
loadPrefs(getApplicationContext());
startService(new Intent(this , MyLocationTrackerService.class));
}
public void loadPrefs(Context context) {
Log.d(TAG, "loadPrefs: fired!");
SharedPreferences pref = getApplicationContext().getSharedPreferences(AppConfig.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
MyLocationTrackerService.USER_TOKEN = pref.getString(AppConfig.SHARED_PREFERENCES_USER_TOKEN , "xxx");
}
protected void getControles() {
Log.d(TAG, "getControles: fired!");
webViewBrowser = (WebView) findViewById(R.id.activity_main_webViewBrowser);
WebAppInterface.wv = webViewBrowser;
}
protected void setBrowser() {
webViewBrowser.addJavascriptInterface(new WebAppInterface(this), "NativeInterface");
WebSettings webSettings = webViewBrowser.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webViewBrowser.setWebViewClient(new MyWebViewClient());
webViewBrowser.setWebChromeClient(new MyWebChromeClient());
webViewBrowser.loadUrl("file:///android_asset/www/index.html");
}
@Override
public void onBackPressed() {
if(webViewBrowser.canGoBack() == true) {
webViewBrowser.goBack();
} else {
MainActivity.super.onBackPressed();
}
}
}
位置跟踪器服务:
public class MyLocationTrackerService extends Service
{
private static final String TAG = "myapp-mlts";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1 * 60 * 1000; // MINUTES*60*1000
private static final float LOCATION_DISTANCE = 0f; // 100f;
public static String USER_TOKEN = "";
private static final int NOTIF_ID = 1;
private static final String NOTIF_CHANNEL_ID = "Channel_Id";
private BroadcastReceiver mRegistrationBroadcastReceiver;
private class LocationListener implements android.location.LocationListener
{
Location mLastLocation;
public LocationListener(String provider)
{
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location)
{
Log.d(TAG, "onLocationChanged: location change detected , "+location.getProvider());
mLastLocation.set(location);
updateServerLocation(getApplication() , location , AppConfig.SERVER_IP , MyLocationTrackerService.USER_TOKEN);
}
@Override
public void onProviderDisabled(String provider)
{
Log.d(TAG, "LocationListener onProviderDisabled , "+provider);
}
@Override
public void onProviderEnabled(String provider)
{
Log.d(TAG, "LocationListener onProviderEnabled , "+provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.d(TAG, "LocationListener onStatusChanged , " + provider);
}
protected void updateServerLocation(Context context, final Location location , final String ip , final String userToken)
{
Log.d(TAG, "LocationListener updateServerLocation, token/server : "+userToken+"/"+ip);
if(ip.equals("")){
Log.d(TAG , "ip of server is empty string. returned.");
} else if(!isConnected()){
Log.d(TAG, "updateServerLocation: not connected!");
} else if(userToken.length() < 1){
Log.d(TAG, "updateServerLocation: userToken.length() < 1 , userToken is : "+userToken);
} else {
String url = ip + "/app/ranande/location";
StringRequest request = new StringRequest(
Request.Method.POST,
url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try{
Log.d(TAG, "onResponse: " + response);
} catch (Exception e){
Log.d(TAG, "onResponse: " + e.getMessage().toString());
}
}
},
new Response.ErrorListener(){
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "onErrorResponse: " + error.toString());
}
}
){
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
String token = userToken;
if( token.equals(null) || token.equals("") ){
Log.d(TAG , "token is empty string, returned.");
}
params.put("token", token);
params.put("latitude", String.valueOf(location.getLatitude()));
params.put("longitude", String.valueOf(location.getLongitude()));
return params;
}
};
VolleyController.getInstance(context).addToRequestQueue(request);
}
}
}
LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
@Override
public IBinder onBind(Intent arg0)
{
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d(TAG, "MyLocationTrackerService onStartCommand fired.");
startForeground();
try{
Log.d(TAG, "MyLocationTrackerService onStartCommand: token/ip are "+MyLocationTrackerService.USER_TOKEN+"/"+AppConfig.SERVER_IP);
} catch (Exception ex){
Log.d(TAG, "onStartCommand: Exception! : "+ex.toString());
}
try{
super.onStartCommand(intent, flags, startId);
} catch (Exception ex){
Log.e(TAG, "onStartCommand: Exception on calling super.onStartCommand," +ex.toString());
}
return START_STICKY;
}
@Override
public void onCreate()
{
Log.d(TAG, "MyLocationTrackerService created.");
initializeLocationManager();
try {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
//use checkSelfPermission()
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} else {
//simply use the required feature
//as the user has already granted permission to them during installation
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
}
} catch (java.lang.SecurityException ex) {
Log.d(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.d(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
@Override
public void onDestroy()
{
Log.d(TAG, "MyLocationTrackerService destroyed.");
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.d(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
try{
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
} catch (Exception ex) {
Log.d(TAG, "initializeLocationManager: error : "+ex.toString());
}
}
public Boolean isConnected(){
ConnectivityManager connectivityManager = (ConnectivityManager)getApplicationContext().getSystemService(MainActivity.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isConnected()){
return true;
}
return false;
}
private void startForeground() {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
startForeground(NOTIF_ID, new NotificationCompat.Builder(this,
NOTIF_CHANNEL_ID) // don't forget create a notification channel first
.setOngoing(true)
.setContentTitle(getString(R.string.app_name))
.setContentText("running ...")
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.globe)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher_round))
.build());
}
}
重新启动电话后,我的应用程序可以正常工作,有时我必须从应用程序管理器中终止该应用程序,然后再次运行它,但有时我必须重新启动电话。
我认为手机 GPS 或 android OS 可能存在错误,而不是我的App。
我的代码中是否存在任何错误?或如何改变和解决这个问题?改用保险丝/谷歌服务是个好主意吗?