DeadObjectException with com.google.android.gms - android

I'm getting a frequent crash with the log below. It doesn't reference my application code but I'm guessing it may have something to do with GoogleApiClient connecting/disconnecting. Anyone get anything similar to this? I haven't been able to find anything on here.
java.lang.IllegalStateException: android.os.DeadObjectException
at com.google.android.gms.internal.ao.removeAllListeners(Unknown Source)
at com.google.android.gms.internal.ap.disconnect(Unknown Source)
at com.google.android.gms.common.api.b.n(Unknown Source)
at com.google.android.gms.common.api.b.a(Unknown Source)
at com.google.android.gms.common.api.b$2.onConnectionSuspended(Unknown Source)
at com.google.android.gms.internal.r.y(Unknown Source)
at com.google.android.gms.internal.q$a.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5102)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.DeadObjectException
at android.os.BinderProxy.transact(Native Method)
at com.google.android.gms.internal.an$a$a.a(Unknown Source)
... 15 more
Possibly where it's happening. I added a try/catch to catch the exception
mGApiClientMgr.addTask(mGApiClientMgr.new GoogleApiClientTask() {
#Override
public void run() {
Log.d(LOG_TAG, "Refreshing data set.");
Location location;
try {
location = LocationServices.FusedLocationApi.getLastLocation(getGoogleApiClient());
onLocationChanged(location);
}
catch(IllegalStateException ex) {
// TODO
}
}
});
where addTask does:
private final LinkedBlockingQueue<GoogleApiClientTask> mTaskQueue = new LinkedBlockingQueue
<GoogleApiClientTask>();
mTaskQueue.offer(task);

This seems related to handlers and message passing...Based on below snippet from your stack trace, gms is seeing a DeadObjectException when trying to process a message on the looper. Even though the stack trace shows gms related, it could have be triggered by your code.
at com.google.android.gms.internal.q$a.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
This exception is seen if the message its trying to access belong to a process that has since exited/killed. Do a code search for all handler sendMessage* message dispatch calls, through out your code. Even this may not catch all instances as some gms calls could result in handler message dispatches.
Also, check if any of your background services, or activities that allocated handler messages, are exiting. Android could be destroying them depending on life cycle states, try overriding onDestroy.
In all your activities/services, any where you make calls to gms api, check the objects you create and pass to gms; If they die, those objects are not valid any more.

Related

Error: Only one Looper may be created per thread with stacktrace that has no "Caused by:"

