How can I go about uploading and receiving a users profile picture? - firebase

So far in my social media app, the user's data such as first name, last name, email, gender, and more can be saved in a firebase database and retrieved when needed. As of today, I got a working profile picture when first creating a profile you can tap on the empty profile picture icon and it loads up your gallery replacing it with whatever image the user chooses.
Although this is quite neat I need to be able to upload this image somehow under the Users node in my firebase database. I am quite lost when it comes to converting the bitmap data and after reading through some documentation it still confuses me. Below is my code for using a locally saved photo replacing it as the profile picture to show what I have so far.
#Override
public void onClick(View view)
{
if (view == profilePicture)
{
//Toast.makeText(this, "We made it to the onClick for image!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 0);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK)
{
Uri targetUri = data.getData();
Bitmap bitmap;
try
{
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(targetUri));
profilePicture.setImageBitmap(bitmap);
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The onClick method runs after the user taps the profile icon. Now I will show you the database I am currently working with, this is the Firebase real-time database, not the Firebase storage. While firebase storage might be more appropriate I can't seem to figure out how to tell whos photo would be who as it does not upload them with a user id associated with them.
Database Picture Here

Instead of uploading a bitMap, a far better solution for a simple problem like yours would be Firebase Storage, similar to the Database but you can upload files such as images with much ease.
Here are the methods I currently use in my app:
private void chooseImage() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
}
private void uploadImage() {
if(filePath != null)
{
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Uploading...");
progressDialog.show();
StorageReference ref = storageReference.child("images/"+userID);
ref.putFile(filePath)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
progressDialog.dismiss();
toastMessage("Uploaded");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
progressDialog.dismiss();
toastMessage("Failed"+e.getMessage());
}
})
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
double progress = (100.0*taskSnapshot.getBytesTransferred()/taskSnapshot
.getTotalByteCount());
progressDialog.setMessage("Uploaded "+(int)progress+"%");
}
});
}
}

Related

how to give access my xamarin.forms webview for use browse file?

I use a WebView on my Xamarin app, and I use it without any problem. but I can't use browse file on my phone for select file. I click button but I don't see any action. that is work on my web site, but I can't use it on my phone app.
On my web
You can check this code and use the new Uri[].
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
{
if (requestCode == FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage) return;
Android.Net.Uri result = intent.Data;
mUploadMessage.OnReceiveValue(new Uri[] { result });
mUploadMessage = null;
}
}

SQLITE Delete item does't delete for real

