Firebase Admin SDK for Android, methods not found - android

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 understanding correctly, the Firebase Admin SDK should allow me to do this. So I followed the instructions here.
To set up the Admin SDK in my app. I added the following to build.app:
compile 'com.google.firebase:firebase-admin:4.1.1'
And in my Application class, I added this:
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);
}
However, it's telling me that:
There is no method called setCredential() in FirebaseOptions.Builder, and
FirebaseApp.initializeApp() takes a Context object, not FirebaseOptions.
According to the docs, FirebaseOptions.Builder.setCredential() is a new method, which replaces the deprecated FirebaseOptions.Builder.setServiceAccount(). But setServiceAccount() doesn't exist either.
What's going on here?

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

Related

Android Tests failing when using Hilt caused by ClassCastException

I have been writing kotlin code for android apps for quite some time, but I decided to also start writing testing code too for my apps. I have been facing some problems though with the use of Hilt. What I tried is :
import android.app.Application
open class AbstractApplication: Application()
#HiltAndroidApp
class IgmeApplication : IgmeAbstractApplication() {
#Inject
lateinit var authenticationManager: AuthenticationManager
....
}
and then in the Android Test Directory:
import dagger.hilt.android.testing.CustomTestApplication
#CustomTestApplication(AbstractApplication::class)
open class HiltTestApplication
import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(cl,HiltTestApp::class.java.name, context)
}
}
my Test class :
#HiltAndroidTest
class AuthenticationTest{
#get:Rule
var hiltRule = HiltAndroidRule(this)
#Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
Assert.assertEquals("com.crowdpolicy.onext.igme", appContext.packageName)
}
#Before
fun setUp() {
// Populate #Inject fields in test class
hiltRule.inject()
}
#After
fun tearDown() {
}
}
my app level gradle file :
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
id 'com.google.firebase.firebase-perf' // Firebase Performance monitoring
id 'androidx.navigation.safeargs.kotlin'
id 'dagger.hilt.android.plugin'
id 'kotlin-parcelize'
id 'com.google.protobuf'
}
Properties localProperties = new Properties()
localProperties.load(new FileInputStream(rootProject.file('local.properties')))
Properties keyStoreProperties = new Properties()
keyStoreProperties.load(new FileInputStream(rootProject.file('keystore.properties')))
android {
buildToolsVersion "30.0.3"
ndkVersion localProperties['ndk.version']
signingConfigs {
release {
storeFile file(keyStoreProperties['key.release.path'])
keyAlias 'igme-key'
storePassword keyStoreProperties['key.release.keystorePassword']
keyPassword keyStoreProperties['key.release.keyPassword']
}
}
compileSdkVersion 30
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
freeCompilerArgs += '-Xopt-in=kotlin.RequiresOptIn'
}
defaultConfig {
applicationId "com.crowdpolicy.onext.igme"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "com.crowdpolicy.onext.igme.HiltTestRunner"
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
debuggable false
//signingConfig signingConfigs.release
firebaseCrashlytics {
// Enable processing and uploading o FirebaseCrashlytics.getInstance()f native symbols to Crashlytics
// servers. By default, this is disabled to improve build speeds.
// This flag must be enabled to see properly-symbolicated native
// stack traces in the Crashlytics dashboard.
nativeSymbolUploadEnabled true
unstrippedNativeLibsDir "$buildDir/ndklibs/libs"
}
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
ndk.debugSymbolLevel = "FULL" // Generate native debug symbols
}
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/rxjava.properties'
}
kotlinOptions {
jvmTarget = '1.8'
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
android.buildFeatures.viewBinding = true
dependencies {
// Testing-only dependencies
testImplementation 'junit:junit:4.13.2'
// Core library
androidTestImplementation 'androidx.test:core:1.4.0'
// AndroidJUnitRunner and JUnit Rules
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'
// Assertions
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.ext:truth:1.4.0'
// Espresso dependencies
androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version"
androidTestImplementation "androidx.test.espresso:espresso-intents:$espresso_version"
androidTestImplementation "androidx.test.espresso:espresso-web:$espresso_version"
androidTestImplementation "androidx.test.espresso.idling:idling-concurrent:$espresso_version"
// The following Espresso dependency can be either "implementation"
// or "androidTestImplementation", depending on whether you want the
// dependency to appear on your APK's compile classpath or the test APK
// classpath.
androidTestImplementation "androidx.test.espresso:espresso-idling-resource:$espresso_version"
//Dagger
implementation "com.google.dagger:dagger:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
// region Hilt
implementation "com.google.dagger:hilt-android:$hilt_version"
implementation "androidx.hilt:hilt-navigation-fragment:$hilt_fragment_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version" // or : kapt 'com.google.dagger:hilt-compiler:2.37'
// Testing Navigation
androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")
// region Hilt testing - for instrumentation tests
androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
// Make Hilt generate code in the androidTest folder
kaptAndroidTest "com.google.dagger:hilt-android-compiler:$hilt_version"
// endregion
// For local unit tests
testImplementation 'com.google.dagger:hilt-android-testing:2.37'
kaptTest 'com.google.dagger:hilt-compiler:2.37'
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.37'
}
}
kapt {
correctErrorTypes true
javacOptions {
// These options are normally set automatically via the Hilt Gradle plugin, but we
// set them manually to workaround a bug in the Kotlin 1.5.20: https://github.com/google/dagger/issues/2684
option("-Adagger.fastInit=ENABLED")
option("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
}
}
// https://github.com/google/protobuf-gradle-plugin
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:$protobuf_version"
// path = localProperties["protoc.dir"]
}
// Generates the java Protobuf-lite code for the Protobufs in this project. See
// https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
// for more information.
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option 'lite'
}
}
}
}
}
dependencies {
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
}
(Above I added only the dependencies used for testing )
project gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.20"
ext.google_version = '4.3.4'
ext.timberVersion = '4.7.1'
ext.event_bus = '3.2.0'
ext.gson_version = '2.8.6'
ext.retrofit2_version = '2.9.0'
ext.datastore_version = '1.0.0-rc02'
ext.rxkotlin_version = '3.0.1'
ext.rxandroid_version = '3.0.0'
ext.lifecycle_version = '2.3.1'
ext.dagger_version = '2.37'
ext.hilt_version = '2.37'
ext.hilt_fragment_version = '1.0.0'
ext.nav_version = '2.3.5'
ext.fragment_version = '1.3.6'
ext.androidXTestCoreVersion = '1.4.0'
ext.espresso_version = '3.4.0'
ext.lottie_version = '3.6.1'
ext.facebook_version = '9.0.0'
ext.protobuf_version = '3.15.8'
ext.protobuf_gradle_plugin_version = '0.8.16'
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.gms:google-services:$google_version"
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1'
classpath 'com.google.firebase:perf-plugin:1.4.0'
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
classpath "com.google.protobuf:protobuf-gradle-plugin:$protobuf_gradle_plugin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
I followed the official documentation from dagger-hilt in this page : https://dagger.dev/hilt/testing.html, but I am still getting this error :
Caused by: java.lang.ClassCastException: com.crowdpolicy.onext.igme.HiltTestApplication cannot be cast to android.app.Application
at android.app.Instrumentation.newApplication(Instrumentation.java:997)
at android.app.Instrumentation.newApplication(Instrumentation.java:982)
at com.crowdpolicy.onext.igme.HiltTestRunner.newApplication(HiltTestRunner.kt:14)
at android.app.LoadedApk.makeApplication(LoadedApk.java:617)
and I do not know how to fix it, because I am really new to testing and it is the first time facing it !
line 14 in HIltTestRunner is :
return super.newApplication(cl,HiltTestApp::class.java.name, context)
I had the same Problem, while Testing i got a ClassCastException: HiltTestApplication cannot be cast to AbcApp (my Application class).
Solution is the #CustomTestApplication annotation, see Dagger Docs or Android Dev Docs and the use of the generated class
<interfacename>_Application.
Further on be aware that just using IgmeApplication (or AbcApp in my case) is not possible when it uses the #HiltAndroidApp annotation, see open Issue. Then you have to make an open class AbstractApplication: Application() like the questioner did. Which is then subclassed by your Application (AbcApp in my case or IgmeApplication in questioners case) and subclassed by the created class from annotation #CustomTestApplication. like:
#CustomTestApplication(AbstractApplication::class)
interface CustomTestApplicationForHilt
Note that interface is used instead of open class, but it also works with open class like the questioner did.
The created class is then CustomTestApplicationForHilt_Application which has to be used, when calling newApplication in your Testrunner class, like:
class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
return super.newApplication(cl, CustomTestApplicationForHilt_Application::class.java.name, context)
}
}
Note that you can choose the name of the interface for the #CustomTestApplication annotation (here CustomTestApplicationForHilt) like you want, but the ending _Application will be added to the class name when the annotation is processed while building the app. Also note that the class will not be available before the build.