I'm using code from Extending the Service class to handle messaging in two Services and in another class (that's not a Service).
Below is the code that initializes and gets the suspicious objects (one thread each in onCreate() in the Services, and 2 threads in a static method in the other class). Nowhere is thread.run() explicitly called (as it shouldn't be, but I know that I can make the crash happen by calling it after calling thread.start() but not by calling thread.start() twice). While this code is taken from the Android documentation, I've only altered some of the variable names in my implementation. The same is true of the message-handling code that relies on this.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
Here's the stacktrace. Unfortunately, there's nothing indicating which implementation in my code is the offender, and I'm not able to reproduce the crash.
Fatal Exception: java.lang.RuntimeException: Only one Looper may be created per thread
at android.os.Looper.prepare(Looper.java:89)
at android.os.Looper.prepare(Looper.java:84)
at android.os.HandlerThread.run(HandlerThread.java:54)
06-15 06:23:18.599 27561-29056/? E/BluetoothBoundService﹕ Interrupted
read:
java.lang.InterruptedException
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:371)
at java.lang.Thread.sleep(Thread.java:313)
at services.BluetoothBoundService.receiveDataFromBT
(BluetoothBoundService.java:1442)
at
services.BluetoothBoundService.access$2700(BluetoothBoundService.java:147)
at services.BluetoothBoundService$9.run(BluetoothBoundService.java:1173)
at java.lang.Thread.run(Thread.java:761)
06-15 06:23:18.898 28954-28975/? E/BluetoothRemoteDevices﹕
state12newState1
06-15 06:23:23.469 27561-27570/? E/System﹕ Uncaught exception thrown by
finalizer
06-15 06:23:23.470 27561-27570/? E/System﹕ java.io.IOException: socket
not created
at android.net.LocalSocketImpl.shutdownInput(LocalSocketImpl.java:404)
at android.net.LocalSocket.shutdownInput(LocalSocket.java:207)
at android.bluetooth.BluetoothSocket.close(BluetoothSocket.java:575)
at android.bluetooth.BluetoothSocket.finalize(BluetoothSocket.java:273)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:222)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:209)
at java.lang.Thread.run(Thread.java:761)
06-15 06:23:24.112 15861-15861/? E/SearchServiceStarter﹕ Task 174 failed
or timed out. Client 69758913221593243 disconnecting from SearchService!
java.util.concurrent.CancellationException: Task was cancelled.
at com.google.common.util.concurrent.d.ct(SourceFile:75)
at com.google.common.util.concurrent.d.get(SourceFile:57)
at com.google.common.util.concurrent.cg.n(SourceFile:2)
at com.google.common.util.concurrent.av.l(SourceFile:50)
at com.google.common.util.concurrent.ax.run(SourceFile:5)
at
com.google.android.apps.gsa.shared.util.concurrent.a.bc.run(SourceFile:2)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android....ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
06-15 06:23:24.144 15861-15861/? E/WorkerRegistryImpl﹕ getWorker() is
called after WorkerRegistry disposal.
06-15 06:23:24.153 15861-15861/? E/WorkerRegistryImpl﹕ getWorker() is
called after WorkerRegistry disposal.
06-15 06:23:34.229 15861-15861/? E/SearchServiceStarter﹕ Task 174 failed
or timed out. Client 69758913221593244 disconnecting from SearchService!
java.util.concurrent.CancellationException: Task was cancelled.
at com.google.common.util.concurrent.d.ct(SourceFile:75)
at com.google.common.util.concurrent.d.get(SourceFile:57)
at com.google.common.util.concurrent.cg.n(SourceFile:2)
at com.google.common.util.concurrent.av.l(SourceFile:50)
at com.google.common.util.concurrent.ax.run(SourceFile:5)
at
com.google.android.apps.gsa.shared.util.concurrent.a.bc.run(SourceFile:2)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(Zy
It seems that somehow and somewhy Android is calling thread.run() when it shouldn't be, but I don't know how to tell what's triggering that. I've looked at the other questions and answers that propose overriding run() to prevent this from happening (for example https://stackoverflow.com/a/24115631/1493426), but I don't see how to do that by extending HandlerThread in a reasonable way that won't have undesirable, unintended consequences.
For now I'm inclined to leave everyting alone, since the code has been around for at least several months, and this crash has only been seen once, but I'd like to know if there's a safe way to make the code more crash proof without hiding any underlying problems.

Sporadic IllegalArgumentException: Unknown URL content://

Very rarely getting:
Fatal Exception: java.lang.IllegalArgumentException: Unknown URL content://com.example.provider/info
at android.content.ContentResolver.insert(ContentResolver.java:1252)
Fatal Exception: java.lang.IllegalArgumentException: Unknown authority com.example.provider
at android.content.ContentResolver.applyBatch(ContentResolver.java:1247)
Emphasis on rarely. Generally work fine without issue, so the authorities is set up fine, but this is showing up every once in a while for no reason. Are there reasons why the ContentResolver may not be able to find a ContentProvider (i.e. if not set up yet)?
I've had the rare IllegalArgumentException with Unknown URIs issue when I was doing ContentResolver operations in the custom Application object.
For example, I was trying to delete items in my content provider in the application onCreate method which would very occasionally crash:
public class CustomApplication extends Application {
#Override
public void onCreate() {
//..
context.getContentResolver().delete(ReminderEntry.getContentURI(), null, null, null, null);
//..
}
}
Which would sometimes render the following crash:
Fatal Exception: java.lang.RuntimeException: Unable to create application com.myapp.CustomApplication: java.lang.IllegalArgumentException: Unknown URL content://com.myapp.db.CustomContentProvider/reminder
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6431)
at android.app.ActivityThread.access$1800(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1887)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7331)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by java.lang.IllegalArgumentException: Unknown URL content://com.myapp.db.CustomContentProvider/reminder
at android.content.ContentResolver.delete(ContentResolver.java:1376)
at com.myapp.ReminderEntryDao.delete(Unknown Source)
at com.myapp.CustomApplication.onCreate(Unknown Source)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1037)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6428)
at android.app.ActivityThread.access$1800(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1887)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7331)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
I also saw similar behaviour with a BOOT_COMPLETE receiver. I had about 70 reported crashes with this exception (mostly Infinix devices ~43%, hardly any Samsung Devices) of about 200 000 monthly active users.
I moved this into a background scheduled job and haven't seen the crash since. I was only ever able to reproduce this issue once on a Nexus device that I used but never again.
I suspect perhaps sometimes on some versions of Android on some devices the Application/BOOT_COMPLETE Receiver initializes before the ContentProvider is fully initialized and therefore when it tries to access it, it is not properly set up yet.
There are a couple of stackoverflow posts that do state exactly what is created first and how the OS should behave:
Is the Application class guaranteed to be instantiated before a defined boot receiver is called
But like I said, I've seen otherwise and moving operations out of the classes into background schedulers seems to fix the problem (perhaps it is just because it takes a bit longer to get setup). Hopefully my experience will help you.
Edit: I used the evernote job dispatcher and deferred my ContentResolver operations to the job if required. (but I would assume that deferring the content provider operation to any kind of background processing might fix it as it had a bit more time to get setup - these are just my suspicions of course).
class DeleteRemindersJob extends Job {
#NonNull
#Override
protected Result onRunJob(final Params params) {
cursor = getContext().getContentResolver().delete(ReminderEntry.getContentURI(), null, null, null, null);
//..
return Result.SUCCESS;
}
}

