Android FileObserver does not trigger onEvent - java

I am trying to register a FileObserver inside of a service to monitor whenever a new photo has been saved to "/DCIM/Camera/".
So far I have tried everything I could find online. In my opinion it should already work...
i do request permissions in the manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<service android:name=".FileWatcherService"
android:enabled="true"
android:exported="false"/>
<!-- Declaring broadcast receiver for BOOT_COMPLETED event. -->
<receiver android:name=".StartupReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
my observer:
public class FileWatcherService extends Service {
static String PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/Camera/";
private static String TAG = "FileWatcher";
public static FileObserver fileObserver = new FileObserver(PATH, CREATE) {
#Override
public void onEvent(int i, #Nullable String s) {
Log.d(TAG, "eventttttt"); //never triggered
}
};
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy: service destroyed");
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: service created");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int res = super.onStartCommand(intent, flags, startId);
fileObserver.startWatching();
Log.d(TAG,"Service started!");
return Service.START_STICKY;
}
public static void start(Context ctx) {
Intent i = new Intent(ctx, FileWatcherService.class);
ctx.startService(i);
}
}
The main activity:
public class MainActivity extends AppCompatActivity {
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
Log.v(".","Permission: "+permissions[0]+ "was "+grantResults[0]);
FileWatcherService.start(getApplicationContext());
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
}
What am I missing? The service starts just fine.
Thanks for your help.

For locally confirming your changes, go to Settings->App info->Your app->Permissions and enable 'Storage' permissions.
Close your app completely (remove from tasks too) and then check if your code works.
What looks to be actually missing is requesting user for access to external storage.
Reference: https://developer.android.com/training/permissions/requesting

Related

startService() and stopService() not working properly

The problem I'm currently experiencing is that I am unable to start and stop the service of another class. I was able to run the application but I couldn't get the results I wanted, as the program didn't show any errors. I thought it was something wrong with my buttons at first, so i tried using System.out.println to see if i get any feedback, in which i did. Then, i decided to try it on my other class (location.java), the System.out.Println I used did not work, which probably means its not even working.
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private EditText input;
private Button start, stop;
private Intent intent;
public static int minute;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iniUI();
}
private void iniUI() {
input=findViewById(R.id.input);
start=findViewById(R.id.start);
stop=findViewById(R.id.stop);
start.setEnabled(false);
stop.setEnabled(false);
start.setOnClickListener(this);
stop.setOnClickListener(this);
intent=new Intent(this, Location.class);
permission();
}
#Override
public void onClick(View view) {
if(view.getId()==R.id.start) {
minute=Integer.parseInt(input.getText().toString());
startTracking();
}
else if(view.getId()==R.id.stop)
stopTracking();
}
private void permission(){
if(ContextCompat.checkSelfPermission(getApplicationContext(), ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED) {
start.setEnabled(true);
}
else{
ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION}, 0);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==0){
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
permission();
}
}
}
private void startTracking(){
startService(intent);
buttonAlt();
}
private void stopTracking() {
stopService(intent);
buttonAlt();
}
private void buttonAlt(){
start.setEnabled(!start.isEnabled());
stop.setEnabled(!start.isEnabled());
}}
Location.java
public class Location extends Service{ private Thread thread;
private LocationManager locationManager;
private double longitude, latitude;
private String dateTime, encodeData;
public Location() {
}
#Override
public void onCreate() {
super.onCreate();
thread = new Thread(runThread);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
thread.start();
return super.onStartCommand(intent, flags, startId);
}
private Runnable runThread = new Runnable() {
#Override
public void run() {
while (true) {
try {
System.out.println("Shutting down");
long sMinutes = MainActivity.minute * 60 * 1000;
Thread.sleep(sMinutes);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("Running");
sendLocation();
}
}
};
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
private void sendLocation() {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
#SuppressLint("MissingPermission")
android.location.Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
longitude=location.getLongitude();
latitude=location.getLatitude();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date=new Date(System.currentTimeMillis());
dateTime=sdf.format(date);
postData();
}
private void encodeData() throws UnsupportedEncodingException {
encodeData= URLEncoder.encode("datetime", "UTF-8") + "=" + URLEncoder.encode(dateTime, "UTF-8") +
"&" + URLEncoder.encode("latitude", "UTF-8") + "=" + URLEncoder.encode(Double.toString(latitude), "UTF-8") +
"&" + URLEncoder.encode("longitude", "UTF-8") + "=" + URLEncoder.encode(Double.toString(longitude), "UTF-8");
System.out.println("Lat:"+latitude);
System.out.println("Long:"+longitude);
}
private void postData(){
try {
encodeData();
URL url=new URL("A PHP SCRIPT TO OBTAIN MY LATITUDE AND LONGITUDE");
URLConnection urlConnection=url.openConnection();
urlConnection.setDoOutput(true);
OutputStreamWriter outputStreamWriter=new OutputStreamWriter(urlConnection.getOutputStream());
outputStreamWriter.write(encodeData);
outputStreamWriter.flush();
new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}}
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".Location"></activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
To sum it all up, both classes showed no errors, but only the MainActivity.java was working. Is there anything i could change about it to get it to work? I think it has something to do with my startService() and stopService().
It seems like in your Manifest file you have registered your service Location.java as an activity, it should work once you change that to service
<service android:name=".Location" />
instead of
<activity android:name=".Location"></activity>

How to receive LocalBroadcast in android service

I am trying to make an app in which I have a receiver which sends out a broadcast:
public class PhoneStateReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
try {
System.out.println("Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
Intent callIntent = new Intent("INCOMING_CALL");
callIntent.putExtra("number", incomingNumber);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
if ((state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))){
//Toast.makeText(context,"Call Received State",Toast.LENGTH_SHORT).show();
}
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
//Toast.makeText(context,"Call Idle State",Toast.LENGTH_SHORT).show();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
I also have a service running and I want to capture the broadcast in that service, I have tried the following but it does not work:
public class NotifierService extends Service
{
...//something goes here
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
LocalBroadcastManager.getInstance(this).registerReceiver(lbReceiver, new IntentFilter("INCOMING_CALL"));
return START_STICKY;
}
private BroadcastReceiver lbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals("INCOMING_CALL"))
{
//do something
}
}
};
Can someone please tell me the correct way to receive a broadcast in a service, if it is not possible to receive a broadcast then what else can i use ?
[UPDATE]
This is how my service is declared in the manifest
<service
android:name=".NotifierService"
android:enabled="true"
android:exported="true"
>
</service>

