I\'m building an Android app backed by a Firebase app, and I would like to be able to create an Admin account that can edit or delete other user accounts. If I\'m understand
You can't use the Firebase Admin SDK in an Android app alongside the Firebase Android client libraries. The SDKs both provide classes with the exact same package and class name, so it wouldn't possibly be able to use them both at the same time (how would the compiler know which one you intend to build into your app?).
As an example, take a look at the javadoc for FirebaseOptions Builder in the Android client library:
com.google.firebase.FirebaseOptions.Builder
Now look at the same class from the java Admin SDK (note the URL is different):
com.google.firebase.FirebaseOptions.Builder
You can see for yourself that they're different things, even though they have the same name. Your compiler is therefore looking at the Android SDK definition and not the admin SDK definition.
As Frank said, you probably don't want to use the Admin library within your Android app. If you want to use the admin SDK, use it from a server you control, and have your Android app communicate with that if needed.
Now FirebaseOptions class taken from other dependencies, May you can remove firebase components from other dependencies as below using exclude tag.
compile 'com.google.firebase:firebase-admin:5.8.0'
compile ('com.google.firebase:firebase-messaging:9.6.1'){
exclude module: 'firebase-common'
}
compile ('com.google.firebase:firebase-auth:9.6.1'){
exclude module: 'firebase-common'
}
compile ('com.google.firebase:firebase-database:9.6.1'){
exclude module: 'firebase-common'
}
compile ('com.firebase:firebase-client-android:2.5.0'){
exclude module: 'firebase-common'
}
As the accepted answer states, it's not a good idea to put Firebase Admin in your Android app that uses Firebase, because there are classes with the same names.
I wanted to create a custom token (https://firebase.google.com/docs/auth/android/custom-auth), so I ended up doing:
1) Create a separate UI-less server app.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
finish() // Just end the app here.
}
}
<resources>
<style name="AppTheme" parent="@android:style/Theme.NoDisplay">
</style>
</resources>
2) Add an IntentService to the server app and generate a custom token.
class CustomTokenService : IntentService(CustomTokenService::class.java.simpleName) {
// Runs in its own thread.
override fun onHandleIntent(intent: Intent?) {
// Initialize FirebaseApp only when not already initialized.
try {
FirebaseApp.getInstance()
} catch (ex: IllegalStateException) {
try {
val inputStream = assets.open("serviceAccountKey.json")
val options = FirebaseOptions.Builder().
setCredential(FirebaseCredentials.fromCertificate(inputStream)).
setDatabaseUrl("https://YOUR_APP.firebaseio.com/").
build()
FirebaseApp.initializeApp(options)
inputStream.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
// In real life, you should verify ID/PW before creating custom token.
val id = intent!!.getStringExtra("ID")
val pw = intent.getStringExtra("PW")
val additionalClaims = HashMap<String, Any>()
additionalClaims.put("premiumAccount", true)
FirebaseAuth.getInstance().createCustomToken(id, additionalClaims).
addOnSuccessListener { customToken ->
// Send custom token back to client.
val resultReceiver = intent.getParcelableExtra<ResultReceiver>(RESULT_RECEIVER)
val bundle = Bundle()
bundle.putString(CUSTOM_TOKEN, customToken)
resultReceiver.send(Activity.RESULT_OK, bundle)
}
}
}
Note that I'm sending the custom token back to the client via "ResultReceiver", but you are free to use other ways, such as "Messenger" or "BroadcastReceiver".
3) From the client, I start the service that resides in the server app.
String MYSERVER = "SERVER_ID"; // e.g. "com.domain.myserver"
String CUSTOM_TOKEN_SERVICE = MYSERVER + ".CustomTokenService";
Intent intent = new Intent();
intent.putExtra("ID", ID);
intent.putExtra("PW", PW);
intent.putExtra(RESULT_RECEIVER, mResultReceiver);
intent.setComponent(new ComponentName(MYSERVER, CUSTOM_TOKEN_SERVICE));
getContext().startService(intent);
4) When I receive the custom token from the server app, I sign in to Firebase.
ResultReceiver resultReceiver = new ResultReceiver(new Handler()) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
String customToken = resultData.getString(CUSTOM_TOKEN);
mFirebaseAuth.signInWithCustomToken(customToken);
}
};
Parcel parcel = Parcel.obtain();
resultReceiver.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
mResultReceiver = ResultReceiver.CREATOR.createFromParcel(parcel);
parcel.recycle();
5) And the Gradle config files.
buildscript {
ext.kotlin_version = '1.2.21'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
---------------------------------------------------------------------------
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 26
defaultConfig {
applicationId "org.solamour.myserver"
minSdkVersion 14
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
javaCompileOptions {
annotationProcessorOptions {
includeCompileClasspath false
}
}
resConfigs "auto"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// Conflict with dependency 'com.google.code.findbugs:jsr305' in project ':app'.
// Resolved versions for app (1.3.9) and test app (2.0.1) differ.
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:2.0.1' // Or "1.3.9".
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.google.firebase:firebase-admin:4.1.6'
implementation 'com.android.support:multidex:1.0.2'
}
The highest Firebase Admin version I was able to use was "4.1.6"; anything after that involved a lot of modifications to the gradle file (and that didn't end up well either).