2017-02-07 6 views
1

Я создаю приложение Android, поддерживаемое приложением Firebase, и я хотел бы иметь возможность создавать учетную запись администратора, которая может редактировать или удалять другие учетные записи пользователей. Если я правильно понимаю, SDK Firebase Admin должен позволить мне сделать это. Поэтому я следовал инструкциям here.Firebase Admin SDK для Android, методы не найдены

Чтобы настроить SDK администратора в моем приложении. Я добавил следующее build.app:

compile 'com.google.firebase:firebase-admin:4.1.1' 

И в моем классе Application, я добавил следующее:

FileInputStream serviceAccount = null; 
try { 
    serviceAccount = new FileInputStream("app/<MY-DATABASE>.json"); 
} catch (FileNotFoundException e) { 
    e.printStackTrace(); 
} 

if (serviceAccount != null) { 
    FirebaseOptions options = new FirebaseOptions.Builder() 
      .setCredential(FirebaseCredentials.fromCertificate(serviceAccount)) 
      .setDatabaseUrl("https://<MY-APP>.firebaseio.com/") 
      .build(); 

    FirebaseApp.initializeApp(options); 
} 

Однако, это мне говорил, что:

  • Там нет способа вызываемый setCredential() в FirebaseOptions.Builder и
  • FirebaseApp.initializeApp() принимает объект Context, а не FirebaseOptions.

В соответствии с документами FirebaseOptions.Builder.setCredential() - это новый метод, который заменяет устаревшие FirebaseOptions.Builder.setServiceAccount(). Но setServiceAccount() не существует.

Что здесь происходит?

+3

Firebase Admin SDK предназначен только для использования на доверенных устройствах (таких как серверы, которыми вы управляете). Если вы вставляете Firebase Admin SDK в приложение Android, которое вы также отправляете своим обычным пользователям, вы эффективно разрешаете всем этим пользователям полный доступ ко всему вашему проекту Firebase. Это не рекомендуется. –

+0

Ответ Фрэнка является важным. Но для объяснения ошибок компиляции ваш пакет должен импортировать пакеты [Client SDK] (https://firebase.google.com/docs/reference/android/com/google/firebase/FirebaseOptions.Builder) вместо [ Пакеты администрирования Admin (Server)] (https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/FirebaseOptions.Builder). –

ответ

3

Вы не можете использовать SDK Firebase Admin в приложении для Android вместе с клиентскими библиотеками Firebase Android. SDK обе предоставляют классы с тем же самым пакетом и именем класса, поэтому он не сможет использовать их одновременно (как компилятор узнает, какой из них вы собираетесь встраивать в ваше приложение?).

В качестве примера, посмотрите на Javadoc для FirebaseOptions Builder в Android клиентской библиотеки:

com.google.firebase.FirebaseOptions.Builder

Теперь посмотрим на тот же класс от Java Admin SDK (обратите внимание на URL отличается) :

com.google.firebase.FirebaseOptions.Builder

Вы можете видеть сами, что они разные вещи, даже если они имеют такое же имя. Поэтому ваш компилятор рассматривает определение Android SDK, а не определение SDK администратора.

Как сказал Фрэнк, вы, вероятно, не хотите использовать библиотеку Admin в своем приложении для Android. Если вы хотите использовать SDK администратора, используйте его с сервера, которым вы управляете, и при необходимости сообщите об этом Android-приложению.

+0

Но .setCredentials (метод GoogleCredentials.fromStream (serviceAccount)) доступен только в Firebase Admin sdk. Можете ли вы сказать, что есть какой-либо способ использовать этот метод, так как моя Studio всегда использует класс FirebaseOptions из других зависимостей. –

0

Как принято в ответе, не стоит включать Firebase Admin в ваше приложение для Android, которое использует Firebase, потому что есть классы с одинаковыми именами.

Я хотел создать пользовательский маркер (https://firebase.google.com/docs/auth/android/custom-auth), так что я в конечном итоге делает:

1) Создание отдельного приложения сервера UI-менее.

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) Добавить IntentService к серверному приложению и создать пользовательский токен.

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) 
     } 
    } 
} 

Обратите внимание, что я посылаю пользовательский маркер обратно клиенту через «ResultReceiver», но вы можете использовать и другие способы, такие как «Коммуникатор» или «BroadcastReceiver».

3) От клиента я запускаю службу, которая находится в серверном приложении.

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) Когда я получаю пользовательский токен из приложения-сервера, я вхожу в 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) И файлы конфигурации Gradle.

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' 
} 

Самая высокая версия Администратора Firebase, которую я смог использовать, был «4.1.6»; что-то после этого включало в себя множество изменений в файле gradle (и это тоже не очень хорошо).

+0

Я попытался реализовать ваше предложение, но я все еще получаю «не распознавание setCredentials» ... можете ли вы поделиться своим файлом gradle? –

1

Теперь класс FirebaseOptions, взятый из других зависимостей, можно удалить компоненты firebase из других зависимостей, как показано ниже, используя тег exclude.

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' 
}