Android Docx4J Error when reading in MS Word file: Didn't find class org.eclipse.persistence.oxm.NamespacePrefixMapper on path

I am trying to use the Docx4j library in order to read in the contents of Word files selected by the user (tried to follow the code in https://github.com/plutext/Docx4j4Android4) However, I receive the following error when I read in a MS Word file:
W/System.err: log4j:ERROR Could not parse url [jar:file:/data/app/com.example.diffcheckertest-8hLouozp5QPE6U8NaxyKYA==/base.apk!/log4j.xml].
javax.xml.parsers.ParserConfigurationException: No validating DocumentBuilder implementation available
at org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl.newDocumentBuilder(DocumentBuilderFactoryImpl.java:61)
...
Process 20716 terminated.
Caused by: java.lang.ClassNotFoundException: Didn't find class "org.eclipse.persistence.oxm.NamespacePrefixMapper" on path: DexPathList[[zip file "/data/app/com.example.diffcheckertest-8hLouozp5QPE6U8NaxyKYA==/base.apk"]
Below is the line of code in MainActivity.kt where I open the MS Word document and where the error occurs (I have imported the necessary utilities):
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import org.apache.commons.lang3.StringUtils;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import java.io.BufferedReader
import java.io.InputStreamReader
class MainActivity : AppCompatActivity() {
private var READ_IN_FILE:Int = 2; // Request code used when reading in a file
// Asks a user to read in a file
private fun chooseFile(view: View) {
// Only the below specified mime types are allowed in the picker
var selectFile = Intent(Intent.ACTION_GET_CONTENT)
selectFile.type = "*/*"
selectFile = Intent.createChooser(selectFile, "Choose a file")
startActivityForResult(selectFile, READ_IN_FILE)
}
// After receiving a result for a launched activity...
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == READ_IN_FILE) { // When a result has been received, check if it is the result for READ_IN_FILE
if (resultCode == Activity.RESULT_OK) { // heck if the operation to retrieve the Activity's result is successful
// Attempt to retrieve the file
try {
var uri = data?.data // Retrieve the file's resource locator
var document = WordprocessingMLPackage.load(uri?.let { contentResolver.openInputStream(it) });
//var documentPart: MainDocumentPart = document.getMainDocumentPart();
Toast.makeText(this, "DiffChecker successfully read in the file :D", Toast.LENGTH_SHORT).show()
} catch (e: Exception) { // If the app failed to attempt to retrieve the error file, throw an error alert
println("Exception: " + e.toString());
Toast.makeText(this, "Sorry, but there was an error reading in the file", Toast.LENGTH_SHORT).show()
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.file1).setOnClickListener(::chooseFile);
}
}
Below is my build.gradle code (app-level):
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.diffcheckertest"
minSdkVersion 22
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
exclude("META-INF/*.kotlin_module")
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation files('libs/activation.jar')
implementation files('libs/additionnal.jar')
implementation files('libs/awt-bastardised-17v8.jar')
implementation files('libs/istack-commons-runtime-3.0.4-SNAPSHOT.jar')
implementation files('libs/jaxb-core-2.3.0-SNAPSHOT-ANDROID.jar')
implementation files('libs/jaxb-runtime-2.3.0-SNAPSHOT-ANDROID.jar')
//implementation files('libs/commons-lang3-3.7.jar')
//implementation files('libs/commons-text-1.2.jar')
implementation 'javax.xml.stream:stax-api:1.0-2'
implementation 'com.fasterxml:aalto-xml:1.0.0'
implementation files('libs/docx4j-6.1.1-SNAPSHOT-shaded.jar')
}
Build is my build.gradle code (project-level):
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.3.61'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
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
}
How did your project work without the javax.xml.bind:jaxb-api:2.2.12 dependency? It should throw java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/xml/bind/JAXBContext; at the first place.
Android does not support JAXB out of the box, and you must add the dependency explicitly.
implementation 'javax.xml.bind:jaxb-api:2.2.12'
Instead of trying your gradle settings I decided to create a new project and start everything from scratch. Fortunately, I could run and load any docx files without issues.
Please download my sample repository and try in your system.
File selecting using SAF (Storage Access Framework) available since Android 4.4 (API level 19):
// Asks a user to read in a file
private fun chooseFile(view: View) {
// Only the below specified mime types are allowed in the picker
var selectFile = Intent(Intent.ACTION_OPEN_DOCUMENT)
selectFile.type = "*/*"
selectFile.addCategory(Intent.CATEGORY_OPENABLE)
selectFile = Intent.createChooser(selectFile, "Choose a file")
startActivityForResult(selectFile, READ_IN_FILE)
}
To prevent ClassNotFoundException for "org.eclipse.persistence.oxm.NamespacePrefixMapper"
add below line to your gradle file dependencies:
implementation 'org.eclipse.persistence:eclipselink:2.7.6'
to prevent Duplicate class error you can exclude Duplicated classes:
implementation ('org.eclipse.persistence:eclipselink:2.7.6'){
exclude group: 'javax.persistence.spi', module: 'ProviderUtil'
exclude group: 'javax.persistence', module: 'Access'
}
How to run JAXB in Android

