Created
January 23, 2017 10:08
-
-
Save LouisCAD/8a7739b0edfae2877017086c339f560f to your computer and use it in GitHub Desktop.
Use ContentProvider to init your application. This example sets up Timber logging and a "crash shield" that can do what you want 5 seconds after an uncaught exception.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.app.AlarmManager | |
import android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP | |
import android.app.PendingIntent | |
import android.content.Context | |
import android.os.SystemClock | |
import android.support.annotation.IntRange | |
import com.google.firebase.provider.FirebaseInitProvider | |
import org.jetbrains.anko.alarmManager | |
import timber.log.Timber | |
private var internalCtx: Context? = null | |
val appCtx: Context | |
get() = internalCtx!! | |
/** | |
* Initializes app-wide components, before [FirebaseInitProvider] initialization. | |
*/ | |
class AppInitProvider : InitProvider() { | |
override fun onCreate() = consume { | |
internalCtx = context // At this point, context is an instance of your Application class on which onCreate() has not been called | |
setupCrashShield() | |
setupLogging() | |
} | |
private fun setupLogging() { | |
Timber.plant(if (BuildConfig.DEBUG) Timber.DebugTree() else ProductionTree()) | |
} | |
private fun setupCrashShield() { | |
Thread.setDefaultUncaughtExceptionHandler { thread, throwable -> restartApp() } | |
} | |
/** | |
* Schedules an app restart with [AlarmManager] and exits the process. | |
* @param restartDelayInMillis Min 3s to let the user get in settings force | |
* close the app manually if needed. | |
*/ | |
private fun restartApp(@IntRange(from = 3000) restartDelayInMillis: Long = 5000L) { | |
require(restartDelayInMillis >= 3000) | |
val restartReceiver = StartReceiver.createIntent(context) | |
.setAction(StartReceiver.ACTION_RESTART_AFTER_CRASH) | |
val restartApp = PendingIntent.getBroadcast( | |
context, | |
RESTART_APP_REQUEST, | |
restartReceiver, | |
PendingIntent.FLAG_ONE_SHOT | |
) | |
val now = SystemClock.elapsedRealtime() | |
// Line below schedules an app restart 5s from now. | |
context.alarmManager.set(ELAPSED_REALTIME_WAKEUP, now + restartDelayInMillis, restartApp) | |
Timber.i("just requested app restart, killing process") | |
System.exit(2) | |
} | |
companion object { | |
private const val RESTART_APP_REQUEST = 2 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<manifest> | |
... | |
<application> | |
... | |
<provider | |
android:name=".provider.AppInitProvider" | |
android:authorities="${applicationId}.appinitprovider" | |
android:exported="false" | |
android:initOrder="900"/> | |
... | |
</application> | |
</manifest> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun unsupported(errorMessage: String? = null): Nothing = throw UnsupportedOperationException(errorMessage) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.ContentProvider | |
import android.content.ContentValues | |
import android.net.Uri | |
/** | |
* Base class for [ContentProvider]s used for initialization purposes. | |
*/ | |
abstract class InitProvider : ContentProvider() { | |
override final fun insert(uri: Uri?, values: ContentValues?) = unsupported() | |
override final fun query(uri: Uri?, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?) = unsupported() | |
override final fun update(uri: Uri?, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?) = unsupported() | |
override final fun delete(uri: Uri?, selection: String?, selectionArgs: Array<out String>?) = unsupported() | |
override final fun getType(uri: Uri?) = unsupported() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment