Skip to content

Commit 154bda8

Browse files
committed
feat: Add support for automatic initialization
1 parent bc0a11a commit 154bda8

File tree

7 files changed

+105
-16
lines changed

7 files changed

+105
-16
lines changed

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ android {
4545
dependencies {
4646
implementation fileTree(dir: 'libs', include: ['*.jar'])
4747

48-
implementation project(path: ":what-the-stack")
48+
debugImplementation project(path: ":what-the-stack")
4949

5050
implementation libs.kotlinStdLib
5151
implementation libs.appCompat

app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
package="com.haroldadmin.crashyapp">
44

55
<application
6-
android:name=".CrashyApp"
76
android:allowBackup="true"
87
android:icon="@mipmap/ic_launcher"
98
android:label="@string/app_name"

app/src/main/java/com/haroldadmin/crashyapp/CrashyApp.kt

Lines changed: 0 additions & 12 deletions
This file was deleted.

app/src/main/java/com/haroldadmin/crashyapp/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ class MainActivity : AppCompatActivity() {
1616
}
1717
}
1818

19-
private class BecauseICanException : Exception("This exception is purely thrown because it can be thrown")
19+
private class BecauseICanException : Exception("This exception is thrown purely because it can be thrown")

what-the-stack/src/main/AndroidManifest.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
22
package="com.haroldadmin.whatthestack">
33
<application>
4+
<provider
5+
android:name=".WhatTheStackInitProvider"
6+
android:authorities="${applicationId}.WhatTheStackInitProvider"
7+
android:exported="false"
8+
android:enabled="true"/>
49
<service
510
android:name=".WhatTheStackService"
611
android:process=":what_the_stack_process" />

what-the-stack/src/main/java/com/haroldadmin/whatthestack/WhatTheStack.kt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,30 @@ import android.content.Intent
55
import android.os.Messenger
66

77
/**
8+
* **DO NOT USE**
89
* A class to allow initialization of WhatTheStack service.
910
*
11+
* WhatTheStack initializes automatically using a content provider. You do not need to initialize
12+
* it explicitly using this class.
13+
*
1014
* @param applicationContext The context used to start the service to catch uncaught exceptions
1115
*/
16+
@Deprecated(
17+
"WhatTheStack initializes automatically at application startup. Do not explicitly initialize it",
18+
level = DeprecationLevel.ERROR
19+
)
1220
class WhatTheStack(private val applicationContext: Context) {
1321

22+
@Suppress("unused")
23+
fun init() {
24+
WhatTheStackInitializer.init(applicationContext)
25+
}
26+
}
27+
28+
internal object WhatTheStackInitializer {
29+
30+
private var isInitialized: Boolean = false
31+
1432
private val connection = WhatTheStackConnection(
1533
onConnected = { binder ->
1634
val messenger = Messenger(binder)
@@ -19,7 +37,9 @@ class WhatTheStack(private val applicationContext: Context) {
1937
}
2038
)
2139

22-
fun init() {
40+
fun init(applicationContext: Context) {
41+
if (isInitialized) { return }
42+
isInitialized = true
2343
val intent = Intent(applicationContext, WhatTheStackService::class.java)
2444
applicationContext.bindService(intent, connection, Context.BIND_AUTO_CREATE)
2545
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.haroldadmin.whatthestack
2+
3+
import android.content.ContentProvider
4+
import android.content.ContentValues
5+
import android.content.Context
6+
import android.content.pm.ProviderInfo
7+
import android.database.Cursor
8+
import android.net.Uri
9+
import android.util.Log
10+
11+
private const val TAG = "WhatTheStackInitializer"
12+
13+
/**
14+
* A content provider to initialize WhatTheStack automatically at application startup. It does not
15+
* provide the ability to query underlying data.
16+
*/
17+
class WhatTheStackInitProvider : ContentProvider() {
18+
19+
override fun onCreate(): Boolean {
20+
val applicationContext = context ?: return false
21+
WhatTheStackInitializer.init(applicationContext)
22+
Log.d(TAG, "Initialized")
23+
return true
24+
}
25+
26+
override fun attachInfo(context: Context?, info: ProviderInfo?) {
27+
super.attachInfo(context, info)
28+
checkProperAuthority(info)
29+
}
30+
31+
override fun insert(uri: Uri, values: ContentValues?): Uri? {
32+
throw UnsupportedOperationException("This content provider can only be used for initializing WhatTheStack")
33+
}
34+
35+
override fun query(
36+
uri: Uri,
37+
projection: Array<out String>?,
38+
selection: String?,
39+
selectionArgs: Array<out String>?,
40+
sortOrder: String?
41+
): Cursor? {
42+
throw UnsupportedOperationException("This content provider can only be used for initializing WhatTheStack")
43+
}
44+
45+
override fun update(
46+
uri: Uri,
47+
values: ContentValues?,
48+
selection: String?,
49+
selectionArgs: Array<out String>?
50+
): Int {
51+
throw UnsupportedOperationException("This content provider can only be used for initializing WhatTheStack")
52+
}
53+
54+
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
55+
throw UnsupportedOperationException("This content provider can only be used for initializing WhatTheStack")
56+
}
57+
58+
override fun getType(uri: Uri): String? {
59+
throw UnsupportedOperationException("This content provider can only be used for initializing WhatTheStack")
60+
}
61+
62+
/**
63+
* Checks to see if the application using this library has declared an applicationId in its
64+
* build.gradle file. If not, it crashes the app with a proper error message.
65+
*
66+
* Performing this check at startup is important because if a user's device has multiple apps
67+
* installed with WhatTheStack, and they do not declare their application IDs, then the content
68+
* providers in those applications will fallback to the same name. Since the authority is used
69+
* to identify the content provider, it **must** be unique.
70+
*/
71+
private fun checkProperAuthority(info: ProviderInfo?) {
72+
val contentProviderName = WhatTheStackInitProvider::class.java.name
73+
require(info?.authority != contentProviderName) {
74+
"Please provide an applicationId inside your application's build.gradle file"
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)