Azure spatial anchors integration issues. Missing NativeLibrary implementations

I've been tinkering with Azure's spatial anchors API. I followed the docs and examples provided by Microsoft without many issues until I tried to make my own project from it. When I try to run a custom project using the Spatial anchors API it crashes looking for some functions that should be provided by the libraries specified in the gradle. The error log says this:
2019-05-28 10:32:10.642 28982-28982/com.azurelib.azureanchorsclean E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.azurelib.azureanchorsclean, PID: 28982
java.lang.UnsatisfiedLinkError: No implementation found for com.microsoft.azure.spatialanchors.status com.microsoft.azure.spatialanchors.NativeLibrary.ssc_cloud_spatial_anchor_session_create(com.microsoft.azure.spatialanchors.Out) (tried Java_com_microsoft_azure_spatialanchors_NativeLibrary_ssc_1cloud_1spatial_1anchor_1session_1create and Java_com_microsoft_azure_spatialanchors_NativeLibrary_ssc_1cloud_1spatial_1anchor_1session_1create__Lcom_microsoft_azure_spatialanchors_Out_2)
at com.microsoft.azure.spatialanchors.NativeLibrary.ssc_cloud_spatial_anchor_session_create(Native Method)
...
The relevant ssc_cloud... functions can be found in the spatialanchors_java dependency specified in the gradle build:
For the cloud session, I start a new activity in my MainActivity's onResume():
#Override
protected void onResume(){
super.onResume();
Intent intent = new Intent(this, AzureSpatialAnchorsActivity.class);
intent.putExtra("BasicDemo", true);
startActivity(intent);
}
And on AzureSpatialAnchorsActivity I create the ArCore Session and start the anchor manager:
#Override
protected void onResume() {
super.onResume();
if (session == null) {
try {
...
// Create the session.
session = new Session(/* context= */ this);
... //Required catch statements
} catch (Exception e) {
message = "Failed to create AR session";
exception = e;
}
}
try {
session.resume();
startNewSession();
} catch (CameraNotAvailableException e) {
...
}
}
private void startNewSession() {
destroySession();
cloudAnchorManager = new AzureSpatialAnchorsManager(session);
cloudAnchorManager.addAnchorLocatedListener(this::onAnchorLocated);
cloudAnchorManager.addLocateAnchorsCompletedListener(this::onLocateAnchorsCompleted);
cloudAnchorManager.addSessionUpdatedListener(this::onSessionUpdated);
cloudAnchorManager.start();
}
The error happens because when I try to create a CloudSpatialAnchorSession object
public AzureSpatialAnchorsManager(Session arCoreSession) {
spatialAnchorsSession = new CloudSpatialAnchorSession();
...
}
the constructor calls a function from NativeLibrary
public CloudSpatialAnchorSession() {
Out<Long> result_handle = new Out();
status resultStatus = NativeLibrary.ssc_cloud_spatial_anchor_session_create(result_handle);
this.handle = (Long)result_handle.value;
NativeLibraryHelpers.checkStatus(this.handle, resultStatus);
CookieTracker.add(this);
}
The problem seems to be that what I previously showed on the the jar screenshot is all there is. ssc_cloud_spatial_anchor_session_create gets called, the application lands on an dead end:
class NativeLibrary {
NativeLibrary() {
}
...
static native status ssc_cloud_spatial_anchor_session_create(Out<Long> var0);
...
}
The gradle and other configs are copy/paste from the original Microsoft sample. I can't find what I'm missing that's causing my custom project not to find the implementations of NativeLibrary. For reference, here's the Microsoft project that I'm using to base my own project of
Here's my actual gradle files just for reference:
Project gradle
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
}
}
allprojects {
repositories {
mavenLocal()
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Module gradle:
apply plugin: 'com.android.application'
def azureSpatialAnchorsSdkVersion = '1.1.0'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.azurelib.azureanchorsclean"
minSdkVersion 24
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.ar:core:1.7.0'
implementation "com.microsoft.azure.spatialanchors:spatialanchors_jni:[${azureSpatialAnchorsSdkVersion}]"
implementation "com.microsoft.azure.spatialanchors:spatialanchors_java:[${azureSpatialAnchorsSdkVersion}]"
implementation 'de.javagl:obj:0.2.1'
implementation 'com.microsoft.aad:adal:1.16.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
Thanks!
Since you are creating your own project are you calling the initialize method inside your OnCreate in the application class?
#Override
public void onCreate() {
super.onCreate();
// Use application's context to initialize CloudServices!
CloudServices.initialize(this);
}

Communication through gRPC/Protobuf

I am coming because I can't make work my communication between my API (Go) and my client (Android).
I have this protobuf file:
syntax = "proto3";
option java_package = "com.emixam23.rushpoc.protobuf";
option java_outer_classname = "HelloWorld";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
The protobuf file comes from the example of https://grpc.io/docs/quickstart/go.html, I just didn't implemented the SayHelloAgain. What i am trying to achieve is, from my android app, SayHello to my Go API and get a reply...
For android, I followed that tutorial (https://grpc.io/docs/quickstart/android.html) in order to, from the protobuf file, to communicate with my API. However, there is a stub, comming from I don't know where.
So I searched about how to create a stub (https://grpc.io/docs/tutorials/basic/android.html) and nothing.. ManagedChannelBuilder doesn't exist and I can't find the way to install it..
PS: to generate my Java class from the protobuf file, I followed that tutorial: https://proandroiddev.com/how-to-setup-your-android-app-to-use-protobuf-96132340de5c
Am I in the right direction or totally wrong?
My project structure:
APP build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.google.protobuf'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.rushpoc.emixam23.androidapp"
minSdkVersion 21
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
//Protobuf
implementation 'com.google.protobuf:protobuf-lite:3.0.0'
implementation 'io.grpc:grpc-okhttp:1.13.2'
implementation 'io.grpc:grpc-protobuf-lite:1.13.2'
implementation 'io.grpc:grpc-stub:1.13.2'
}
protobuf {
generatedFilesBaseDir = "$projectDir/generated"
protoc {
// You still need protoc like in the non-Android case
artifact = 'com.google.protobuf:protoc:3.0.0'
}
plugins {
javalite {
// The codegen for lite comes as a separate artifact
artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
}
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.13.2'
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
java
}
task.plugins {
grpc {}
}
}
}
}
TOP-LEVEL/Root build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.protobufVersion = '0.8.6'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath "com.google.protobuf:protobuf-gradle-plugin:$protobufVersion"
// 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
}
I haven't checked the entire gradle files yet but I see in your screenshot the .proto file was in src/main/protobufs, which was not following either of the tutorials you mentioned. The protobuf gradle plugin does not detect this directory by default. Therefore I suggest you change it into the default directory src/main/proto. If you would like to insist putting the .proto file in src/main/protobufs, you might need let the protobuf gradle plugin know it by adding
// see https://github.com/google/protobuf-gradle-plugin#customizing-source-directories
sourceSets {
main {
proto {
// In addition to the default 'src/main/proto'
srcDir 'src/main/protobufs'
}
}
}
After that, the protobuf gradle plugin will generate the java code if there's no other mistake.