Background Service not working on MIUI 9.6 Redmi 4x

I have been searching in the entire web understanding why my background service is not working. When I close the application the service is killed without being called back from the Brodcast Receiver. This guide : https://www.quora.com/How-do-I-keep-an-app-running-in-the-background-in-MIUI shows three different methods and none of them is working for me. I'm sure that the application is perfectly working because it works fine with the emulator, same API 24, and it worked with a huawei aswell, again same API.
XML
<service
android:name="com.arvi.neverendingbackgroundservice.SensorService"
android:enabled="true"
android:exported="true"
android:stopWithTask="false">
</service>
<receiver
android:name="com.arvi.neverendingbackgroundservice.SensorRestartBroadcastReceiver"
android:enabled="true"
android:exported="true"
android:label="RestartServiceWhenStopped">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
Service
public class SensorService extends Service {
private Context ctx;
TimerCounter tc;
private int counter = 0;
private static final String TAG = SensorService.class.getSimpleName();
public SensorService() {
}
public SensorService(Context applicationContext) {
super();
ctx = applicationContext;
Log.i(TAG, "SensorService class");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate()");
tc = new TimerCounter();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.i(TAG, "onStartCommand()");
tc.startTimer(counter);
return START_STICKY;
}
#Override
public void onDestroy() {
Log.i(TAG, "serviceOnDestroy()");
super.onDestroy();
Intent broadcastIntent = new Intent(getApplicationContext(),SensorRestartBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
tc.stopTimerTask();
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.i(TAG, "serviceonTaskRemoved()");
// workaround for kitkat: set an alarm service to trigger service again
Intent intent = new Intent(getApplicationContext(), SensorService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 5000, pendingIntent);
super.onTaskRemoved(rootIntent);
}
#Override
public void onLowMemory() {
super.onLowMemory();
Log.i(TAG, "onLowMemory()");
}
}

Service doesn't work with Oreo 8.1 - The Detector does not work, nor does the process in the background

My call detector app is running fine on all android version except 8 Oreo. I get a deadlock paradigm: My detector is not called, and when I close the application the system kills it, not leaving it in the background.
I have already read the documentation from cable to tail https://developer.android.com/about/versions/oreo/background, I already looked a lot in google, and here in stack over flow, but no solution applied to my case, because of the required "dangerous" permissions.
My case seems simple: I have a detector, a service and the main with a button. I want it when the user calls a certain number, my main open.
What is the right way to fix this issue?
manifest.xml :
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service
android:name=".CallDetectionService"
android:enabled="true"
android:exported="false"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</activity>
</application>
CallDetectionService.java
public class CallDetectionService extends Service {
private CallDetector callDetector;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
callDetector = new CallDetector(this);
int r = super.onStartCommand(intent, flags, startId);
callDetector.start();
return r;
}
#Override
public void onDestroy() {
super.onDestroy();
callDetector.stop();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
CallDetector.java
public class CallDetector {
public static final String MY_PREF = "MY_PREF";
public static final String NUMBER_KEY = "NUMBER_KEY";
private SharedPreferences sharedPreferences;
public class OutgoingDetector extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
String compare_num = "12345678";
if (number.equals(compare_num)) {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
setResultData(null);
context.startActivity(i);
}
}
}
private Context ctx;
private OutgoingDetector outgoingDetector;
public CallDetector(Context ctx) {
this.ctx = ctx;
outgoingDetector = new OutgoingDetector();
}
public void start() {
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
ctx.registerReceiver(outgoingDetector, intentFilter);
}
public void stop(){
ctx.unregisterReceiver(outgoingDetector);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button button;
private TextView textView;
private boolean detecting = false;
private static final int MY_PERMISSIONS_REQUEST_CALL_PHONE = 0;
public boolean isPermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.CALL_PHONE)
== PackageManager.PERMISSION_GRANTED) {
Log.v("TAG", "Permission is granted");
return true;
} else {
Log.v("TAG", "Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 1);
return false;
}
} else {
Log.v("TAG", "Permission is granted");
return true;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
/* button.setOnClickListener(this); */
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.CALL_PHONE)) {
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CALL_PHONE},
MY_PERMISSIONS_REQUEST_CALL_PHONE);
}
}
String action = "START";
final Intent intent = new Intent(this, CallDetectionService.class);
intent.setAction(action);
startService(intent);
}
#Override
public void onResume() {
super.onResume();
SharedPreferences sharedPreferences = getSharedPreferences(CallDetector.MY_PREF, MODE_PRIVATE);
String number = sharedPreferences.getString(CallDetector.NUMBER_KEY, "URA VISUAL");
textView.setText(number);
}
}
What am I doing so wrong? I've been looking for a solution for 4 days and I still have not found anything.