I got a xamarin forms app, and the problem is when I delete an item from a sqlite table, it looks like all works, the item is deleted from the collection, the grids got updated, etc, but when I restart the app, the item is still there. its like the delete only works in memory but it never got saved in the database.
my code is below
I create an instance called DB in my App constructor
public partial class App
{
static Database database;
public static Database DB
{
get
{
if (database == null)
{
string nombreBD = "MyDataBaseFile.db3";
string _databasePath = Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, nombreBD);
database = new Database(_databasePath);
}
return database;
}
}
................
}
I'm using sqlite with tables created from classes, like this
db = new SQLiteAsyncConnection(dbPath);
db.CreateTableAsync<MyType>().Wait();
where MyType is a class like this
public class MyType
{
[PrimaryKey]
public int Idtable { get; set; }
......
}
I try to delete a row of the table like this:
var x = await App.DB.GetItemAsync<MyType>(obj.Idtable );
int regsDeleted = await App.DB.DeleteItemAsync<MyType>(x);
the GetItemsAsync is basically: await db.FindAsync<T>(id);
public async Task<T> GetItemAsync<T>(int id) where T : new()
{
try
{
return await db.FindAsync<T>(id);
}
catch (System.Exception ex)
{
throw new System.Exception($"Error sqlLite {MethodBase.GetCurrentMethod().Name}: {ex.Message}");
}
}
and the delete method is this:
public async Task<int> DeleteItemAsync<T>(T item) where T : new()
{
try
{
int regsDeleted=await db.DeleteAsync(item);
db.GetConnection().Commit();
return regsDeleted;
}
catch (System.Exception ex)
{
throw new System.Exception($"Error sqlLite {MethodBase.GetCurrentMethod().Name}: {ex.Message}");
}
}
like I said I got no errors and all looks like worked, but when restart the app, the item still there!!
any Idea? something to add in the connection maybe? transactions?... any help will be great
thanks
UPDATE After a lot of test I realize the problem is not the delete. The problem is that every time I run the app from VS to my android device through USB cable, I don't know how or why the database get restored from some backup, that I donĀ“t know when or where was done. Looks like Android have a backup and the "data" of my app and when a new version comes he just restore the data. I read somne that said the Xamarin.Essentials.FileSystem.AppDataDirectory should not be used to save databases, so the question is. where is th right place to save the SQLLite database.Any Idea? My app don't deployed an empty database, my app create the database in the first execution. Does anyone knows how to avoid that restauration of the folder? every time I run the app from VisualStudio ?
The DeleteAsync works without Commit. I make come changes for your code. It works on my side.
I add the PrimaryKey and AutoIncrement attributes to ensure that each Note instance in the SQLite.NET database will have a unique id provided by SQLite.NET.
public class MyType
{
[PrimaryKey, AutoIncrement]
public int Idtable { get; set; }
public string Text { get; set; }
}
The code for the connect to the database, save the record, delete the row and get the all the items.
readonly string _databasePath = Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "MyDataBaseFile.db3");
SQLiteAsyncConnection database;
public MyType myType { get; set; }
int i = 0;
public Page2()
{
InitializeComponent();
}
private void Connect_Clicked(object sender, EventArgs e)
{
database = new SQLiteAsyncConnection(_databasePath);
database.CreateTableAsync<MyType>().Wait();
}
async void Save_Clicked(object sender, EventArgs e)
{
myType = new MyType() { Text = "Hello" + i };
if (myType.Idtable != 0)
{
// Update an existing note.
await database.UpdateAsync(myType);
i++;
}
else
{
// Save a new note.
await database.InsertAsync(myType);
i++;
}
}
async void Delete_Clicked(object sender, EventArgs e)
{
var x = await database.FindAsync<MyType>(myType.Idtable);
int regsDeleted = await database.DeleteAsync(x);
}
async void Get_Clicked(object sender, EventArgs e)
{
var s = await database.Table<MyType>().ToListAsync();
try
{
var s2 = await database.FindAsync<MyType>(myType.Idtable);
}
catch
{
return;
}
}
}
Please note if i restart the app, there is no myType.Idtable. So i use the try catch to make my project run.
Add four items for the database and detele the last one.
After restart the app, the items:
I had a similar error. Very annoying and couldn't figure it out. After reading this question I have just deleted the db3 file on the android device rerun my app and now it works. I suspect that during development and changing the structure of the class for the table something gets screwed up. Deleting the database db3 (or whatever, sqlite doesn't care) re-created the the tables completely.
So how do you get to the file? (For a Pixel 5 emulator)
I used Android Studio and the DeviceFileExplorer (View>ToolWindows)
But where is it. Well In my app I use
private readonly static string filename = "xxx.db3";
...
database = new Database.Database(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), filename));
and I (eventually) found this located in data>data>(my Application Id)>files
where my ApplicationID is something like uk.co.mydomainname.myappname
I just then deleted the file with a right click delete
(Note: I found sometimes you have to right click the files folder and synchronise to refresh the tree and see the db file)
Hope this helps.
PS I wish for me (.net maui) the documentation explained more clearly the paths and where things get located/placed!!

How to know FirebaseRecyclerAdapter query is zero or not, exist or not