java.lang.NullPointerException IntentService

I'm trying to start a service in a different app that's installed on the device. I get a NullPointerException when using startService
public void notConnected(){
Log.i(TAG,"no connection... reconnecting.");
Intent reset = new Intent("com.famoco.intent.action.TOGGLE_DATA");
Log.i(TAG,"calling " + reset.getAction());
if(reset.getAction().equals("com.famoco.intent.action.TOGGLE_DATA"))
{
startService(reset);
}
else
{
Log.i(TAG,"couldn't start service");
}
}
and this is error log
E/AndroidRuntime: FATAL EXCEPTION: IntentService[MyAppCommService]
Process: com.myapppackage.MyApp, PID: 8583
java.lang.NullPointerException
at android.content.ContextWrapper.startService(ContextWrapper.java:494)
at com.myapppackage.MyApplocation.activity.MyAppActivity.notConnected(MyAppActivity.java:591)
at com.myapppackage.MyApplocation.api.MyAppApi.submitClock(MyAppApi.java:228)
at com.myapppackage.MyApplocation.service.MyAppCommService.submitTags(MyAppCommService.java:52)
at com.myapppackage.MyApplocation.service.MyAppCommService.onHandleIntent(MyAppCommService.java:98)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.os.HandlerThread.run(HandlerThread.java:61)
Turns out my context returned null, I fixed it by getting the context in onCreate and calling myContext.startservice.
You are starting a new Intent. And looking at that Google example, looks like you use the wrong method to start it up.
- you use:
startService(reset);
- try this one:
startActivity(intent);
But that starts an Activity. And you want an service. I don't think you can do that unless you are the developer of that other app. In general, Android Apps don't have access each others code & resources.
Fixed it by returning context in the onCreate() and then calling context.startService()

Getting a lot of crashes from android youtube player api

I am using version 1.2.1 (tried with latest version 1.2.2) of android's youtube player api. It works fine on most of the devices. However now and then, I keep on getting crashes on crashlytics. I am getting the following crashes
Fatal Exception: java.lang.IllegalStateException: android.os.TransactionTooLargeException
at com.google.android.youtube.api.jar.client.RemoteEmbeddedPlayer.x(SourceFile:558)
at bpd.w(SourceFile:576)
at tef.onTransact(SourceFile:390)
at android.os.Binder.transact(Binder.java:395)
at com.google.android.youtube.player.internal.d$a$a.r(Unknown Source)
at com.google.android.youtube.player.internal.s.h(Unknown Source)
at com.google.android.youtube.player.YouTubePlayerView.e(Unknown Source)
at com.google.android.youtube.player.YouTubePlayerSupportFragment.onSaveInstanceState(Unknown Source)
at android.support.v4.app.Fragment.performSaveInstanceState(Fragment.java:1936)
at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1654)
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1722)
at android.support.v4.app.Fragment.performSaveInstanceState(Fragment.java:1938)
at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1654)
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1722)
at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:527)
at com.newshunt.news.activities.NewsBaseActivity.onSaveInstanceState(NewsBaseActivity.java:56)
at com.newshunt.news.activities.NewsDetailsActivity.onSaveInstanceState(NewsDetailsActivity.java:613)
at android.app.Activity.performSaveInstanceState(Activity.java:1388)
at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1286)
at android.app.ActivityThread.callCallActivityOnSaveInstanceState(ActivityThread.java:4588)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3960)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4023)
at android.app.ActivityThread.access$1200(ActivityThread.java:181)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1498)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6117)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Also getting crashes for the following exception.
Fatal Exception: java.lang.IllegalStateException: android.os.DeadObjectException
at com.google.android.apps.youtube.api.jar.a.eo.surfaceDestroyed(SourceFile:236)
at android.view.SurfaceView.updateWindow(SurfaceView.java:589)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:237)
at android.view.View.dispatchDetachedFromWindow(View.java:12854)
at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2757)
at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2757)
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3844)
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3819)
at android.view.ViewGroup.removeView(ViewGroup.java:3751)
at com.google.android.youtube.player.YouTubePlayerView$1.b(Unknown Source)
at com.google.android.youtube.player.internal.r.h(Unknown Source)
at com.google.android.youtube.player.internal.r$e.onServiceDisconnected(Unknown Source)
at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1111)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1125)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5317)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(NativeStart.java)
The crash happens to appear in specific versions of youtube application like 5.2.27. Although there are a lot of issues filed for these crashes, there has been no reply from the youtube developers on how to mitigate this issue.
Some of the fellow developers have suggested the following workarounds
1) Use loadVideo instead of cueVideo. But I cannot use this workaround because loadVideo always autoplays the video which is not a requirement of my application. Also someone mentioned that with loadVideo also, this problem is happening although in some different version.
2) Put check in the code to check the youtube application version and then put the specific code. Now the problem with this approach is that I have to check each and every version of youtube app ever released and check which versions are causing the issue which is not a good workaround.
Now is there any fix which I can apply to avoid this issue or are the youtube developers planning to release some jar which internally takes care of all these issues?
I reduced the bug occurrence by putting youtube calls (like youtubePlayer.loadVideo(), cueVideo(), getCurrentTimeMillis() etc.) in a try catch block and catch the IllegalStateException exception then reinitialize youtube player.
To create a new instance of the YoutubePlayer just call the initialize() method in the catch block.
Example:
if (youtubePlayer != null) {
try {
youtubePlayer.loadVideo(videoId);
} catch (IllegalStateException e) {
initialize(API_KEY, this);
}
}
but the bug still occurred , I worked around it by catching these exceptions and restart activity. This uncaught exceptions and to catch them you need to use UncaughtExceptionHandler
example :
private Thread.UncaughtExceptionHandler defaultUEH;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
// setup handler for uncaught exception
Thread.setDefaultUncaughtExceptionHandler(_unCaughtExceptionHandler);
}
private Thread.UncaughtExceptionHandler _unCaughtExceptionHandler =
new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.e(TAG, "uncaughtException: ", ex);
PendingIntent myActivity = PendingIntent.getActivity(getApplicationContext(),
192837, new Intent(getApplicationContext(), MainActivity.class),
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager;
alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
15000, myActivity );
System.exit(2);
// re-throw critical exception further to the os (important)
defaultUEH.uncaughtException(thread, ex);
}
};
The android YouTube Player API is not stable, there are known bugs in it. The team from YouTube said that they will release a new version of the library.
For now, the best solution I have found is to build my own library.

