android how to add byte[] data to cloud firestore database - android

I have tried to upload my data of local database to Cloud Firestore database, and the data type of one field is byte[]. It can't be success or failure.
Map<String, Object> setDetail = new HashMap<>();
j = cursor.getColumnIndex("sound");
byte[] sound = cursor.getBlob(j);
setDetail.put("sound", sound);
dbFire.collection("SetDetails").document(strWordID).set(setDetail)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
}
});
The debugger steps over this line dbFire.collection("SetDetails").document(strWordID).set(setDetail)
then jumps out to the last line of zzj.class
final class zzj implements Runnable {
zzj(zzi var1, Task var2) {
this.zzm = var1;
this.zzg = var2;
}
public final void run() {
synchronized(zzi.zza(this.zzm)) {
if (zzi.zzb(this.zzm) != null) {
zzi.zzb(this.zzm).onComplete(this.zzg);
}
}
}
}
If I continue running, it will jump to this line of Looper.java
final int thresholdOverride =
SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
I have read documents, Bytes is one of data types that Cloud Firestore supports, so what's wrong with it. Could anyone help me? Thanks!

To write a byte array type field on Android, use Blob.fromBytes() to convert a byte array to a Blob object, then provide the Blob object to update() or set().

Related

How to avoid index in firestore?

I have created a database in firestore and loaded the test data successfully. But later I noticed that some data is missing in database. I found that when I load the same records with a different value for some fields the old record is replaced with the new record. I feel like this is the issue in the database design. I need to collect and save all the records even if it is a duplicate records at entire records level.
Could you please let me know how to do this ?
private void exportToFireStore() {
// Access a Cloud Firestore instance from your Activity
final FirebaseFirestore db = FirebaseFirestore.getInstance();
/* ----------------_-------Collection delete is not supported-----------------------
----------Hence get all the document (coins) for individual Docs delete----------
*/
//------------------------------- Getting document (coins) Ends ---------------------------------------------
final List<String> coinsFromFirestore = new ArrayList<>();
db.collection("cryptos").document(userEmailID).collection("coin")
.whereEqualTo("createdBy", userEmailID)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
System.out.println("Testing 1 Batch Read done" + document.getData());
coinsFromFirestore.add(document.getData().get("coinname").toString());
}
//------------------------------- Getting document (coins) Ends ---------------------------------------------
if(coinsFromFirestore.size()>0){
for (int i=0;i<coinsFromFirestore.size();i++) {
if ( i<(coinsFromFirestore.size()-1) ) {
db.collection("cryptos").document(userEmailID).collection("coin").document(coinsFromFirestore.get(i))
.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
System.out.println("Testing 1 Successfully Deleted the document " );
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
System.out.println("Testing 1 Error Deleting the document ");
}
});
}else{
db.collection("cryptos").document(userEmailID).collection("coin").document(coinsFromFirestore.get(i))
.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
addTranToFireBaseeNow(db);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
}
});
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! For last coin Ends !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
}else{
addTranToFireBaseeNow(db);
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
//------------------------------- Getting document (coins) Ends ---------------------------------------------
}
private void addTranToFireBaseeNow(FirebaseFirestore db) {
WriteBatch batch = db.batch();
DocumentReference newCoinRef;
//CollectionReference cryptos = db.collection("cryptos");
List<Tran> tranList = getAllTranForFireStore();
String firebaseUID = FirebaseAuth.getInstance().getCurrentUser().getUid();
for (Tran t : tranList) {
Map<String, Object> tranData = new HashMap<>();
tranData.put("firebaseid", firebaseUID);
tranData.put("createdBy", userEmailID);
tranData.put("coinid", t.getCoinID());
tranData.put("coinname", t.getCoinName());
tranData.put("coinsymbol", t.getCoinSymbol());
tranData.put("date", String.valueOf(t.getDate()));
tranData.put("qty", String.valueOf(t.getQty()));
tranData.put("price", String.valueOf(t.getPrice()));
tranData.put("priceunit", String.valueOf(t.getPriceUnit()));
newCoinRef= db.collection("cryptos").document(userEmailID).collection("coin").document(t.getCoinName());
batch.set(newCoinRef, tranData);
}
batch.commit().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
// ...
}
});
}
No index is setup for my DB
Since you are using set without any options, it will overwrite the existing data. But your requirement is to merge your data, so you have to use the merge option as follows:
batch.set(newCoinRef, tranData, SetOptions.merge());
You can read more about options here.
Furthermore there is a good post which lists the differences between set, update and create.
You can use update and change one variable
reference.document("documentname").update("field", variable)
or
reference.document("documentname").set({
field: variable
}, { merge: true });
Or.. if you have to update an entire object, you can use:
reference.document("documentname").set(newObject, { merge: true });
Check this article:
https://saveyourtime.medium.com/firebase-cloud-firestore-add-set-update-delete-get-data-6da566513b1b

updateChildren not updating the array of images, its overwriting the exist array(url) data firebase android

updateChildren not updating the array of images, its overwriting the exist array(url) data firebase android. I want to add some more images to existing url array in firebase.
This is my firebase structure
Blog--
pushid--
"name": xxxx
"url"
-- 0: "first image"
1: "second image"
I want to update(add some more images to existing url array . Im using updatechildren() but its overwriting the existing images
for (String photo : selectedImages) {
blogimages = new ArrayList<>();
Uri file = Uri.fromFile(new File(photo));
Bitmap bitmap = null;
try {
bitmap = decodeSampledBitmapFromUri(file, mMaxDimension, mMaxDimension);
StorageReference photoRef = mstorageReference.child("images/" + file.getLastPathSegment());
uploadTask = photoRef.putBytes(byteArray);
uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Uri downloadUrl = taskSnapshot.getDownloadUrl();
blogimages.add(downloadUrl.toString());
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("url", blogimages);
HashMap<String, Object> params = new HashMap<>();
params.put("url", blogimages);
uploads.child(post_key).child("url").updateChildren(params).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(UpdatePost.this, "Post updated..", Toast.LENGTH_LONG).show();
MainActivity.loaded = true;
Intent i = new Intent(UpdatePost.this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(UpdatePost.this, "Failed to post the blog.. Try again later", Toast.LENGTH_LONG).show();
}
});
}
});
} catch (FileNotFoundException e) {
Log.e(TAG, "Can't find file to resize: " + e.getMessage());
FirebaseCrash.report(e);
} catch (IOException e) {
Log.e(TAG, "Error occurred during resize: " + e.getMessage());
FirebaseCrash.report(e);
}
}
That's not the way updateChildren() works. updateChildren() will completely overwrite the content for all child fields that you specify. It doesn't "push" array elements at all, or do any other array-like operations. If you want to append to an array, you're going to have to read the contents of the array from the database, then add the element, then write it back out.
Note that Firestore is different in that it has an arrayUnion operation to append non-unique array elements to an array type field.

storing data into firestore in android

I have 2 arrays like
phonenumber[]={12345,67890,43215,34567,56789}
amount[]={10,20,30}
I want to store data in a document like
field1:phonenumber1 as 12345
field2:amount1 as 10
and again the same process to happen in the same document in firestore.
Is it possible to store like this in firestore
My code
final int phonenumber[] = {12345,67890,43215,67894,32453};
final int length = list.length;
final int amount[] = {20,30,40,50,60};
final int length1 = amount.length;
Map<String, Object> docData1 = new HashMap<>();
for(int i =0 ; i<length;i++)
{
for(int j =i;j<=i;j++){
docData1.put("phonenumber", list[i]);
docData1.put("amount", amount[i]);
}
}
docData1.put("invitee",docData1);
db.collection("Split").document("lahari")
.set(docData1)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully written!");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error writing document",e);
}
});
error I had occured is

On Network call response data stores successfully but not present while reading. Using SnappyDb for storing the data.

