I read the latest Firebase Blog which reports firebase now supports not-equal queries. However, it is not working on this android code snippet and I am getting Unresolved reference: where error when using where.
private fun getAllContacts() {
val currentUserPhoneCredential = auth.currentUser?.phoneNumber!!
firestore.collection("Contacts")
//getting unresolved reference when using where
.where("phoneNumber", "!=", currentUserPhoneCredential)
.get().addOnSuccessListener { querySnapshot ->
for (doc in querySnapshot) {
val user = doc.toObject(User::class.java)
contactsList.add(user)
contactsNames.add(user.name!!)
}
adapter.notifyDataSetChanged()
}
}
I am using the latest Firebase Android Library and running Android SDK 30.0 on Android Studio 4.0.2
implementation 'com.google.firebase:firebase-firestore:21.7.1'
Here is an image of my code
You are using the API for JavaScript, not Java. Be sure to switch to the "java" tab when viewing the documentation, and you will see that the API is whereNotEqualTo():
.whereNotEqualTo("phoneNumber", currentUserPhoneCredential)
I think you are looking for this,
https://firebase.google.com/docs/firestore/query-data/queries#not_equal
firestore.collection("Contacts").whereNotEqualTo("phoneNumber", currentUserPhoneCredential)
You are using the API of web.
Note: For iOS, Android, and Java, the comparison operator is explicitly named in the method.
citiesRef.whereEqualTo("state", "CA")
citiesRef.whereLessThan("population", 100000)
citiesRef.whereGreaterThanOrEqualTo("name", "San Francisco")
citiesRef.whereNotEqualTo("capital", false)
So for android java and android kotlin use following code
firestore.collection("Contacts").whereNotEqualTo("phoneNumber", currentUserPhoneCredential)
for more details you can refer this link
Related
I am learning KMM. I am now designing a common Location fetching in iOSMain and Android main
My problem is , I don't know to map Swift to Kotlin in iOSMain
For example,
The Swift code for , getting location is
var locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
var currentLoc: CLLocation!
if(CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways) {
currentLoc = locationManager.location
print(currentLoc.coordinate.latitude)
print(currentLoc.coordinate.longitude)
}
Kotlin side implementation:
In the above code:
How to use the Swift's .authorizedWhenInUse and .authorizedAlways in Kotlin Code ?
And the in currentLoc.coordinate.longitude , the longitude and latitude is not resolving . Why ?
Please help me
Mapping Swift (Objective-C) to Kotlin
How to use the Swift's .authorizedWhenInUse and .authorizedAlways in Kotlin Code ?
According to Kotlin's documentation on interoperability, Kotlin/Native provides bidirectional interoperability with Objective-C, not Swift, so my first recommendation would be to reference Apple's Objective-C documentation over the Swift documentation.
If you pull up the Swift documentation for .authorizedWhenInUse, you'll see you can switch the language to Objective-C:
Switch this to the Objective-C documentation to see how to reference this in Objective-C:
Given this, you should be able to use kCLAuthorizationStatusAuthorizedWhenInUse in your Kotlin code.
Referencing iOS Frameworks
Since you already have some reference code, you could also simply Command+Click (or Command+B) one of the objects (for example, CLLocationManager) which should open up the compiled Kotlin code.
Manually you can also access all iOS frameworks from the "Project" View of Android Studio → "External Libraries" and then search for the iOS framework that you are searching for.
Here, you can dig through the frameworks to find what you're looking for. Not knowing the equivalent Objective-C API, you could just search for "authorizedWhenInUse" and can find it:
Dealing with C-structs
currentLoc.coordinate.longitude , the longitude and latitude is not resolving
This is more complicated...
The location property is of type CLLocationCoordinate2D and (the important part!) is that it is contained within a CValue:
#kotlinx.cinterop.ExternalObjCClass public open class CLLocation : platform.darwin.NSObject, platform.Foundation.NSCopyingProtocol, platform.Foundation.NSSecureCodingProtocol {
...
public final val coordinate: kotlinx.cinterop.CValue<platform.CoreLocation.CLLocationCoordinate2D> /* compiled code */
Note that in Objective-C, CLLocationCoordinate2D is a C struct:
typedef struct CLLocationCoordinate2D {
...
} CLLocationCoordinate2D;
The Kotlin documentation here is thin, but it shows the methods available for CValue includes the .useContents() method.
Therefore, your code could be written as follows (compiled and confirmed that this runs and generates a location on a physical device):
val locationManager = CLLocationManager()
val currentLoc: CLLocation?
if (locationManager.authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse ||
locationManager.authorizationStatus == kCLAuthorizationStatusAuthorizedAlways) {
currentLoc = locationManager.location
currentLoc?.coordinate?.useContents {
println("latitude = ${latitude}")
println("longitude = ${longitude}")
}
}
[Update September 2022]
If you want to dig deeper, I also published a blog post on writing iOS-platform-dependent code using Kotlin with KMM's expect/actual: artandscienceofcoding.com/science/avoid-this-kmm-technique
I have been trying to integrate AppCheck with my Android app, but I can't seem to make a valid request.
As for test purposes, I have been using the following code:
Android Code
class Application : MultiDexApplication() {
override fun onCreate() {
FirebaseApp.initializeApp(this)
val appCheck = FirebaseAppCheck.getInstance()
if (BuildConfig.DEBUG) appCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance(), true)
else appCheck.installAppCheckProviderFactory(SafetyNetAppCheckProviderFactory.getInstance(), true)
super.onCreate()
}
}
class TestActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
val data = "This is a test!"
Firebase.functions.getHttpsCallable("test").call(data).addOnCompleteListener {
if (it.isSuccessful) {
val result = it.result.data
print(result)
}
else {
val exception = it.exception
print(exception)
}
}
}
}
Function Code
const functions = require("firebase-functions")
exports.test = functions.https.onCall((data, context) => {
if (context.app == undefined) {
functions.logger.error("Test - Failed validating device integrity!")
throw new functions.https.HttpsError("failed-precondition", "The function must be called from an App Check verified app")
}
return data
})
I have added the DebugAppCheckProviderFactory token to the Firebase console, but no matter what I do, if it is an emulator or physical device, when I call the function, the failed-precondition exception is always thrown.
Checking the function logs, I can see that the app is missing:
I have already read the documentation multiple times and I can't seem to be missing any step. Am I missing something or is there anything I can do to find the root cause for this?
Thank you for your time!
EDIT:
As for Martin suggestion, I created a new OnRequest function and added the X-Firebase-AppCheck header. I received the token correctly and was able to validate it successfully with:
firebaseAdmin.appCheck().verifyToken(appCheckToken)
So, my guess is that Android is not adding the X-Firebase-AppCheck automatically to the OnCall function like it should.
I ran the code and made some breakpoints through the code and noticed the following. The call method from Firebase is adding the Firebase-Instance-ID-Token but I can't seem to find the X-Firebase-AppCheck header anywhere. Maybe I am not supposed to see this value, or maybe I just can't find where it is being added. Or maybe it is not added at all, thus I can't validate my context.app at all.
It may be required to obtain an AppCheckToken:
FirebaseAppCheck
.getInstance()
.getAppCheckToken(false)
.addOnSuccessListener(new OnSuccessListener<AppCheckToken>() {
#Override
public void onSuccess(#NonNull AppCheckToken tokenResponse) {
String appCheckToken = tokenResponse.getToken();
...
}
});
Which has to be passed along, with the HTTP request (the example shows Retrofit, which could also be used instead of HttpsCallable:
#GET("yourExampleEndpoint")
Call<List<String>> exampleData(
#Header("X-Firebase-AppCheck") String appCheckToken,
...
);
Where FirebaseFunctions.getInstance().getHttpsCallable().call() doesn't tell how or if one has to explicitly set that X-Firebase-AppCheck header. Cloud Functions should usually receive an X-Firebase-AppCheck header - with the previously retrieved AppCheck token:
const appCheckToken = req.header('X-Firebase-AppCheck');
if (!appCheckToken) {
res.status(401);
return next('Unauthorized');
}
try {
const appCheckClaims = await firebaseAdmin.appCheck().verifyToken(appCheckToken);
// If verifyToken() succeeds, continue with the next middleware function in the stack.
return next();
} catch (err) {
res.status(401);
return next('Unauthorized');
}
One can also issue own tokens ...and checking for context-app is also valid.
Update: The Protocol specification for https.onCall reads:
Optional: X-Firebase-AppCheck: <token>
The Firebase App Check token provided by the client app making the request. The backend automatically verifies this token and decodes it, injecting the appId in the handler's context. If the token cannot be verified, the request is rejected.Available for SDK >=3.14.0
To install the minimum required NodeJS dependencies:
npm install firebase-functions#">=3.14.0"
npm install firebase-admin#">=9.8.0"
And last, but not least ...there's even a debug helper for that:
dependencies {
debugImplementation "com.google.firebase:firebase-appcheck-debug:16.0.0-beta02"
}
After testing everything with no success, in a desperate move, I tried to look to unrelated files and found the solution.
In my build.gradle I was importing all the Firebase dependencies with the bom:
implementation platform("com.google.firebase:firebase-bom:27.0.0")
implementation "com.google.firebase:firebase-crashlytics-ktx"
implementation "com.google.firebase:firebase-analytics-ktx"
implementation "com.google.firebase:firebase-firestore-ktx"
implementation "com.google.firebase:firebase-functions-ktx"
implementation "com.google.firebase:firebase-auth-ktx"
So I thought: "Can the firebase-bom be importing an outdated functions-ktx dependency?"
And guess what? As soon as I imported the dependencies without the bom, I started to see the X-Firebase-AppCheck being added and the context.app being valid.
I ended up with the following build.gralde:
implementation "com.google.firebase:firebase-crashlytics-ktx:18.2.1"
implementation "com.google.firebase:firebase-analytics-ktx:19.0.0"
implementation "com.google.firebase:firebase-firestore-ktx:23.0.3"
implementation "com.google.firebase:firebase-functions-ktx:20.0.0"
implementation "com.google.firebase:firebase-auth-ktx:21.0.1"
After a little more investigation, I found out that I was using an outdated firebase-bom version. Android Studio used to let me know if there was a new version for the dependencies, but it did not notice me for the firebase-bom. Turns out, that I just need to update my firebase-bom dependency.
TL;DR
Check your Android Firebase libraries version!
It's pretty hard to understand the nuget packages to install in a Xamrin solution when searching around the web, there are dozens of packages, dozens of different solutions.
Right now, our solution has 2 projects, an Android one and a PCL one. Our model and data access is defined in the PCL. Our platform implementation is defined in the Android one.
We need SQLite, SQLite.Net (for the data annotations and table relations), and SQLiteExtentions for the *withchildren methods.
We are stuck in old versions because anytime we try to update anything, our frail magical way in which our installed packages are working together just falls apart. We do need to upgrade or find a way to add SQLCipher to this weird snafu of nuget packages.
Our current packages installed, which works:
Android project
Mono.Data.Sqlite.Portable 1.0.3.5 (not sure why...)
SQLite.Net.Core-PCL 3.1.1
SQLite.Net.Platform.XamarinAndroidN 3.1.1
SQLite.Net-PCL 3.1.1
SQLiteNetExtensions 1.3.0 (required for GetWithChildren etc.)
SQLitePCL.raw 0.9.3
PCL Project (model definition and data access methods)
Mono.Data.Sqlite.Portable 1.0.3.5 (not sure why...)
SQLite.Net.Core-PCL 3.1.1
SQLite.Net.Platform.XamarinAndroidN 3.1.1
SQLite.Net-PCL 3.1.1
SQLiteNetExtensions 1.3.0 (required for GetWithChildren etc.)
SQLitePCL.raw 0.9.3
Currently, if we update the SQLiteExtensions to 2.0, a bunch of other SQLite nuget packages are installed, breaking the frail stability of our data access code (fails on the *WithChildren methods with:
Severity Code Description Project File Line Suppression State
Error CS1929 'SQLiteConnection' does not contain a definition for
'GetWithChildren' and the best extension method overload
'ReadOperations.GetWithChildren<TEntity>(SQLiteConnection, object, bool)'
requires a receiver of type 'SQLiteConnection'
We'd also need to incorporate SQLiteCipher and no combinations of packages can be made to work with our solution.
Our Android platform specific implementation:
#region Usings
using OURPCLLib.DataAccess;
using Serilog;
using SQLite.Net;
using SQLite.Net.Interop;
using SQLite.Net.Platform.XamarinAndroid;
using System;
using System.IO;
#endregion Usings
public class AndroidSQLiteDatabase : SQLiteDatabaseAccess
{
protected ISQLitePlatform SQLitePlatform
{
get { return new SQLitePlatformAndroidN(); }
}
protected override SQLiteConnection GetConnection()
{
var conn = new SQLiteConnection(
SQLitePlatform,
"dbpathforus.sqlite",
SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.FullMutex |
SQLiteOpenFlags.ProtectionCompleteUnlessOpen |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache);
return conn;
}
}
The (simplified) base data access class in the PCL:
#region Usings
using OURPCLLib.DataAccess.Entities;
using SQLite.Net;
using SQLite.Net.Attributes;
using SQLite.Net.Interop;
using SQLiteNetExtensions.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
#endregion Usings
public abstract class SQLiteDatabaseAccess
{
protected abstract SQLiteConnection GetConnection();
// Example of one of the many methods accessing the DB using SQLite.Net
public bool Any<TEntity>(Expression<Func<TEntity, bool>> expression)
where TEntity : class, IBaseEntity, new()
{
using (var currentConnection = this.GetConnection())
{
return currentConnection.Table<TEntity>().Where(expression).FirstOrDefault() != null;
}
}
// Example of one of the methods accessing the DB using SQLiteExtentions
public TEntity GetWithChildren<TEntity>(int id, bool recursive = false)
where TEntity : class, IBaseEntity, new()
{
using (var currentConnection = this.GetConnection())
{
return currentConnection.GetWithChildren<TEntity>(id, recursive);
}
}
}
Anyone can help us as to how to use SQLite with SQLIte.net, SQLiteExtentions and SQLIte cipher on a project like ours? (data access in a pcl and connection implementation in an android project?
For anyone wondering, I solved it, with minimal code impact, and some loss of functionality but not much, by only installing SQLiteNetExtensions and letting it get its SQLite dependency by itself.
I am using the latest version of DJI which is 4.5.1 and using WaypointMissionOperator for loading the mission, still I am getting the same error while trying to load mission. Can anyone help me in resolving this?
Some additional information would be helpful. A little code snippet would help or some additional detail like how many points, etc?
Can you describe your data flow, aka, what calls and in what order? Is the mission failing to load and is there any detail in the error return?
final DJIError djiError = missionOperator.loadMission(mission);
if (djiError != null) {
Log.d("TEST", djiError.getDescription()));
}
I have been trying a ( i hope) simple bit of Android hyperloop code directly within a titanium project (using SDK 7.0.1.GA and hyperloop 3).
var sysProp = require('android.os.SystemProperties');
var serialNumber = sysProp.get("sys.serialnumber", "none");
But when the app is run it reports
Requested module not found:android.os.SystemProperties
I think this maybe due to the fact that when compiling the app (using the cli) it reports
hyperloop:generateSources: Skipping Hyperloop wrapper generation, no usage found ...
I have similar code in a jar and if I use this then it does work, so I am wondering why the hyperloop generation is not being triggered, as I assume that is the issue.
Sorry should have explained better.
This is the jar source that I use, the extraction of the serial number was just an example (I need access to other info manufacturer specific data as well), I wanted to see if I could replicate the JAR functionality using just hyperloop rather that including the JAR file. Guess if it's not broke don't fix it, but was curious to see if it could be done.
So with the feedback from #miga and a bit of trial and error, I have come up with a solution that works really well and will do the method reflection that is required. My new Hyperloop function is
function getData(data){
var result = false;
var Class = require("java.lang.Class");
var String = require("java.lang.String");
var c = Class.forName("android.os.SystemProperties");
var get = c.getMethod("get", String.class, String.class);
result = get.invoke(c, data, "Error");
return result;
}
Where data is a string of the system property I want.
I am using it to extract and match a serial number from a Samsung device that is a System Property call "ril.serialnumber" or "sys.serialnumber". Now I can use the above function to do what I was using the JAR file for. Just thought I'd share in case anyone else needed something similar.
It is because android.os.SystemProperties is not class you can import. Check the android documentation at https://developer.android.com/reference/android/os/package-summary.html
You could use
var build = require('android.os.Build');
console.log(build.SERIAL);
to access the serial number.