Unresolved reference async in Kotlin

I am trying to perform network operation async in Kotlin. I read it you can do async using async function. I am getting below error, can anyone guess what could be the issue ?
Unresolved reference: async
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
async() {
val forecastWeather = ForecastRequest("302015").execute()
Log.d("Test", forecastWeather.toString())
}
}
ForecastRequest.kt
class ForecastRequest(val zipcode: String) {
companion object {
private val APP_ID = "XYZ"
private val URL = "http://api.openweathermap.org/data/2.5/" +
"forecast/daily?mode=json&units=metric&cnt=7"
private val COMPLETE_URL = "$URL&APPID=$APP_ID&q="
}
fun execute(): ForecastResponse {
val forecastJsonStr = java.net.URL(COMPLETE_URL + zipcode).readText()
return Gson().fromJson(forecastJsonStr, ForecastResponse::class.java)
}
}
Top level build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.1.2-4'
repositories {
maven { url 'https://maven.google.com' }
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha2'
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 {
maven { url 'https://maven.google.com' }
jcenter()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Module level build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.williams.thirddemo"
minSdkVersion 23
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.google.code.gson:gson:2.8.1'
}
async is available inside kotlinx.couroutines
Make sure that you added the dependency in your gradle file:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'
Also make sure that the async is called on a coroutine scrope such as GlobalScope.
val deferredResult = GlobalScope.async {
}
I see async function is available in anko library not Kotlin library itself. https://github.com/Kotlin/anko
I resolved by adding this dependency in build.gradle compile "org.jetbrains.anko:anko-commons:0.10.1" as this is not available in Kotlin itself.
I see that async is deprecated now, library suggests to use doAsync instead.
doAsync {
val forecastWeather = ForecastRequest("302015").execute()
uiThread {
Log.d("Test", forecastWeather.toString())
}
}
Different Kotlin libraries can have different implementations of async that do different things.
If you wanted the general async-await function from the core library, make sure you have a dependency to kotlinx.coroutines
if you are using Deferred , make sure you import kotlinx.coroutines.Deferred, there is also a chance you import firebase Deferred

Categories

Resources