5

Mam usługę, która powinna przechwytywać lokalizację użytkownika i aktualny poziom naładowania baterii oraz wysłać go do serwera zaplecza. Z jakiegoś powodu wydaje się, że gdy tylko moja usługa zostanie włączona w mojej aplikacji, moja aplikacja zostanie losowo otwarta bez żadnej interakcji użytkownika (nawet jeśli użytkownik jest w innej aplikacji, moja aplikacja zostanie otwarta). Czy ktoś ma pojęcie, dlaczego tak się dzieje?Usługa Androida z usługą Google Play Lokalizacja Powoduje, że aplikacja jest otwierana losowo

Oto mój kod dla usługi:

import android.app.Service; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.content.SharedPreferences; 
import android.location.Address; 
import android.location.Geocoder; 
import android.location.Location; 
import android.os.BatteryManager; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.preference.PreferenceManager; 
import android.util.Log; 
import android.widget.Toast; 

import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.api.GoogleApiClient; 
import com.google.android.gms.common.server.converter.StringToIntConverter; 
import com.google.android.gms.location.LocationListener; 
import com.google.android.gms.location.LocationRequest; 
import com.google.android.gms.location.LocationServices; 
import com.google.firebase.database.DataSnapshot; 
import com.google.firebase.database.DatabaseError; 
import com.google.firebase.database.DatabaseReference; 
import com.google.firebase.database.FirebaseDatabase; 
import com.google.firebase.database.ValueEventListener; 

import java.io.IOException; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Locale; 
import java.util.Map; 
import java.util.concurrent.TimeUnit; 

import static android.R.attr.lines; 
import static com.package.R.id.location; 
import static com.package.R.id.view; 