AbstractThreadedSyncAdapter doesn't fire right away

I've been wondering why the AbstractThreadedSyncAdapter doesn't perform Sync once i run the app but instead it waits like 5-10 mins then it starts to download the data using an API request and fills my tables ,which causes this error :
02-03 05:03:34.954 6061-6061/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.moviesapp.app, PID: 6061
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.android.moviesapp.app/com.example.android.moviesapp.app.MainActivity}:
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
at com.example.android.moviesapp.app.DetailFragment.ReadTrailersDetailsFromDB(DetailFragment.java:70)
at com.example.android.moviesapp.app.DetailFragment.onCreateView(DetailFragment.java:114)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:330)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
at android.app.Activity.performStart(Activity.java:5241)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2157)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233) 
at android.app.ActivityThread.access$800(ActivityThread.java:135) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:136) 
at android.app.ActivityThread.main(ActivityThread.java:5001) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:515) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 
at dalvik.system.NativeStart.main(Native Method)
The whole point of the Android SyncManager is that you let it decide when it wants to do a sync. This is for battery efficiency so that the system has the flexibility to batch sync operations from different apps together. Doing so means that the system can turn off the power hungry radio for longer periods of time when all apps have synced.
So, if you use the Android SyncManager (by implementing the SyncAdapter pattern) then you must expect it to call SyncAdapter.onPerformSync() at times that you cannot control.
From what I understand, your Activity crashes because it is reading empty tables? And you expected the tables to have been filled by your SyncAdapter already?
There is no way around it, you must make your Activities so that they can deal with empty tables. You will have to put in an extra check for that.
Note that you can trigger an immediate sync with this:
/**
* Starts a manual sync operation, i.e. independent of the automatic sync settings.
*
* #param context System's service locator
* #param account The account to sync
* #param expedited Make this sync a priority system wide
*/
public static void requestSync(Context context, Account account, boolean expedited) {
Bundle extras = new Bundle();
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, expedited);
ContentResolver.requestSync(account, Contract.AUTHORITY, extras);
}
You provide the Account that you want to sync and set expedited to true to make it so that the Android SyncManager will sync your account before any other apps. Because this sync request is set to 'manual' it means the SyncManager will not wait for a convenient time, it will just turn on the radio and start syncing all apps, your's first.
But even if you do a requestSync, you should expect that the internet is slow and the results will take some time from milliseconds to seconds or even minutes before they are written to your database by your SyncAdapter. In the meantime your Activity has already started up and is reading empty tables...
So make sure you Activities do not crash on empty tables.

Categories

Resources