Logout and Clear GoogleAPIclient in Async Task - java

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.

Related

logout GoogleApiClient from another activity

I want build app with google account API. I done login with google tutorial and it work good but i try to logout account from another activity and it works too but method "onStart" in class LoginActivity.java login account back when i comment "onStart" its ok but when i try login again it login for account which was logged. For pass googleApiClient object to another activity i used singleton. Can you help me?
Code:
public void onStart() {
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
HomeActivity.java:
public class HomeActivity extends AppCompatActivity implements View.OnClickListener {
private GoogleApiClient mGoogleApiClient;// = state.getmGoogleApiClient();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
GlobalState state = ((GlobalState) getApplicationContext());
mGoogleApiClient = state.getmGoogleApiClient();
findViewById(R.id.sign_out_button).setOnClickListener(this);
}
private void signOut(){
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
GlobalState state = ((GlobalState) getApplicationContext());
state.setmGoogleApiClient(mGoogleApiClient);
Intent login = new Intent(getApplicationContext(), LoginActivity.class);
login.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(login);
finish();
}
});
}
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.sign_out_button:
signOut();
break;
}
}
change onStart() with
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
i resolve it by add onStart in HomeActivity:
#Override
protected void onStart() {
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
mGoogleApiClient.connect();
super.onStart();
}

how to solve for mLastLocation, mLatitudeText, mLongitudeText in getting last location

