I have and activity that starts an IntentService that is supposed to update the location regularly and post it to Firebase. Somehow it does not work. There is no exception, no error or anything. It just does not do what I want.
Here is my main activity:
public class MainActivity extends AppCompatActivity {
private Intent mTrackingIntent;
//UI
protected Button mStartTrackingButton;
protected Button mStopTrackingButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Locate the UI widgets
mStartTrackingButton = (Button) findViewById(R.id.start_button);
mStopTrackingButton = (Button) findViewById(R.id.stop_button);
mTrackingIntent = new Intent(this, TrackingService.class);
}
public void startButtonHandler(View view) {
startService(mTrackingIntent);
}
public void stopButtonHandler(View view) {
stopService(mTrackingIntent);
}
Here is TrackingService:
public class TrackingService extends IntentService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private FirebaseAuth mFirebaseAuth;
private FirebaseUser mFirebaseUser;
public static final String SENDER_EMAIL = "*************";
public static final String SENDER_PASSWORD = "******************";
private DatabaseReference mDatabase;
private String mUserId;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000; //upper bound
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2; //lower bound
private String mLastUpdateTime;
private String mLastUpdateYear;
private String mLastUpdateMonth;
private String mLastUpdateDay;
private static final SimpleDateFormat mYearFormat = new SimpleDateFormat("yyyy");
private static final SimpleDateFormat mMonthFormat = new SimpleDateFormat("MM");
private static final SimpleDateFormat mDayFormat = new SimpleDateFormat("dd");
private static final SimpleDateFormat mTimeFormat = new SimpleDateFormat("HH:mm:ss");
private Location mLastUpdateLocation;
public TrackingService() {
super("TrackingService");
}
#Override
public void onDestroy() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
super.onDestroy();
}
#Override
protected void onHandleIntent(Intent intent) {
//Initialize Firebase Auth
initFirebase();
//connect to the Google API
buildGoogleApiClient();
startLocationUpdates();
}
private void initFirebase() {
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = mFirebaseAuth.getCurrentUser();
mDatabase = FirebaseDatabase.getInstance().getReference();
if (mFirebaseUser == null) {
//log in to Firebase
mFirebaseAuth.signInWithEmailAndPassword(SENDER_EMAIL, SENDER_PASSWORD);
mFirebaseUser = mFirebaseAuth.getCurrentUser();
mUserId = mFirebaseUser.getUid();
}
mUserId = mFirebaseUser.getUid();
}
protected void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
//Set update interval bounds and accuracy
createLocationRequest();
mGoogleApiClient.connect();
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private void startLocationUpdates() {
//check if permission to get the location is granted
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onLocationChanged(Location location) {
Date updateDate = Calendar.getInstance().getTime();
mLastUpdateTime = mTimeFormat.format(updateDate);
mLastUpdateYear = mYearFormat.format(updateDate);
mLastUpdateMonth = mMonthFormat.format(updateDate);
mLastUpdateDay = mDayFormat.format(updateDate);
mLastUpdateLocation = location;
//post to Firebase
postToFirebase(location);
}
public void postToFirebase(Location location) {
mDatabase.child("users").child(mUserId).child(mLastUpdateYear).child(mLastUpdateMonth).child(mLastUpdateDay).child("trackRecords").push().setValue(location);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
IntentService is not really the right tool for this job. The way IntentService works is this. When an Intent is received from startService(), it will use a background thread to handle the intent (starting in onHandleIntent()), and when that method returns, the IntentService stops itself and shuts down if there are no more intents in its queue.
Instead you probably need to create a custom service that manages its lifecycle so that it performs its background work so that it stays active until it's told to stop.
Related
I am working on a project where I want to collect sensor data with coordinates and save them to a csv file.
The app was working perfectly before I started coding for getting the location.
I am using location manager but every time I install this app on my device the application just doesn't seem to work. I disappears after few seconds of installation.
Also note that I am saving the sensor data in every 20 milliseconds so should I collect the coordinate data in the same rate?
Sorry to put the whole code but I need help! Please let me know where should I make changes?
public class MainActivity extends AppCompatActivity implements SensorEventListener, LocationListener {
private SensorManager sensorManager;
private Sensor magnetic;
//Location
LocationManager locationManager;
Handler handler;
Location location;
double latitude;
double longitude;
// --o
private int counter = 1;
private boolean recording = false;
private boolean counterOn = false;
private float magValues[] = new float[3];
private Context context;
private static final int REQUESTCODE_STORAGE_PERMISSION = 1;
Collection<String[]> magneticData = new ArrayList<>();
private CsvWriter csvWriter = null;
public static DecimalFormat DECIMAL_FORMATTER;
TextView stateText;
EditText fileIDEdit;
//Location
TextView lat;
TextView lon;
//--o
TextView magText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Location
handler = new Handler();
lat = (TextView) findViewById(R.id.latitudeTextView);
lon = (TextView) findViewById(R.id.longitudeTextView);
//--o
findViewById(R.id.button).setOnClickListener(listenerStartButton);
findViewById(R.id.button2).setOnClickListener(listenerStopButton);
fileIDEdit = (EditText)findViewById(R.id.editText);
magText = (TextView) findViewById(R.id.textView3);
stateText = (TextView) findViewById(R.id.textView);
stateText.setText("Stand by");
context = this;
// Sensor
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
symbols.setDecimalSeparator('.');
DECIMAL_FORMATTER = new DecimalFormat("#.000", symbols);
//Location
handler.postDelayed(runLocation, 1000);
}
public Runnable runLocation = new Runnable() {
#Override
public void run() {
lat.setText(String.valueOf(latitude));
lon.setText(String.valueOf(longitude));
Toast.makeText(MainActivity.this, "location check", Toast.LENGTH_SHORT).show();
MainActivity.this.handler.postDelayed(MainActivity.this.runLocation, 5000);
}
};
private View.OnClickListener listenerStartButton = new View.OnClickListener() {
#Override
public void onClick(View v) {
recording = true;
stateText.setText("Recording started");
stateText.setTextColor(Color.parseColor("#FF0000"));
}
};
#Override
public void onSensorChanged(SensorEvent event) {
long timeInMillisec = (new Date()).getTime() + (event.timestamp - System.nanoTime()) / 1000000L;
// Some sensor operations
}
//magneticData.add(new String[]{String.valueOf(timeInMillisec), String.valueOf(magValues[0]), String.valueOf(magValues[1]), String.valueOf(magValues[2])});
#SuppressLint("SimpleDateFormat") SimpleDateFormat logLineStamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS", Locale.getDefault());
//logLineStamp.setTimeZone(TimeZone.getTimeZone("UTC"));
magneticData.add(new String[]{logLineStamp.format(new Date(timeInMillisec)), String.valueOf(x), String.valueOf(y), String.valueOf(z), String.valueOf(magnitude), String.valueOf(latitude), String.valueOf(longitude)});
counter++;
}
}
// Checks if the the storage permissions are given or not by the user
// It will request the use if not
private static boolean storagePermitted(Activity activity){
// Check read write permission
}
//Check Location
private void getLocation() {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION_PERMISSION);
} else {
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null){
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// Added Later
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onLocationChanged(Location location) {
latitude = location.getLatitude();
longitude = location.getLongitude();
lat.setText(String.valueOf(latitude));
lon.setText(String.valueOf(longitude));
Toast.makeText(MainActivity.this, "location changed: "+latitude+" "+longitude, Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
}
How do I get the coordinates of my current location in yandex mapkit ?
There is very little information on the Internet, please help, can you have projects ?
public class MapActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final double DESIRED_ACCURACY = 0;
private static final long MINIMAL_TIME = 1000;
private static final double MINIMAL_DISTANCE = 1;
private static final boolean USE_IN_BACKGROUND = false;
public static final int COMFORTABLE_ZOOM_LEVEL = 18;
private final String MAPKIT_API_KEY = "";
private MapView mapView;
private CoordinatorLayout rootCoordinatorLayout;
private LocationManager locationManager;
private LocationListener myLocationListener;
private Point myLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MapKitFactory.setApiKey(MAPKIT_API_KEY);
MapKitFactory.initialize(this);
setContentView(R.layout.map);
mapView = (MapView) findViewById(R.id.mapview);
locationManager = MapKitFactory.getInstance().createLocationManager();
myLocationListener = new LocationListener() {
#Override
public void onLocationUpdated(Location location) {
if (myLocation == null) {
moveCamera(location.getPosition(), COMFORTABLE_ZOOM_LEVEL);
}
myLocation = location.getPosition(); //this user point
Log.w(TAG, "my location - " + myLocation.getLatitude() + "," + myLocation.getLongitude());
}
#Override
public void onLocationStatusUpdated(LocationStatus locationStatus) {
if (locationStatus == LocationStatus.NOT_AVAILABLE) {
System.out.println("sdncvoadsjv");
}
}
};
}
#Override
protected void onStart() {
super.onStart();
MapKitFactory.getInstance().onStart();
mapView.onStart();
subscribeToLocationUpdate();
}
#Override
protected void onStop() {
super.onStop();
MapKitFactory.getInstance().onStop();
locationManager.unsubscribe(myLocationListener);
mapView.onStop();
}
public void onFabCurrentLocationClick(View view) {
if (myLocation == null) {
return;
}
moveCamera(myLocation, COMFORTABLE_ZOOM_LEVEL);
}
private void subscribeToLocationUpdate() {
if (locationManager != null && myLocationListener != null) {
locationManager.subscribeForLocationUpdates(DESIRED_ACCURACY, MINIMAL_TIME, MINIMAL_DISTANCE, USE_IN_BACKGROUND, FilteringMode.OFF, myLocationListener);
}
}
private void moveCamera(Point point, float zoom) {
mapView.getMap().move(
new CameraPosition(point, zoom, 0.0f, 0.0f),
new Animation(Animation.Type.SMOOTH, 1),
null);
}
}
I have created a database which stores user information like email, password, latitude, longitude and plant location. plant location is that when user click on map then latitude and longitude of that location is saved in plant location.
Database Image Before:
But when I signout the current user and then login back again with the same email then plant location was removed. As you can now plant location and its child got deleted.
Database After :
Help me please with this.
MapsActivity.java
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
NavigationView.OnNavigationItemSelectedListener,
AppCompatCallback {
private static final String Tag = "MapsActivity";
private GoogleMap mMap;
GeoFire geoFire;
SharedPrefrence mShared;
public AppCompatDelegate delegate;
private final float DEFAULT_ZOOM = 15f;
private static final String FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
private static final String COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
public Boolean mLocationPermissionGranted = false;
private static final int LOCATION_PERMISSION_REQUESTCODE = 1234;
public static DatabaseReference mReference,user_ref;
DrawerLayout drawerLayout;
boolean doubleBackToExitPressedOnce = false;
Toolbar tool;
FirebaseAuth mAuth;
ImageView img;
FirebaseAuth.AuthStateListener authStateListener;
ActionBarDrawerToggle actionBarDrawerToggle;
String userID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
delegate = AppCompatDelegate.create(this, this);
delegate.onCreate(savedInstanceState);
delegate.setContentView(R.layout.activity_maps);
getlocationpermission();
mShared=new SharedPrefrence(this);
mAuth = FirebaseAuth.getInstance();
userID=mAuth.getCurrentUser().getUid();
img = findViewById(R.id.tree_button);
mReference = FirebaseDatabase.getInstance().getReference().child("UserData");
user_ref=FirebaseDatabase.getInstance().getReference().child("You");
tool = findViewById(R.id.toolbar);
delegate.setSupportActionBar(tool);
delegate.getSupportActionBar().setDisplayShowTitleEnabled(true);
drawerLayout = findViewById(R.id.drawer);
actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.open, R.string.close);
drawerLayout.addDrawerListener(actionBarDrawerToggle);
actionBarDrawerToggle.setDrawerIndicatorEnabled(true);//use for toggling navbar
actionBarDrawerToggle.syncState();
NavigationView navigationView = findViewById(R.id.navigation);
navigationView.setNavigationItemSelectedListener(this);
authStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() == null) {
Toast.makeText(getApplicationContext(), "Logged Out", Toast.LENGTH_SHORT).show();
Intent i = new Intent(MapsActivity.this, Login.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
}
}
};
geoFire = new GeoFire(user_ref);
}
void initMap() {
SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
supportMapFragment.getMapAsync(MapsActivity.this);
}
private void getlocationpermission() {
String[] permission = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
if (ContextCompat.checkSelfPermission(this.getApplicationContext(), FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this.getApplicationContext(), COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
initMap();
} else {
ActivityCompat.requestPermissions(this, permission, LOCATION_PERMISSION_REQUESTCODE);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
mLocationPermissionGranted = false;
switch (requestCode) {
case LOCATION_PERMISSION_REQUESTCODE: {
if (grantResults.length > 0) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
return;
}
}
mLocationPermissionGranted = true;
initMap();
}
}
}
}
private void getDeviceLocationMethod() {
Log.d(Tag, "getting the device location");
FusedLocationProviderClient mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
final Task<Location> location = mFusedLocationProviderClient.getLastLocation();
location.addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
if (task.isSuccessful()) {
Location currentlocation = task.getResult();
User_Data user_data=new User_Data(mShared.getUser_pass(),mShared.getUser_email(),currentlocation.getLatitude(),
currentlocation.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(currentlocation.getLatitude(),
currentlocation.getLongitude()), DEFAULT_ZOOM));
DatabaseReference user=FirebaseDatabase.getInstance().getReference("UserData");
user.child(userID).setValue(user_data);
addMarker(new LatLng(currentlocation.getLatitude(), currentlocation.getLongitude()), mMap);
} else {
Toast.makeText(MapsActivity.this, "Error while finding the location" + task.getException(), Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
getDeviceLocationMethod();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
location_to_firebase(googleMap);
}
private void location_to_firebase(final GoogleMap google_map) {
int height = 150;
int width = 150;
final BitmapDrawable bitmapdraw = (BitmapDrawable) getResources().getDrawable(R.drawable.icon);
Bitmap b = bitmapdraw.getBitmap();
final Bitmap smallMarker = Bitmap.createScaledBitmap(b, width, height, false);
google_map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
Marker marker = google_map.addMarker(new MarkerOptions().position(point));
marker.setIcon(BitmapDescriptorFactory
.fromBitmap(smallMarker));
final LatLng latLng = marker.getPosition();
final DatabaseReference newPost = mReference.child(userID);
newPost.child("plant location").push().setValue(latLng);
}
});
mReference.child(userID).child("plant location").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot s:dataSnapshot.getChildren()){
final LatLng lng = new LatLng(s.child("latitude").getValue(Double.class),
s.child("longitude").getValue(Double.class));
google_map.addMarker(new MarkerOptions().
position(lng).title(s.getKey())).setIcon(BitmapDescriptorFactory.fromBitmap(smallMarker));
google_map.addCircle(new CircleOptions().center(lng).radius(500).strokeColor(Color.TRANSPARENT));
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Login.java
public class Login extends AppCompatActivity {
EditText _email, _password;
Button _submit,_signup;
SharedPrefrence mShared;
private FirebaseAuth mAuth;
private static final int LOCATION_PERMISSION_REQUESTCODE=1234;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
_email = findViewById(R.id.email);
_password = findViewById(R.id.password);
_submit = findViewById(R.id.login);
_signup=findViewById(R.id.signup);
mShared=new SharedPrefrence(this);
_signup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Login.this,Signup.class));
}
});
mAuth = FirebaseAuth.getInstance();
_submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startSignin();
}
});
runtimepermission();
}
private void startSignin() {
final String email = _email.getText().toString();
final String pass = _password.getText().toString();
if (TextUtils.isEmpty(email) || TextUtils.isEmpty(pass)) {
Toast.makeText(this, "Invalid Email or Password", Toast.LENGTH_SHORT).show();
} else {
mAuth.signInWithEmailAndPassword(email, pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
Toast.makeText(Login.this, "SigninProblem", Toast.LENGTH_SHORT).show();
}
else
{
mShared.saveEmail(Login.this,email);
mShared.savePass(Login.this,pass);
Intent i=new Intent(Login.this,MapsActivity.class);
startActivity(i);
finish();
}
}
}).addOnCanceledListener(new OnCanceledListener() {
#Override
public void onCanceled() {
Toast.makeText(Login.this,"Login Canceled",Toast.LENGTH_LONG).show();
}
});
}
}
But when I signout the current user and then login back again with the same email then plant location was removed.
The problem isn't happening when you login back is happening everytime your map is ready. You are calling getDeviceLocationMethod() right in your onMapReady() method which means that everytime your map is ready, you are creating a new User_Data object, meaning that you are overriding the existing user from the database. That's way all the data within plant location node is deleted. To solve this, simply chech if the user already exist. If it doesn't, add it to the database otherwise take no action.
I have code which is working fine for logout of google apiclient, but it left one activity opened after execution, either can some one tell where should I put finish(); to kill that activity or how can I do whole thing in async task. I tried to do with async but got error as client not connected.
Here is code for logout with class extending to activity:
public class GoogleDriveLogoutBackup extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "drive-quickstart";
private GoogleApiClient mGoogleApiClient;
#Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addScope(Drive.SCOPE_APPFOLDER)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle connectionHint) {
Log.d("Connected","Here");
mGoogleApiClient.clearDefaultAccountAndReconnect();
finish();
}
#Override
public void onConnectionSuspended(int i) {
finish();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
And here is code which I m using for Async class which I giving me error:
public class GoogleDriveLogout extends AsyncTask<Void, Void, Void> {
private static final String TAG = "drive-quickstart";
private GoogleApiClient mGoogleApiClient;
private Context mcontext;
public GoogleDriveLogout(Context context) {
this.mcontext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(mcontext)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addScope(Drive.SCOPE_APPFOLDER)
.build();
}
mGoogleApiClient.connect();
}
#Override
protected Void doInBackground(Void... params) {
Log.d("Connected", "Here");
mGoogleApiClient.clearDefaultAccountAndReconnect();
return null;
}
}
I able to did it now by using calling ApiClientAsyncTask which is provided by google itself.
I am trying to implement a app which updates user location at every 15 seconds,stores data to database and show it to listview in my activity.
Location should always update even activity destroys,for that i have created LocationService class.
The problem is I am able to get updates and also able to store into database but i am unable to show these updates in listview at runtime means i want list should refresh at every 15 sec and show it to UI..
Also when I get details from database I am unable to get latest detail instead i get whole arraylist every time which affects my activity response.I want that only newly added data will be fetch from database so that it will take less time in loading but I want to display all data to list everytime.
I have implement a thread (Commented code)which fetch data and show to listview but this is not right way to update UI..please suggest me a way so that i can refresh my list when new data is added into database
This is my activity
public class MainActivity extends Activity {
List<MyLocation> locationList = new ArrayList();
ListView mList;
LocationAdapter adapter;
BroadcastReceiver receiver;
LocationService mService;
boolean mBound = false;
private DbHelper dbHelper;
private Button updateLocation;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
LocationService.LocalBinder binder = (LocationService.LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
updateLocation = (Button) findViewById(R.id.update_location);
mList = (ListView) findViewById(R.id.listView);
dbHelper = new DbHelper(this);
updateLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
locationList = mService.displayLocation();
adapter = new LocationAdapter(MainActivity.this, locationList);
mList.setAdapter(adapter);
}
});
/*
Thread mThread = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(500);
runOnUiThread(new Runnable() {
#Override
public void run() {
locationList = dbHelper.getLocationDetails();
Collections.reverse(locationList);
adapter = new LocationAdapter(MainActivity.this, locationList);
mList.setAdapter(adapter);
}
});
}
} catch (InterruptedException e) {
}
}
};
mThread.start();*/
}
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, LocationService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
}
LocationService
public class LocationService extends Service implements LocationListener, GoogleApiClient.ConnectionCallbacks {
private final IBinder mBinder = new LocalBinder();
ArrayList<MyLocation> locationList = new ArrayList<>();
private DbHelper dbHelper;
private Location mLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private String TAG = "Service";
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addApi(LocationServices.API).build();
mGoogleApiClient.connect();
dbHelper = new DbHelper(this);
createLocationRequest();
displayLocation();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "service destroy");
}
public List<MyLocation> displayLocation() {
mLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLocation != null) {
double latitude = mLocation.getLatitude();
double longitude = mLocation.getLongitude();
String lastUpdateTime = DateFormat.getTimeInstance().format(new Date());
dbHelper.insertLocationDetails(longitude, latitude, lastUpdateTime);
locationList = dbHelper.getLocationDetails();
return locationList;
} else {
return null;
}
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Connected to update");
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
public void onLocationChanged(Location location) {
mLocation = location;
Toast.makeText(getApplicationContext(), "Location changed",
Toast.LENGTH_SHORT).show();
displayLocation();
}
public void onConnected(Bundle arg0) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
public class LocalBinder extends Binder {
public LocationService getService() {
return LocationService.this;
}
}
}
Dbhelper
public class DbHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String LONGITUDE = "longitude";
private static final String LATITUDE = "latitude";
private static final String LOCATION_CHANGE_TIME = "location_change_time";
private static final String LOCATION_DETAIL_TABLE = "location_detail_table";
private static final String CREATE_TABLE_LOCATION = "CREATE TABLE "
+ LOCATION_DETAIL_TABLE + " (" + LONGITUDE + " TEXT,"
+ LOCATION_CHANGE_TIME + " TEXT,"
+ LATITUDE + " TEXT)";
public static String DATABASE_NAME = "Location_database";
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(CREATE_TABLE_LOCATION);
}
public void insertLocationDetails(double longitude, double latitude, String time) {
SQLiteDatabase database = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(LONGITUDE, longitude);
values.put(LATITUDE, latitude);
values.put(LOCATION_CHANGE_TIME, time);
long id= database.insert(LOCATION_DETAIL_TABLE, null, values);
System.out.println("Newly added item id "+id);
database.close();
}
public ArrayList<MyLocation> getLocationDetails() {
ArrayList<MyLocation> locationList = new ArrayList();
String selectQuery = "SELECT * FROM " + LOCATION_DETAIL_TABLE;
SQLiteDatabase database = this.getReadableDatabase();
Cursor cursor = database.rawQuery(selectQuery, null);
if (cursor.moveToNext()) {
do {
MyLocation location = new MyLocation();
String longitude = cursor.getString(cursor
.getColumnIndexOrThrow(LONGITUDE));
String latitude = cursor.getString(cursor.getColumnIndexOrThrow(LATITUDE));
String time = cursor.getString(cursor
.getColumnIndexOrThrow(LOCATION_CHANGE_TIME));
location.setLatitude(latitude);
location.setLongitude(longitude);
location.setLastUpdatedTime(time);
locationList.add(location);
} while (cursor.moveToNext());
}
if (cursor != null) {
cursor.close();
}
database.close();
return locationList;
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
In your case, you can use ContentProvider and implements LoaderManager.LoaderCallbacks in your activity.
#Nullable
#Override
public Uri insert(Uri uri, ContentValues values) {
db = dbHelper.getWritableDatabase();
String table = uri.getLastPathSegment();
long rowID = db.insert(table, null, values);
Uri CONTENT_URI = Uri.parse("content://"
+ AUTHORITY + "/" + table);
Uri resultUri = ContentUris.withAppendedId(CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(resultUri, null);
return resultUri;
}
Line
getContext().getContentResolver().notifyChange(resultUri, null);
in ContentProvider will cause requery data. And using SimpleAdapter in activity will update your UI.
You can use Callback for this purpose.
Define some interface like
public class LocationInterface(){
public void sendLocationDetails(Long lat, Long lon, String time);
}
Now let your Activity implement this interface.
public class MyActivity implements LocationInterface {
#Override
public void sendLocationDetails(Long lat, Long lon, String time){
//At this point, you have the required details
}
}
Now in LocationService.java you need to pass this interface as an argument.
public class LocationService {
private LocationInterface locationInterface;
LocationInterface(LocationInterface locationInterface){
this.locationInterface = locationInterface;
}
}
Now whenever you call displayLocation() method, you can call this interface and send data to the activity.
public List<MyLocation> displayLocation() {
mLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLocation != null) {
double latitude = mLocation.getLatitude();
double longitude = mLocation.getLongitude();
String lastUpdateTime = DateFormat.getTimeInstance().format(new Date());
//At this point, you are calling the interface.
locationInterface.sendDetails(latitude,longitude,lastUpdateTime);
dbHelper.insertLocationDetails(longitude, latitude, lastUpdateTime);
locationList = dbHelper.getLocationDetails();
return locationList;
} else {
return null;
}
}