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>
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? –
Dodałem tę dodatkową informację teraz –
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). –