I am currently trying to follow along this tutorial to get last location of android device - https://developer.android.com/training/location/retrieve-current.html#play-services - but I cannot get past the last part.
My code:
package com.example.prouser.driveapp;
public class MainActivity extends AppCompatActivity implements ConnectionCallbacks {
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
super.onStart();
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
public void onConnected(Bundle connectionHint) {
if (mLastLocation != null) {
mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));
}
}
// Create an instance of GoogleAPIClient.
GoogleApiClient mGoogleApiClient = new GoogleApiClient() {
#Override
public boolean hasConnectedApi(#NonNull Api<?> api) {
return false;
}
#NonNull
#Override
public ConnectionResult getConnectionResult(#NonNull Api<?> api) {
return null;
}
#Override
public void connect() {
}
#Override
public ConnectionResult blockingConnect() {
return null;
}
#Override
public ConnectionResult blockingConnect(long l, #NonNull TimeUnit timeUnit) {
return null;
}
#Override
public void disconnect() {
}
#Override
public void reconnect() {
}
#Override
public PendingResult<Status> clearDefaultAccountAndReconnect() {
return null;
}
#Override
public void stopAutoManage(#NonNull FragmentActivity fragmentActivity) {
}
#Override
public boolean isConnected() {
return false;
}
#Override
public boolean isConnecting() {
return false;
}
#Override
public void registerConnectionCallbacks(#NonNull ConnectionCallbacks connectionCallbacks) {
}
#Override
public boolean isConnectionCallbacksRegistered(#NonNull ConnectionCallbacks connectionCallbacks) {
return false;
}
#Override
public void unregisterConnectionCallbacks(#NonNull ConnectionCallbacks connectionCallbacks) {
}
#Override
public void registerConnectionFailedListener(#NonNull OnConnectionFailedListener onConnectionFailedListener) {
}
#Override
public boolean isConnectionFailedListenerRegistered(#NonNull OnConnectionFailedListener onConnectionFailedListener) {
return false;
}
#Override
public void unregisterConnectionFailedListener(#NonNull OnConnectionFailedListener onConnectionFailedListener) {
}
#Override
public void dump(String s, FileDescriptor fileDescriptor, PrintWriter printWriter, String[] strings) {
}
};
if(mGoogleApiClient==null)
{
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener((OnConnectionFailedListener) this)
.addApi(LocationServices.API)
.build();
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
Try this:
public class MainActivity extends AppCompatActivity implements
ConnectionCallbacks, OnConnectionFailedListener {
protected static final String TAG = "MainActivity";
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Represents a geographical location.
*/
protected Location mLastLocation;
protected String mLatitudeLabel;
protected String mLongitudeLabel;
protected TextView mLatitudeText;
protected TextView mLongitudeText;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
mLatitudeLabel = getResources().getString(R.string.latitude_label);
mLongitudeLabel = getResources().getString(R.string.longitude_label);
mLatitudeText = (TextView) findViewById((R.id.latitude_text));
mLongitudeText = (TextView) findViewById((R.id.longitude_text));
buildGoogleApiClient();
}
/**
* Builds a GoogleApiClient. Uses the addApi() method to request the LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) {
// Provides a simple way of getting a device's location and is well suited for
// applications that do not require a fine-grained location and that do not need location
// updates. Gets the best and most recent location currently available, which may be null
// in rare cases when a location is not available.
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
mLatitudeText.setText(String.format("%s: %f", mLatitudeLabel,
mLastLocation.getLatitude()));
mLongitudeText.setText(String.format("%s: %f", mLongitudeLabel,
mLastLocation.getLongitude()));
} else {
Toast.makeText(this, R.string.no_location_detected, Toast.LENGTH_LONG).show();
}
}
#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());
}
#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();
}
}
You have a complete example here:
https://github.com/googlesamples/android-play-location

Started service does not work

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.

Why can't I call this Service from my Activity?

I've tried calling this Service in two different ways, but it didn't seem to work.
The first way was:
startService(new Intent(getBaseContext(), LocationService.class));
for which I get an error saying `
Caused by: `java.lang.IllegalStateException: GoogleApiClient is not connected yet.
Then I tried this:
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.parseapp.eseen.eseen.service.LocationService");
startService(serviceIntent);
Also it didn't work, in contrary absolutely nothing happens, nothing shows up in logcat. Can anyone help?
Here's the whole code:
LocationService.class
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
// LogCat tag
private static final String TAG = LocationService.class.getSimpleName();
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
private static int DISPLACEMENT = 10; // 10 meters
#Override
public void onCreate() {
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
togglePeriodicLocationUpdates();
}
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
private void togglePeriodicLocationUpdates() {
mGoogleApiClient.connect();
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
startLocationUpdates();
Log.d(TAG, "Periodic location updates started!");
} else {
mRequestingLocationUpdates = false;
// Stopping the location updates
stopLocationUpdates();
Log.d(TAG, "Periodic location updates stopped!");
}
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
protected void startLocationUpdates() {
mGoogleApiClient.connect();
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnected(Bundle arg0) {
createLocationRequest();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getApplicationContext(), "Location changed!",
Toast.LENGTH_SHORT).show();
}
#Override
public boolean stopService(Intent name) {
return super.stopService(name);
}
SearchActivity.class
button = (Button)findViewById(R.id.buttonPressed);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.parseapp.eseen.eseen.service.LocationService");
startService(serviceIntent);
}
});
AndroidManifest.xml
<service android:name=".LocationService">
<intent-filter>
<action android:name=".LocationService"> </action>
</intent-filter>
</service>
Your first attempt to start the service using the class name worked:
startService(new Intent(getBaseContext(), LocationService.class));
The exception occurred after the service started executing. Your code cannot use LocationServices until the GoogleApi connection is successful, namely after onConnected() is called. Your code calls connect() multiple times before getting to startLocationUpdates(), but does not wait for onConnected() to be called. That method is the notification you receive when the connection has been made and LocationServices can be used.
This demo code is for an AsyncTask, not a Service, but gives an idea of how the connection processing can be done using a CountDownLatch.
you package name com.parseapp.eseen.eseen
and You are tryng to call using com.parseapp.eseen.eseen.service.LocationService as action but you mentioned in Manifest as .LocationService that means you should call using com.parseapp.eseen.eseen.LocationService
in startLocationUpdates(); you are calling connect again and requesting api before connecting
request for locationupdates from onConnected method
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);

Getting Current Location inside a Service in android

I'm trying to get the current GPS location of a phone inside a android service.
I try to do it like here:
Getting Repeated Current Location inside a Service in android?
My service looks like this:
public class MeasurementService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
private Feedback feedback;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
feedback = new Feedback();
if (isNetworkAvailable()) {
new MeasuringTask().execute();
}
return Service.START_NOT_STICKY;
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager
.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
}
#Override
public void onConnected(Bundle arg0) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(2000);
...
}
#Override
public void onConnectionSuspended(int arg0) {
}
#Override
public void onDestroy() {
super.onDestroy();
mGoogleApiClient.disconnect();
}
#Override
public void onLocationChanged(Location arg0) {
// TODO Auto-generated method stub
}
private class MeasuringTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
//network access
}
}
I start my service through a broadcast receiver everytime the phone is started.
When I execute the app I get a java.lang.NoClassDefFoundError: packet.MeasurementService
If I try to change this part:
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
To this:
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(MeasurmentService.class)
.addOnConnectionFailedListener(MeasurmentService.class)
.addApi(LocationServices.API)
.build();
Like recommended in the other post, I get:
The method addConnectionCallbacks(GoogleApiClient.ConnectionCallbacks) in the type GoogleApiClient.Builder is not applicable for the arguments (Class)
Ideas? Thanks a lot!
Make sure the LocationListener your service implemented is from com.google.android.gms.location.
Move the code to onCreate function.
#Override
public void onCreate() {
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
I have a sample application on github, please click here.
I finally figured it out, it was a build error which I wasn't able to resolve.
My solution:
I migrated the project from Eclipse to Android Studio.

Categories

Resources