I've implemented google drive into my android application and it work pretty nice, but I'm trying to figure out a way to run an upload/download in a background thread so that I can leave an activity and do something else on my app. The problem is, drive needs the activity reference in case of exceptions, such as UserRecoverableAuthIOException.
Here's the issue I cannot understand. Here's some try/catch code:
try {
//...drive api stuff here
} catch (UserRecoverableAuthIOException e) {
possibleException = e;
try {
e.getIntent();
} catch ( NullPointerException e2 ) { //this is the crazy part
// e.getIntent() should not throw a nullpointer
e2.printStackTrace();
possibleException = e2;
}
onActivityRestartWhat = RESTART_IMPORT;
// just a note i do handle this exception properly in another section of a code when there is an intent.
} catch (FileNotFoundException e) {
possibleException = e;
e.printStackTrace();
} catch (IOException e) {
possibleException = e;
e.printStackTrace();
}
What I can't figure out is why UserRecoverableAuthIOException is throwing a NullPointerException whey I try to access getIntent.
More Info
I do catch UserRecoverableAuthIOException when more authentication is needed and request it via the startActivityForResult method. Also, this exception is thrown only if I back out of the activity that has started, aka destroy the activity. Basically, I have a process that uploads/downloads drive files in a thread and if I don't leave the activity until completion it works, if I destroy the activity via the back button then I get this exception.
Stack Trace
07-10 14:45:32.903: W/System.err(1450): java.lang.NullPointerException
07-10 14:45:32.913: W/System.err(1450): at android.content.Intent.<init> (Intent.java:3529)
07-10 14:45:32.913: W/System.err(1450): at com.google.android.gms.auth.UserRecoverableAuthException.getIntent(Unknown Source)
07-10 14:45:32.913: W/System.err(1450): at com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException.getIntent(UserRecoverableAuthIOException.java:62)
07-10 14:45:32.913: W/System.err(1450): at my.app.DriveHelper$2.run(DriveHelper.java:211)
My Desire
I want to run downloads/uploads (via google drive) in a background thread. Since the sdk requires startActivityForResult and other methods that might require a reference to an Activity or Context that makes this difficult, but it should work once the app has been granted the sdk permissions that require those references. Hopefully this makes sense.
Below are the steps you can follow to handle UserRecoverableAuthIOException Exception properly and you can even avoid getting that exception when back pressed.
In some cases if you are receiving that error mean the activity is destroyed so you shouldn't depend on the activity
You need to
create fresh com.google.api.services.tasks.Tasks object from
Context of Service not from any Activity directly like shown in 'tasks-android-sample'
When you get Exception
You need show a notification with PendingIntent from Service
PendingIntent should contain the reference to an Activity , say
HomeActivity
Activity should handle the intent extra and should do
the required things like showing choose account dialog
you can go through the sample code here (GoogleTasksService)
What you can do, in this case don't use multiple activities.
By switching to views you can achieve your task.
Related
I have voice recognition code that crashes upon launch (after the splashscreen). My app works great without voice recognition, but it is required for this app that I have it.
This Acer Chromebook 10 outside of my development has no issue with voice recognition (Okay Google, what time is it... etc.)
Here is a partial screenshot of the error I am getting from logcat on the Chromebook:
I have added permissions in the manifest (before I added this it worked on the Pixel 2XL):
<addPermission android:name="android.permission.BIND_VOICE_INTERACTION"/>
... but still get the same error. I am not launching a competing service, but rather a thread runnable activity. Here is a snippet of the code that I think that may be throwing this error (it crashes right after the splash screen so I don't even get the catch response):
try
{
_activity.runOnUiThread(new Runnable()
{
public void run()
{
// I don't know why, but we have to destroy and redo the recognizer after a failure (unlike onResult), then works great.
mSpeechRecognizer.destroy();
mSpeechRecognizer.setRecognitionListener(recognitionListener);
mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US");
mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
}
});
} // end of try
catch (Exception e)
{
Log.debug("Recognition failed with exception " + e.getMessage());
}
Some background - like the title says this code is working with Pixel 2XL. It is part of an in-house plugin that I've written for the Unreal Engine to support voice recognition. As such I test for the permission "android.permission.BIND_VOICE_INTERACTION" in Blueprints (a flowchart-like language for UE4) when running the code on my Pixel and it comes back true - so I know this permission is okay with the Pixel 2XL.
I get the impression that there may be a competing service causing conflict on the Chromebook specifically (ArcVoiceInteractionService?) and if this is so, I need to find out how to get around it.
I'm working on a phone-conference app on Android 7. I found this problem.
When app crash I loose ongoing call control resulting in app closed and voice channel open.
Reopening app result in two ongoing calls.
There are ways to close the first voice call?
I try closing the call at app restart but obviously Android OS don't let me touch it.
the best (still not working) result I achieved is error class extension. that event is fired at crash start.
here is my class CrashKillCall that implements Thread.UncaughtExceptionHandler
public void uncaughtException(Thread t, Throwable e) {
//"the last song kill the audience" by Crash & the boys
Log.e(TAG, "--------------------------------------");
Log.e(TAG,t.getName());
Log.e(TAG,e.getCause().getMessage());
Log.e(TAG, "--------------------------------------");
crashCall.disconnect();
Log.e(TAG,"work?");
}
public static void setCall(Call call){
crashCall=call;
}
the desired result is some way to, or to let system know that i want to, terminate the ongoing or all calls.
thank you for your help.
ended out that i was pointing at wrong Call object. code work, you just need declare an istance of that class as default exception listener and register the right Call
In my Application, I am trying to make a sync adapter service in Android which will run in the background when the app is killed.
This service will call WL.getInstance().sendActionToJS() to send the control to js.
I am using:
WL.App.setKeepAliveInBackground(true);
method to keep the app alive in Background, using this method I am able to use the instance to WL even though app is killed.
onSync.java:
try {
JSONObject data = new JSONObject();
data.put("isConnected", true);
data.put("connRes", "MOBILE");
WL wl = WL.getInstance();
if(wl!=null){
L.e("WL is not null");
wl.sendActionToJS("isConnected", data);
}
else{
L.e("WL is null");
}
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
main.js:
WL.App.setKeepAliveInBackground(true, options);
WL.App.addActionReceiver("MIActionReceiverId", function actionReceiver(received){
console.log('MIActionReceiverId . '+JSON.stringify(received));
else if(received.action == 'isConnected') {
//Connectivity manager
console.log('isConnected. ');
var isConnected = received.data.isConnected;
console.log('isConnected. '+isConnected);
}
}
WL.getInstance().sendActionToJS() method does nothing neither throwing any exception and addActionReceiver in main.js not receiving anything.
This is happening when app is killed and runnig the background rest of the time everything is working fine.
As mentioned in an earlier questions, there is no official support in the MobileFirst Android SDK to run in an Android service or otherwise, as such some aspects of the SDK that you try to use in this context will work, and some may not.
In addition, I do not believe that this kind of using the sendAction API is even correct or possible...
Got asked this today in an Android interview. I answered the usual, you know, intent + startActivity, etc. Interviewer then asked more pointedly,
"Yes, but where is it actually instantiated? You don't call new
Activity anywhere".
Which now that I think about it, I don't really know. He hinted that it used Java reflection, but I dont have a lot of experience with that, and I've only used it to access some variables in the Android SDK.
Can someone explain how Activities are instantiated using reflection, and why? Bonus points for insight into what value the interviewer saw in knowing this.
When an app's launcher icon is clicked on homescreen, following event happens under the android system :
Homescreen/Launcher app sends an intent to start an activity using startActivity()(startActivity() is binder call to ActivityManager)
Activity Manager sends a process fork request using a socket to Zygote.
Zygote forks a new VM instance that loads ActivityThread(Activity thread manages the execution of the main thread in an application process, scheduling and executing activities, broadcasts, and other operations on it as the activity manager requests.).
ActivityThread has real main() for an app.
ActivityThread calls the app's onCreate().
Hence ActivityThread is responsible for instantiating Activity(inside performLaunchActivity method)
Explanation :
If you observe the stacktrace :
android.app.Instrumentation.newActivity(Instrumentation.java:1021)
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
Code where new activity is instantiated :
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
... //More code
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
... //More code
return activity;
}
Instrumentation.java(class will be instantiated for you before any of the application code)
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
The simple way to check the path to the constructor method is to create a temporary project, override constructor in your Activity and place breakpoint there.
You should be able to walk through the all code and find what exactly you want.
As long as you are not in an interview for an Android system developer (kernel hacker, ...) the answer is simply: That is an implementation detail of the Android framework a normal Android developer should not need to care about because of the abstraction and layer principle and it can be looked up in the rare case you would really need to know it.
Android core is responsible to manage de activity instantiation, and manage it into his activity lifecycle.
The android system takes care about calling all the events you can control in your class in the correct order, add the activity to the stack and many other things.
When you call startActivity, Android core takes control and makes an activity instance (or reuse a previous one if match) and starts to call activity lifecycle events
You can see it here: http://developer.android.com/reference/android/app/Activity.html in Activity Lifecycle part
I had seen many questions on stack but no one is telling if a Fail to connect to camera service will occur, how to get rid of this RuntimeException.
I have an camera application its working fine, I already take care to release the resources but if somehow user install the other application which not releasing the resources properly, my application facing RuntimeException: Fail to connect to camera Service and hence got crashed, want to avoid this situation.
If i click on original camera application it shows me a AlertDialog
Camera error: Cannot connect to camera.
That's what i exactly want to handle this. I am trying this code to handle it but cant succeed yet.
try {
camera = Camera.open();
camera.setDisplayOrientation(90);
} catch (RuntimeException e) {
// TODO: handle exception
Log.d("Inside RunTime exception", e+"//");
camera.setErrorCallback(errorCallback);
reConnectCameraVideo();
} catch(Exception e) {
finish();
}
but camera object returning null on camera.setErrorCallback because it wont open.
setErrorCallback() cannot be used for the case where the Camera will not open. You appear to be trying to still use the Camera -- AFAIK this is impossible until the user reboots their phone if some other app leaked the Camera. Simply display your own message to that effect.
Also:
Use an error logging service, like ACRA, Flurry, BugSense, etc.
Never blindly finish an activity due to an exception, as in your last catch block. Always do something to let the user and/or you (via the error logging service) know about the exception