public class LocationBatteryService extends Service implements 
    GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { 
    private String currentUser; 
    private String city; 
    private String country; 
    private float batteryLevel; 
    private int batteryLevelInt; 
    protected GoogleApiClient mGoogleApiClient; 
    protected LocationRequest mLocationRequest; 
    protected Location mCurrentLocation; 
    List<Address> addresses; 
    Geocoder geocoder; 




    @Override 
    public void onCreate() { 
     super.onCreate(); 
     buildGoogleApiClient(); 
    } 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    protected synchronized void buildGoogleApiClient() { 
     Log.i("TAG", "Building GoogleApiClient"); 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 
     createLocationRequest(); 
     mGoogleApiClient.connect(); 
    } 



    protected void createLocationRequest() { 
     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 
     String locationSyncSettings = prefs.getString("location_sync_time", ""); 
     long intervalTime = 5; 
     if(locationSyncSettings.equals("5 minutes")) { 
      intervalTime = 5; 
     } 
     if (locationSyncSettings.equals("10 minutes")) { 
      intervalTime = 10; 
     } 
     if (locationSyncSettings.equals("15 minutes")) { 
      intervalTime = 15; 
     } 
     if (locationSyncSettings.equals("30 minutes")) { 
      intervalTime = 30; 
     } 
     if (locationSyncSettings.equals("1 hour")) { 
      intervalTime = 60; 
     } 
     mLocationRequest = new LocationRequest(); 
     mLocationRequest.setInterval(TimeUnit.MINUTES.toMillis(intervalTime)); 
     mLocationRequest.setFastestInterval(60000); 
     mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); 
    } 


    @Override 
    public void onConnected(Bundle connectionHint) { 
     Log.i("TAG", "Connected to GoogleApiClient"); 
     try { 
      LocationServices.FusedLocationApi.requestLocationUpdates(
        mGoogleApiClient, mLocationRequest, this); 
      mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
      onLocationChanged(mCurrentLocation); 
     } 
     catch (SecurityException e){ 
      Log.d("TAG", "Error: " + e); 
     } 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     Log.d("TAG", "You got destoryed mate"); 
    } 

    @Override 
    public void onLocationChanged(Location location) { 
     updateLocationBackend(mCurrentLocation); 
    } 

    @Override 
    public void onConnectionSuspended(int cause) { 
     // The connection to Google Play services was lost for some reason. We call connect() to 
     // attempt to re-establish the connection. 
     Log.i("TAG", "Connection suspended"); 
     mGoogleApiClient.connect(); 
    } 

    public void onTaskRemoved (Intent rootIntent){ 
     this.stopSelf(); 
    } 

    @Override 
    public void onConnectionFailed(ConnectionResult result) { 
     // Refer to the javadoc for ConnectionResult to see what error codes might be returned in 
     // onConnectionFailed. 
     Log.i("TAG", "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode()); 
    } 

    public float getBatteryLevel() { 
     Intent batteryIntent = registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 
     int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); 
     int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); 

     // Error checking that probably isn't needed but I added just in case. 
     if(level == -1 || scale == -1) { 
      return 50.0f; 
     } 

     return ((float)level/(float)scale) * 100.0f; 
    } 

    private void updateLocationBackend(final Location location) { 

     Log.i("TAG", "Location and battery being updated"); 
     batteryLevel = getBatteryLevel(); 
     batteryLevelInt = Math.round(batteryLevel); 
     // Get current user 
     SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); 
     currentUser = sharedPrefs.getString("Username", ""); 

     // Get users added by you 
     DatabaseReference ref = FirebaseDatabase.getInstance().getReferenceFromUrl(Passwords.FB_URL).child("Relations").child(currentUser); 
     ref.addListenerForSingleValueEvent(
       new ValueEventListener() { 
        @Override 
        public void onDataChange(DataSnapshot dataSnapshot) { 
         // Get user value 
         for (DataSnapshot ds : dataSnapshot.getChildren()) { 
          final String contactNumber = ds.getKey(); 
     // Check to see if users added you 
          final DatabaseReference ref = FirebaseDatabase.getInstance().getReferenceFromUrl(Passwords.FB_URL).child("Contacts").child(contactNumber).child(currentUser); 
          ref.addListenerForSingleValueEvent(new ValueEventListener() { 
           @Override 
           public void onDataChange(DataSnapshot dataSnapshot) { 
            if (!dataSnapshot.child("name").exists()) { 
            // User has not added you so do not update location 
            } 
            // User has added you so update location 
            else { 
             SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); 
             boolean contactLocationSetting = sharedPrefs.getBoolean(contactNumber + "_location_pref", true); 
             Log.d("TAG", "ContactLocationSetting for " + contactNumber + " is equal to: " + contactLocationSetting); 
             if (location != null && contactLocationSetting == true) { 
              Map updateLocation = new HashMap(); 
              double latitude = location.getLatitude(); 
              double longitude = location.getLongitude(); 

              geocoder = new Geocoder(getApplicationContext(), Locale.getDefault()); 
              try { 
               addresses = geocoder.getFromLocation(latitude, longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5 
              } catch (IOException e) { 
               Log.e("TAG", "error is: " + e); 
              } 
              if (addresses.size() == 0) { 
               // Do nothing 
              } else { 
               city = addresses.get(0).getLocality(); 
               country = addresses.get(0).getCountryName(); 
               // String knownName = addresses.get(0).getFeatureName(); // Only if available else return NULL 
              } 
              updateLocation.put("battery", batteryLevelInt); 
              updateLocation.put("latitude", latitude); 
              updateLocation.put("longitude", longitude); 
              updateLocation.put("city", city); 
              updateLocation.put("country", country); 
              updateLocation.put("lastUpdated", System.currentTimeMillis()); 
              ref.updateChildren(updateLocation); 
              Log.d("TAG", "Updated location for: " + contactNumber); 
             } 
            } 
           } 

           @Override 
           public void onCancelled(DatabaseError databaseError) { 

           } 
          }); 


         } 
        } 

        @Override 
        public void onCancelled(DatabaseError databaseError) { 
         Log.w("TAG", "getUser:onCancelled", databaseError.toException()); 
        } 
       }); 
    } 

} 

Oto kod gdzie mogę uruchomić usługę:

import android.app.ActivityManager; 
import android.content.Context; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.os.Bundle; 
import android.preference.PreferenceManager; 
import android.support.design.widget.TabLayout; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentPagerAdapter; 
import android.support.v4.view.ViewPager; 
import android.support.v7.app.AppCompatActivity; 
import android.support.v7.widget.Toolbar; 
import android.util.Log; 

import java.util.ArrayList; 
import java.util.List; 