Can't get passed Google Drive "Choose Account" screen in Android

I'm trying to incorporate the Google Drive API within my android application.
I have added google play services to my build.gradle along with getting the Android API key. My issue is within the OnResume() where the user picks the account.
It just keeps reprompting the user to choose account and does not proceed.
May anyone help me ?
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
private static final String TAG = "Google Drive Activity";
private static final int REQUEST_CODE_RESOLUTION = 1;
private static final int REQUEST_CODE_OPENER = 2;
private GoogleApiClient mGoogleApiClient;
private boolean fileOperation = false;
private DriveId mFileId;
public DriveFile file;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient != null) {
// disconnect Google API client connection
mGoogleApiClient.disconnect();
}
super.onPause();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
return;
}
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
#Override
public void onConnected(Bundle connectionHint) {
Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_LONG).show();
}
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
public void onClickCreateFile(View view){
fileOperation = true;
Drive.DriveApi.newDriveContents(mGoogleApiClient)
.setResultCallback(driveContentsCallback);
}
public void onClickOpenFile(View view){
fileOperation = false;
Drive.DriveApi.newDriveContents(mGoogleApiClient)
.setResultCallback(driveContentsCallback);
}
public void OpenFileFromGoogleDrive(){
IntentSender intentSender = Drive.DriveApi
.newOpenFileActivityBuilder()
.setMimeType(new String[] { "text/plain", "text/html" })
.build(mGoogleApiClient);
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_OPENER, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.w(TAG, "Unable to send intent", e);
}
}
final ResultCallback<DriveApi.DriveContentsResult> driveContentsCallback =
new ResultCallback<DriveApi.DriveContentsResult>() {
#Override
public void onResult(DriveApi.DriveContentsResult result) {
if (result.getStatus().isSuccess()) {
if (fileOperation == true) {
CreateFileOnGoogleDrive(result);
} else {
OpenFileFromGoogleDrive();
}
}
}
};
public void CreateFileOnGoogleDrive(DriveApi.DriveContentsResult result){
final DriveContents driveContents = result.getDriveContents();
new Thread() {
#Override
public void run() {
// write content to DriveContents
OutputStream outputStream = driveContents.getOutputStream();
Writer writer = new OutputStreamWriter(outputStream);
try {
writer.write("Hello abhay!");
writer.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("abhaytest2")
.setMimeType("text/plain")
.setStarred(true).build();
Drive.DriveApi.getRootFolder(mGoogleApiClient)
.createFile(mGoogleApiClient, changeSet, driveContents)
.setResultCallback(fileCallback);
}
}.start();
}
final private ResultCallback<DriveFolder.DriveFileResult> fileCallback = new
ResultCallback<DriveFolder.DriveFileResult>() {
#Override
public void onResult(DriveFolder.DriveFileResult result) {
if (result.getStatus().isSuccess()) {
Toast.makeText(getApplicationContext(), "file created: "+""+
result.getDriveFile().getDriveId(), Toast.LENGTH_LONG).show();
}
return;
}
};
#Override
protected void onActivityResult(final int requestCode,
final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_CODE_OPENER:
if (resultCode == RESULT_OK) {
mFileId = (DriveId) data.getParcelableExtra(
OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
Log.e("file id", mFileId.getResourceId() + "");
String url = "https://drive.google.com/open?id="+ mFileId.getResourceId();
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
}
This is my manifest. Blocking the API Key.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="edu.moli9479csumb.version1googledrive">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyD_2eJ5pPdRMysVwxxxxxxxxxxxxxx"/>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
You get the AccountSelector when the GoogleApiClient is not able to connect and has a resolution which requires the user to authorize the App for the API. This happens when you call "result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);" from the onConnectionFailed method.
Once the user selects the account your activity gets a callback with the code REQUEST_CODE_RESOLUTION. This code must be handled and you should call apiClient.connect() to connect again when this code is received in onActivityResult method.
See this for more details. I hope it works :)
You can easily force to prompt the user to choose account by using [Account Picker](https://developer.android.com/reference/android/accounts/AccountManager.html#newChooseAccountIntent(android.accounts.Account, java.util.ArrayList, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle)), common account picker is similar to the standard framework account picker introduced in newChooseAccountIntent. Returns an intent to an Activity that prompts the user to choose from a list of accounts. The caller will then typically start the activity by calling startActivityForResult(intent, ...);.
On success the activity returns a Bundle with the account name and type specified using keys KEY_ACCOUNT_NAME and KEY_ACCOUNT_TYPE.
The most common case is to call this with one account type, e.g.:
Intent intent = AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"},
false, null, null, null, null);
startActivityForResult(intent, SOME_REQUEST_CODE);
The account picker activity will return when the user has selected and/or created an account, and the resulting account name can be retrieved as follows:
protected void onActivityResult(final int requestCode, final int resultCode,
final Intent data) {
if (requestCode == SOME_REQUEST_CODE && resultCode == RESULT_OK) {
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
}
}
Here's the Official Google Sample code which uses the above code with concrete explanation how to use API: https://developers.google.com/drive/v3/web/quickstart/android#step_5_setup_the_sample
Take a look at your onResume() and onConnectionFailded() methods.
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
return;
}
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
What happens?
In onResume() you create GoogleApiClient and call connect(). Connection fails because you are not authorized with an account. Method onConnectionFailed() is executed which opens a resolution which is actually another activity called for result. You choose an acount but I guess authorization fails or is cancelled.
You return to your original activity and onResume() is executed. And you go a full circle again.
Why does your authorization fail? I guess because there is something wrong with your credentials. Go to Developer console and create O Auth credentials for your package and your key signature.

Categories