I set up ML-Kit like AndroidExample and using on-device recognition mode.
It's working so well.
but
If we have a single character like 'A','5','K','9' it can't recognize anything! it only works for more than one length of string!
I need to recognize only one character.
What am I missing?!
This is my Function that gets a bitmap of an image and finds the texts from it.
private void RecognizeText(Bitmap bitmap) {
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance()
.getOnDeviceTextRecognizer();
Task<FirebaseVisionText> result =
detector.processImage(image)
.addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
#Override
public void onSuccess(FirebaseVisionText firebaseVisionText) {
String s = firebaseVisionText.getText() + " | " + firebaseVisionText.getText().length();
Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();
textView.setText(s);
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(Exception e) {
Log.d("EEEEEEEEVVVVVV", e.toString());
}
});
}
Related
I'm trying to make a database of users with profile pictures(stored in storage) related to their IDs.
I'm using Firebase auth,Realtime database and Realime storage.
The code work like this : In user registration process, they choose username and picture. The database is filled with Users -> userUUid -> username and URL of picture stored.
The storage stores the picture.
If I keep such name of the table (Users) code works fine, however if I try to manipulate the tables, for example if I want to make more categories like Users -> SpecialUsers / NormalUsers -> userUUid -> ... the app just crashes.. I tried debugging but saw no errors.
Is there any way how to catch these Firebase exceptions (if there is any) or any explanation why if I change the structure of the tables, the code doesn't work ?
These is the method responsible for the registration :
(this one works)
public void signUp(String email,String password,String userName)
{
auth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(task -> {
if (task.isSuccessful())
{
dbReference.child("Users").child(auth.getUid()).child("userName").setValue(userName);
//if user choose some picture
if(imageControl)
{
UUID randomID = UUID.randomUUID(); //create random UUID for the picture
final String imageName = "images/"+randomID+".jpg";
storageReference.child(imageName).putFile(imageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
StorageReference myStorageRef = firebaseStorage.getReference(imageName);
myStorageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String filePath = uri.toString();
dbReference.child("Users").child(auth.getUid()).child("image").setValue(filePath).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(RegistrationActivity.this, "Write to database is successful.", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(RegistrationActivity.this, "Write to database is not successful.", Toast.LENGTH_SHORT).show();
}
});
}
});
}
});
}
else
{
dbReference.child("Users").child(auth.getUid()).child("image").setValue("null");
}
Intent intent = new Intent(RegistrationActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
else
{
Toast.makeText(RegistrationActivity.this, "There is a problem.", Toast.LENGTH_SHORT).show();
}
});
}
This doesn't work :
(As you can see the only thing changed is the structure of the tables from only 'Users' to 'superUsers' -> 'anotherCategory')
public void signUp(String email,String password,String userName)
{
auth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(task -> {
if (task.isSuccessful())
{
dbReference.child("superUsers").child('anotherCategory').child(auth.getUid()).child("userName").setValue(userName);
//if user choose some picture
if(imageControl)
{
UUID randomID = UUID.randomUUID(); //create random UUID for the picture
final String imageName = "images/"+randomID+".jpg";
storageReference.child(imageName).putFile(imageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
StorageReference myStorageRef = firebaseStorage.getReference(imageName);
myStorageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String filePath = uri.toString();
dbReference.("superUsers").child('anotherCategory').child(auth.getUid()).child("image").setValue(filePath).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(RegistrationActivity.this, "Write to database is successful.", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(RegistrationActivity.this, "Write to database is not successful.", Toast.LENGTH_SHORT).show();
}
});
}
});
}
});
}
else
{
dbReference.("superUsers").child('anotherCategory').child(auth.getUid()).child("image").setValue("null");
}
Intent intent = new Intent(RegistrationActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
else
{
Toast.makeText(RegistrationActivity.this, "There is a problem.", Toast.LENGTH_SHORT).show();
}
});
}
I suspect that the errors occurs somewhere after imageControl check.
In the second example of the code, the tables superUsers -> anotherCategory tables are created in the database, however the reference to the picture UUids is empty (not even null is placed)
What could be the error if nothing relevant to the process of storing pictures is changed ?
I am using ML kit's on device translation API to translate a text.Although the translation is working perfectly fine but I am unable to display the translated text in my text view.I tried using setText method but nothing is being displayed in text view.Everything is being displayed in the logcat.
I am working in Android Studio
edit:
This shows the model being downloaded
TranslatorOptions options =
new TranslatorOptions.Builder()
.setSourceLanguage(TranslateLanguage.ENGLISH)
.setTargetLanguage(TranslateLanguage.BENGALI)
.build();
final Translator englishBengaliTranslator =
Translation.getClient(options);
//DOWNLOAD THE MODEL
DownloadConditions conditions = new DownloadConditions.Builder()
.requireWifi()
.build();
englishBengaliTranslator.downloadModelIfNeeded(conditions)
.addOnSuccessListener(
new OnSuccessListener() {
#Override
public void onSuccess(Object o) {
}
//#Override
public void onSuccess(Void v) {
// Model downloaded successfully. Okay to start translating.
// (Set a flag, unhide the translation UI, etc.)
Toast.makeText(getApplicationContext(), "Model Downloaded.Translation will start ", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Model couldn’t be downloaded or other internal error.
// ...
Toast.makeText(getApplicationContext(), "Model could not be Downloaded. ", Toast.LENGTH_SHORT).show();
}
});
In this snippet of the code I have called the translate function (as the model is now downloaded)
englishBengaliTranslator.translate(stringResult)
.addOnSuccessListener(
new OnSuccessListener() {
#Override
public void onSuccess(Object o) {
}
//#Override
public void onSuccess(#NonNull String translatedText1) {
textViewTranslatedText.setText(translatedText1);
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Error.
// ...
Toast.makeText(getApplicationContext(), "Text could not be translated. ", Toast.LENGTH_LONG).show();
}
});
I have used the setText function but still the translated text gets displayed in logcat and not in the textview(The translation works completely fine).How do I display it in my textView instead of logcat?Any leads would be helpful!
here is the image of logcat where translated text is displayed:enter image description here
Try this code,
englishBengaliTranslator.downloadModelIfNeeded(conditions)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// Model downloaded successfully. Okay to start translating.
// (Set a flag, unhide the translation UI, etc.)
Toast.makeText(getApplicationContext(), "Model Downloaded.Translation will start ", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Model couldn’t be downloaded or other internal error.
// ...
Toast.makeText(getApplicationContext(), "Model could not be Downloaded. ", Toast.LENGTH_SHORT).show();
}
});
The above code does nothing. I have just removed the unnecessary interface.
But the below code does something. I mean it specifies the return type.
englishBengaliTranslator.translate(stringResult)
.addOnSuccessListener(new OnSuccessListener<String>() {
#Override
public void onSuccess(String s) {
if(textViewTranslatedText!=null)
textViewTranslatedText.setText(translatedText1);
else
Log.d(TAG, "onSuccess: translation Done but text view null");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
//Handle onFailure
}
});
storageRef.child("users/me/profile.png").getBytes(Long.MAX_VALUE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
#Override
public void onSuccess(byte[] bytes) {
Uri image=uri;
Toast.makeText(viewpgdetails.this, "image uri="+image , Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast.makeText(viewpgdetails.this, "failed to get image", Toast.LENGTH_SHORT).show();
// Handle any errors
}
});
// [END download_full_example]
}
It is unclear which type of URI you want, so I'll include both versions.
Google Storage URI
This is not very useful outside of a Google APIs.
This will be in the format: gs://PROJECT_ID.appspot.com/path/to/file.png
To get this value, you would use the following code:
String storageUri = storage.getReference('path/to/file.png').toString();
In the question's code, you would use:
StorageReference fileRef = storageRef.child("users/me/profile.png")
fileRef.getBytes(Long.MAX_VALUE)
.addOnSuccessListener(new OnSuccessListener<byte[]>() {
#Override
public void onSuccess(byte[] bytes) {
Toast.makeText(viewpgdetails.this, "image uri: " + fileRef.toString(), Toast.LENGTH_SHORT).show();
// Use the bytes to display the image
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast.makeText(viewpgdetails.this, "failed to get image", Toast.LENGTH_SHORT).show();
// Handle any errors
}
});
HTTPS Resource URL
This URL would be used if you wanted to include the image in a web page or link to it in an email.
This will be in the format: https://firebasestorage.googleapis.com/v0/b/PROJECT_ID.appspot.com/o/path%2Fto%2Ffile.png?alt=media&token=ACCESS_TOKEN
Because this URL uses an access token issued by the server, it must be requested and returned to the client asynchronously. This is achieved with the following code:
Task<Uri> getDownloadUrlTask = storage.getReference('path/to/file.png').getDownloadUrl();
In the question's code, you would use:
StorageReference fileRef = storageRef.child("users/me/profile.png")
fileRef.getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri downloadUrl) {
Toast.makeText(viewpgdetails.this, "image url: " + downloadUrl, Toast.LENGTH_SHORT).show();
// Use URL for internal web page, etc.
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast.makeText(viewpgdetails.this, "failed to get image url", Toast.LENGTH_SHORT).show();
// Handle any errors
}
});
Note: If you want both the HTTPS URL and the file as a byte array, they would have to be requested as seperate Tasks using both getBytes() and getDownloadUrl().
See also
Cloud Storage for Android Guide
StorageReference API Reference
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().
I have a problem with Flowables and adding them to the compositeDisposables.
I want to switch from an Observable to a Flowable as the operation might emit 1000 or more values. Im somewhat unexperienced with rxjava2 so please forgive me if that question is stupid :)
So far I used the observable like this:
public Observable<String> uploadPictureRx(String path)
{
return Observable.create(new ObservableOnSubscribe<String>()
{
#Override
public void subscribe(ObservableEmitter<String> e) throws Exception
{
Uri file = Uri.fromFile(new File(path));
String segment = file.getLastPathSegment();
UploadTask uploadTask = reference.child("SomeChild").child(segment).putFile(file);
uploadTask.addOnFailureListener(new OnFailureListener()
{
#Override
public void onFailure(#NonNull Exception exception)
{
e.onError(exception);
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>()
{
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot)
{
//noinspection VisibleForTests
downloadUrl = taskSnapshot.getDownloadUrl();
String url = downloadUrl.getPath();
e.onNext(url);
e.onComplete();
}
}).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>()
{
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot)
{
//noinspection VisibleForTests
long bytes = taskSnapshot.getBytesTransferred();
String bytesS = String.valueOf(bytes);
e.onNext(bytesS);
}
});
}
});
}
and called the method like this:
private void uploadPicToFireBaseStorage(String path)
{
compositeDisposable.add(storageService.uploadPictureRx(path)
.subscribeOn(Schedulers.io())
.observeOn(mainScheduler)
.subscribeWith(new DisposableObserver<String>()
{
#Override
public void onNext(String s)
{
String ss = s;
System.out.println(ss);
}
#Override
public void onError(Throwable e)
{
e.printStackTrace();
}
#Override
public void onComplete()
{
view.displayToast("Picture Upload completed");
}
})
);
}
This works fine! However when I try to do the same with a Flowable instead of observable it wont compile:
public Flowable<String> uploadPictureRx(String path)
{
return Flowable.create(new FlowableOnSubscribe<String>()
{
#Override
public void subscribe(FlowableEmitter<String> e) throws Exception
{
Uri file = Uri.fromFile(new File(path));
String segment = file.getLastPathSegment();
UploadTask uploadTask = reference.child("somechild").child(segment).putFile(file);
uploadTask.addOnFailureListener(new OnFailureListener()
{
#Override
public void onFailure(#NonNull Exception exception)
{
e.onError(exception);
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>()
{
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot)
{
//noinspection VisibleForTests
downloadUrl = taskSnapshot.getDownloadUrl();
String url = downloadUrl.getPath();
e.onNext(url);
e.onComplete();
}
}).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>()
{
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot)
{
//noinspection VisibleForTests
long bytes = taskSnapshot.getBytesTransferred();
String bytesS = String.valueOf(bytes);
e.onNext(bytesS);
}
});
}
}, BackpressureStrategy.BUFFER);
}
The Error is:
Inferred type 'E' for type parameter 'E' is not within its bound; should implement 'org.reactivestreams.Subscriber
My guess is, that Flowable does not implement Disposable and thats why it wont compile. I have no clue if thats true or not, just my best guess so far.
Or do I have to change subscribeWith() to subscribe()? I dont know what the impact of that change would be.
Anyway suggestions how to make this work and get this Flowable into my compositedisposable is really appreciated.
Thanks guys!
Edit:
Tried to change the DisposableObserver into a Subscriber. But this results in the following Error:
Compiler Error
Flowables use Subscription instead of Disposable for the reason of Backpressure. Basically use Subscription.request() method to tell observable how many items I want for that moment.
Change your code:
private void uploadPicToFireBaseStorage(String path)
{
compositeDisposable.add(storageService.uploadPictureRx(path)
.subscribeOn(Schedulers.io())
.observeOn(mainScheduler)
.subscribeWith(new DisposableObserver<String>()
{
#Override
public void onNext(String s)
{
String ss = s;
System.out.println(ss);
}
#Override
public void onError(Throwable e)
{
e.printStackTrace();
}
#Override
public void onComplete()
{
view.displayToast("Picture Upload completed");
}
})
);
}
into
private void uploadPicToFireBaseStorage(String path)
{
compositeDisposable.add(storageService.uploadPictureRx(path)
.subscribeOn(Schedulers.io())
.observeOn(mainScheduler)
.subscribeWith(new ResourceSubscriber<String>()
{
#Override
public void onNext(String s)
{
String ss = s;
System.out.println(ss);
}
#Override
public void onError(Throwable e)
{
e.printStackTrace();
}
#Override
public void onComplete()
{
view.displayToast("Picture Upload completed");
}
})
);
}
Flowable works according to pub-sub pattern, i.e publisher - subscriber pattern
whereas ,
Observable works according to observer pattern
In pub-sub pattern there is middle event channel which holds the data released by the publisher and then the event channel emits the data and the subscriber gets the data in onNext(...).
Whereas,
In observer pattern the observable directly emits the data or throws the data directly to the observer. This might create back-pressure.(cause it emits the whole data in one go.)
So use (Flowable)
.subscribeWith(new ResourceSubscriber<>) // in case of flowable
Or,
.subscribeWith(new DisposableSubscriber<>)
whereas in case of (observable) use
.subscribeWith(new ResourceObserver<>)