How to know FirebaseRecyclerAdapter query is zero or not, exist or not
I find some instructions on
https://github.com/firebase/FirebaseUI-Android/tree/master/database
it says:
Data and error events
When using the FirebaseRecyclerAdapter you may
want to perform some action every time data changes or when there is
an error. To do this, override the onDataChanged() and onError()
methods of the adapter:
FirebaseRecyclerAdapter adapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(options) {
// ...
#Override
public void onDataChanged() {
// Called each time there is a new data snapshot. You may want to use this method
// to hide a loading spinner or check for the "no documents" state and update your UI.
// ...
}
#Override
public void onError(DatabaseError e) {
// Called when there is an error getting data. You may want to update
// your UI to display an error message to the user.
// ...
}
};
When I tried to use as follow:
mAdapter = new FirebaseRecyclerAdapter<Place, PlaceViewHolder>(options)
{
#Override
public void onDataChanged(DataSnapshot dataSnapshot)
{
// Called each time there is a new data snapshot. You may want to use this method
// to hide a loading spinner or check for the "no documents" state and update your UI.
// ...
if (dataSnapshot.exists())
{
Log.d(TAG,"data exists");
}
else
{
Log.d(TAG,"No data exists");
}
}
#NonNull
#Override
public PlaceViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i)
{
Error message is:
Method does not override method from its superclass
So how can I solve this problem, Thank you.
I found the answer from another page:
https://www.programcreek.com/java-api-examples/?api=com.firebase.ui.database.FirebaseRecyclerAdapter
#Override
public void onDataChanged()
{
// Called each time there is a new data snapshot. You may want to use this method
// to hide a loading spinner or check for the "no documents" state and update your UI.
// ...
if (getItemCount() == 0)
{
Log.d(TAG,"No data exists");
}
else
{
Log.d(TAG,"data exists");
}
}

Moving cloud firestore collection

I have a scenario in which I want to move my top level, in other words first, collection to the third level. Is the only way to go about this to use third party import-export software with manipulation to do this, or is there a firestore feature that I am missing?
All help will be greatly appreciated.
TopLevel>Documents>ThirdLevel, where top level is the first collection in the db. Just to give a better picture of what I am trying to say.
Firestore has no ability to move collections or documents. Instead, you can copy documents. You'll have to write code to read the contents of a document, then write those contents to a document in a new location, then delete the original document.
I know it's an old question, but just in case someone else needs this. It's now possible using google's cloud shell.
Details available in this link:
https://firebase.google.com/docs/firestore/manage-data/export-import
You have two options to export specific collections, modify them, then import them, or export the whole bucket, then import it back. As I understood you can't mix the operations for example export all and import specific collections.
Note: I believe you'll be charged for the read and write of all documents exported and imported. And billing must be activated.
maybe this can help
public void moveFirestoreDocument(DocumentReference fromPath, final DocumentReference toPath) {
fromPath.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document != null) {
toPath.set(document.getData())
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully written!");
fromPath.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully deleted!");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error deleting document", e);
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error writing document", e);
}
});
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
}

if(resultCode==Activity.RESULT_OK) is returning false

I am working on a very basic app which captures a photo using the phone's camera and sets it up on the ImageView. But the code is not entering the if(resultCode==Activity.RESULT_OK) statement. I understood this by using Log inside the if statement. Any idea how I can resolve this? Here is the onActivityResult()
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==Activity.RESULT_OK){
Log.v("cam"," resultCode");
Bundle extras=data.getExtras();
bmp=(Bitmap) extras.getParcelable("data");
iv.setImageBitmap(bmp);
button1.setText("Take Another");
}
}
first of all
Check that u have all the necessary permission in the manifest file for capturing the image and where you're storing that image that folder access.
Check it out for more reference. for reference
Try This ... It works for Me..
if ( resultCode == Activity.RESULT_OK ) {
Uri path = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(),path);
imgView.setImageBitmap(bitmap);
imgView.setVisibility(View.VISIBLE);
Name.setVisibility(View.VISIBLE);
} catch (IOException e) {
e.printStackTrace();
}
}

Resources