I am making a network call through volley. On Response success I am trying to store data through SnappyDb which shows that it has stored successfully. But while reading any data is not present. But if I have data outside of response than it saves and reads too. Below is my code. I am struggling in this from last 2 days. Your help will be highly appreciated. Thanks
private void makeApiCall(String key) {
if (Utility.isNetworkAvailable(AddCustomerActivity.this)) {
final String finalKey = key;
showProgressDailog("Adding...");
NetworkEb.apiCallAddUser(customerEb, (key != null && !key.contains(":"))? true : false, new OnJsonResponse() {
#Override
public void onSuccess(JSONObject response) {
try {
int serverId = response.getInt("id");
customerEb.setKey(serverId + "");
customerEb.setSync(true);
snappyDbUtil.saveObjectFromKey("customer", DbName.CUSTOMER.name(), customerEb);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onError(String response) {
Utility.showToast("Upload failed! Try Again");
progressDialog.dismiss();
}
});
} else {
if (key == null) {
key = snappyDbUtil.getNewKey(DbName.CUSTOMER.name());
customerEb.setKey(key);
customerEb.setSync(false);
Utility.showToast("Saved locally");
}
snappyDbUtil.saveObjectFromKey(key, DbName.CUSTOMER.name(), customerEb);
}
}
I found a solution for this. You need to save the data in UI thread by calling this
runOnUiThread(new Runnable() {
#Override
public void run() {
itemDataModel.setKey("ITEMS:" + key);
itemDataModel.setSync(true);
snappyDbUtil.saveObjectFromKey(itemDataModel.getKey(), DbName.ITEMS.name(), itemDataModel);
}
});
Here you have to also care for the keys to store with which only saves if we provide a db name as shown in the above code.

Role ACL doesn't work using Parse's Android Local Datastore:

The issue is straightforward:
Create a user and add it to a role
Create an object and give it role ACL
The user will be able to find and pin the object, however, the object cannot be retrieved from the local datastore. If I switch to user or public ACL, the object is retrieved.
Example:
public void findAndPinInBackground(ParseQuery<ParseObject> query, final MyCallback callback) {
query.findInBackground(new FindCallback<ParseObject>() {
public void done(final List<ParseObject> eventList, ParseException e) {
if (e == null) {
ParseObject.pinAllInBackground(eventList, new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d(TAG, "Pinned " + eventList.size() + " objects");
callback.onTaskCompleted();
} else {
callback.onTaskFailed(e);
}
}
});
} else {
callback.onTaskFailed(e);
}
}
});
}
Log: "Pinned 1 objects"
ParseQueryAdapter<ParseObject> eventsAdapter = new ParseQueryAdapter<ParseObject>(getActivity(), new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery<ParseObject> create() {
ParseQuery query = new ParseQuery("Event");
query.orderByAscending("name");
query.fromLocalDatastore();
return query;
}
}, android.R.layout.simple_list_item_1);
eventsAdapter.addOnQueryLoadListener(new ParseQueryAdapter.OnQueryLoadListener<ParseObject>() {
#Override
public void onLoading() { }
#Override
public void onLoaded(List<ParseObject> parseObjects, Exception e) {
Log.d(TAG, "Retrieved " + parseObjects.size() + " objects");
}
});
Log: "Retrieved 0 objects"
Facebook has confirmed this is a known bug.
Is there a workaround?
The iOS documentation now mentions this:
To access this data protected by Role based ACLs, you will need to
ignore ACLs when executing a Local Datastore query:
PFQuery *query = [[[PFQuery queryWithClassName:#"Note"]
fromLocalDatastore]
ignoreACLs];
https://parse.com/docs/ios/guide#local-datastore-security
It seems the same applies to Android, which has the ignoreACLs in the API:
public ParseQuery<T> ignoreACLs()
Ignore ACLs when querying from the Local Datastore.
This is particularly useful when querying for objects with Role based
ACLs set on them.
https://parse.com/docs/android/api/com/parse/ParseQuery.html#ignoreACLs%28%29
I also experience the same issue so what i did is the following:
Before you pin the object to the local data store do the following:
ParseACL acl = user.getACL();
// Read access only for the logged in user (not public!)
acl.setReadAccess(ParseUser.getCurrentUser(),true);
user.setACL(acl);
user.pinInBackground();
Hope it helps.

Categories

Resources