public class MainActivity extends AppCompatActivity { 
    private Toolbar toolbar; 
    private TabLayout tabLayout; 
    public static ViewPager viewPager; 
    public static ViewPagerAdapter adapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); 
     String currentUser = sharedPrefs.getString("Username", null); 
     if (currentUser == null) { 
      // Take user to log in screen 
      Log.d("TAG", "user needs to login"); 
      Intent intent = new Intent(this, MyIntro.class); 
      startActivity(intent); 
      finish(); 
     } 
     else { 
      // User already logged in 
      setupMainActivity(); 
     } 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
return; 
    } 

    private void setupViewPager(ViewPager viewPager) { 
     adapter = new ViewPagerAdapter(getSupportFragmentManager()); 
     adapter.addFragment(new ChalkboardFragment(), getString(R.string.chalkboard_label)); 
     adapter.addFragment(new ContactsFragment(), getString(R.string.contacts_label)); 
     viewPager.setAdapter(adapter); 
    } 

    class ViewPagerAdapter extends FragmentPagerAdapter { 
     private final List<Fragment> mFragmentList = new ArrayList<>(); 
     private final List<String> mFragmentTitleList = new ArrayList<>(); 

     public ViewPagerAdapter(FragmentManager manager) { 
      super(manager); 
     } 

     @Override 
     public Fragment getItem(int position) { 
      switch (position) { 
       case 0: 
        return new ChalkboardFragment(); 
       case 1: 
        return new ContactsFragment(); 
      } 
      return null; 
     } 

     @Override 
     public int getCount() { 
      return mFragmentList.size(); 
     } 

     public void addFragment(Fragment fragment, String title) { 
      mFragmentList.add(fragment); 
      mFragmentTitleList.add(title); 
     } 

     @Override 
     public CharSequence getPageTitle(int position) { 
      return mFragmentTitleList.get(position); 
     } 
    } 
public void setupMainActivity() { 
    setContentView(R.layout.activity_main); 
    toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 
    getSupportActionBar().setDisplayHomeAsUpEnabled(false); 
    viewPager = (ViewPager) findViewById(R.id.viewpager); 
    setupViewPager(viewPager); 
    tabLayout = (TabLayout) findViewById(R.id.tabs); 
    tabLayout.setupWithViewPager(viewPager); 
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 
    boolean locationSetting = prefs.getBoolean("location_pref", false); 
    Log.d("TAG", "location_pref " + locationSetting); 
    if (isMyServiceRunning(LocationBatteryService.class) == false && locationSetting == true) { 
     startService(new Intent(this, LocationBatteryService.class)); 
    } 
} 
    private boolean isMyServiceRunning(Class<?> serviceClass) { 
     ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
     for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 
      if (serviceClass.getName().equals(service.service.getClassName())) { 
       return true; 
      } 
     } 
     return false; 
    } 
} 

Application start:

import android.app.Application; 
import android.content.Context; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.preference.PreferenceManager; 
import android.util.Log; 
import com.digits.sdk.android.Digits; 
import com.twitter.sdk.android.core.TwitterAuthConfig; 
import com.twitter.sdk.android.core.TwitterCore; 

import io.fabric.sdk.android.Fabric; 

public class ApplicationStart extends Application { 
    private static Context mContext; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     mContext = this.getApplicationContext(); 
     /*if (!FirebaseApp.getApps(this).isEmpty()) { 
      FirebaseDatabase.getInstance().setPersistenceEnabled(true); 
     }*/ 
     SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); 
     String currentUser = sharedPrefs.getString("Username", null); 
     if (currentUser == null) { 
      // Take user to log in screen 
      Log.d("TAG", "user needs to login"); 
      Intent intent = new Intent(this, MyIntro.class); 
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      startActivity(intent); 
     } 
     else { 
      // User already logged in 
      Log.d("TAG", "user logged in: " + currentUser); 
      Intent intent = new Intent(this, MainActivity.class); 
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      startActivity(intent); 
     } 
     TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY,TWITTER_SECRET); 
     Fabric.with(this, new TwitterCore(authConfig),new Digits.Builder().build()); 
    } 
    public static Context getAppContext(){ 
     return mContext; 
    } 
} 

Kompletna oczywisty:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.package"> 
<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> 
<uses-permission android:name="android.permission.READ_PROFILE" /> 
<uses-permission android:name="android.permission.READ_CONTACTS" /> 
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
<uses-permission android:name="android.permission.RECEIVE_SMS" /> 
<uses-permission android:name="android.permission.READ_SMS" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" /> 
<uses-permission android:name="android.permission.WAKE_LOCK" /> 
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" /> 
    <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" android:protectionLevel="signature" /> 

<application android:name=".ApplicationStart" android:allowBackup="false" android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> 
    <activity android:name=".MainActivity" android:label="@string/app_name" android:launchMode="singleTop"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
    <activity android:name=".LoginActivity" android:label="@string/title_activity_login" 
     android:parentActivityName=".MainActivity" /> 
    <activity android:name=".ContactsSettingsActivity" android:label="Contact Settings" 
     android:launchMode="singleTop"> 
     <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.package.ContactsChalkboard" /> 
    </activity> 
    <activity android:name=".MyIntro" /> 
    <activity android:name=".ContactsChalkboard" /> 
    <activity android:name=".AlarmActivity" /> 
    <activity android:name=".AddContactActivity" android:parentActivityName=".MainActivity"> 
     <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.package.MainActivity" /> 
    </activity> 
    <activity android:name=".PictureNameActivity" android:label="@string/title_activity_picture_name" 
     android:parentActivityName=".LoginActivity"> 
     <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.package.LoginActivity" /> 
    </activity> 
    <activity android:name=".Test" /> 
    <activity android:name=".SettingsActivity" android:label="Settings"> 
     <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.package.MainActivity" /> 
    </activity> 
    <activity android:name="com.package.GeofenceActivity" android:label="@string/title_activity_geofence"> 
    </activity> 

    <service android:name=".LocationBatteryService" android:enabled="true" android:exported="true" /> 
    <service android:name=".MyFirebaseMessagingService"> 
     <intent-filter> 
      <action android:name="com.google.firebase.MESSAGING_EVENT" /> 
     </intent-filter> 
    </service> 
    <service android:name=".MyFirebaseInstanceIDService"> 
     <intent-filter> 
      <action android:name="com.google.firebase.INSTANCE_ID_EVENT" /> 
     </intent-filter> 
    </service> 
    <service android:name=".GeofenceTransitionsIntentService" /> 
    <receiver android:name=".AlarmReceiver" android:enabled="true" android:exported="true" /> 
    <receiver android:name=".BootReceiver" android:enabled="true" android:exported="true"> 
     <intent-filter> 
      <action android:name="android.intent.action.BOOT_COMPLETED" /> 
     </intent-filter> 
    </receiver> 
    <meta-data android:name="com.google.android.geo.API_KEY" android:value="API KEY VALUE" /> 
    <meta-data android:name="io.fabric.ApiKey" android:value="API KEY VALUE" /> 
</application> 
</manifest> 
+0

Czy używasz niestandardowej klasy aplikacji, jeśli tak, czy możesz dodać źródła do klasy aplikacji? Czy mógłbyś dodać kompletny plik Manifest? –

+0

Dodałem tę dodatkową informację teraz –

+0

Rozpoczynasz działanie od aplikacji: powoduje to otwarcie aplikacji. Umieść logikę związaną z rozpoczęciem działania (MainActivity lub Intro) w działaniu i skonfiguruj je jako działanie LAUNCHER (po prostu skopiuj to, co już zrobiłeś w pliku manifestu dla MainActivity). –

Odpowiedz

7

Cóż, nie ma gwarancji, że system cały czas będzie obsługiwał Twoją usługę. Gdy aplikacja zostanie zabita, a nowa lokalizacja zostanie dostarczona, lib usługi odtwarzania uruchomi aplikację i uruchomi usługę. Musisz usunąć startActivity ze swojej klasy aplikacji.

+0

To się zgadza. Nigdy nie startActivity() z aplikacji jako część zwykłej procedury uruchamiania. Zamiast tego użyj działania bez ekranu jako programu uruchamiającego. Sprawdź https://gist.github.com/chanakin/c44bf1c6a9a80d2640440b5aaa92c8ee na przykład kod. –