I'm wanting to use Kotlin to update a contact with a new Bitmap bmp as a profile picture. I found documentation for editing contacts, but I can't find a field on the intents page for changing the photo. Any stack overflow solutions I found all involve strange ways of updating it, even though the developer page encourages using intents. What's the best way to change contact photos?
First of all, never use bmp, it's such a huge file you don't want to put bmp photos in any database.
So, now to insert a new picture to a specific raw-contact, and assuming you have some standard picture file (jpeg/png) on hand, you do this:
val rawContactPhotoUri = Uri.withAppendedPath(
ContentUris.withAppendedId(RawContacts.CONTENT_URI, yourRawContactId), // note that this must be a RAW-contact-id, not a contact-id
RawContacts.DisplayPhoto.CONTENT_DIRECTORY
) // this is the url the represents a RawContact picture
try {
val bytes = yourPictureFile.toByteArray() // get a byte array from your pic
val fd = context.contentResolver.openAssetFileDescriptor(rawContactPhotoUri, "rw")
val os = fd?.createOutputStream()
os?.write(bytes)
os?.close()
fd?.close()
} catch (e: IOException) {
// Handle the error
}
Related
I get an image from an user which is converted into a bitmap. I then convert the bitmap to a an byte array and send it over JSON to be stored in a database. Then when the user starts the particular activity I want the image to be retrieved form the database and displayed to the user.
In the application a user is able to make a post with a title, description and an image. I want these three variables stored in the database so that when someone else views the post, they are able to see all the content. Also the image would be stored in the database as a blob, i simply use JSON to send the data to an backend application which handles all the communication with the DB.
My problem is that the bitmap that I get seems to be a reference to some memory on the device android.graphics.Bitmap#324a72b which changes every time I run the application although I select the same image. I want to be able to retrieve the actual bitmap so it can be stored in a DB. I'm also not using as web server for storing the images since its a smaller project.
b.buttonNewItemUpImg.setOnClickListener {
val openGalleryIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(openGalleryIntent, ResultLoadImage)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == ResultLoadImage){
if (resultCode == Activity.RESULT_OK){
var temp = MediaStore.Images.Media.getBitmap(this.contentResolver, data!!.getData())
bitmap = getResizedBitmap(temp!!, maxImageSize)
b.imageView.setImageURI(data!!.getData())
}
}
}
The getResizedBitmap() function simply makes the image smaller.
As described in https://stackoverflow.com/a/57576381/6359367
Use this
var temp = ImageDecoder.createSource(this.getContentResolver(), data!!.getData())
bitmap = ImageDecoder.decodeBitmap(temp);
beware this code was java I tried to adapt it to kotlin you may need to tweak it a bit
Instead of storing the whole image in the database, you should copy images to the app's local storage and then store, path of these copied images to the database, which you can use later to retrieve the images.
Copying image to the app's local storage after getting the selected image uri
//creating an image file in the app's local storage
val dir = requireActivity().getDir(FOLDER_TO_SAVE, Context.MODE_PRIVATE).path
val copiedImageFile = File(dir, UUID.randomUUID().toString() + ".jpg")
val copiedImageUri = Uri.fromFile(copiedImageFile)
//copying selected image to the local storage
data!!.getData().path?.let {
File(it).copyTo(copiedImageFile)
}
Get path of the above copied image, using its uri
copiedImageUri.path.?.let{
val copiedImagePath = "file://$it"
//now save this path to your database
}
Use this saved image path to retrieve the image in any fragment or activity.
I am writing an App for my diploma thesis and my partner has a external Mariadb. I can get and set data on the mariadb easily, but whenever we try to upload a picture we get the following problem, that I dont know how.
In my SetData Kotlin Class I have the following Code:
val query =
"INSERT INTO Profiles (p_name, notification, unit, p_picture) VALUES ('$nam', $noti, $uni, $pic)"
val stmt: Statement = connect!!.createStatement()
val rs: ResultSet = stmt.executeQuery(query)
For the converting the chosen Picture into bitmaps, byteArrays & co. I have these lines:
bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, imageUri)
var bos = ByteArrayOutputStream()
bitmap!!.compress(Bitmap.CompressFormat.PNG, 100, bos)
val bArray = bos.toByteArray()
var p_picture: String = Base64.encodeToString(bArray, Base64.DEFAULT)
And then invocating my function where I transport the parameters for the already mentioned "query":
setData.setValues(p_name, p_notification, p_unit, p_picture)
When working without a picture (in this case p_picture is null) everything works fine and the database has a now entity. But if try the same thing with a chosen picture, I get the following error in the "query"-line:
2021-02-10 17:11:13.899 5974-5974/com.example.dbtesting E/ErrorĀ 1: (conn=149) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'nFS9W5McSY8lBsBvccmsItlfr82Y1mTSrKRfs0/6/09jspHZfN0kqzIzLu4OYB9ORJBTD23N7mJk
I have already reviewed other questions on SOF, but nobody wanted to the same thing, they always did it with PHP, while we have a "direct" connection to the external database.
Sideinformation: The datatype of picture in the database is a BLOP.
So my problem simply is, what have I to do, that the syntax is right. Maybe other datatype? Maybe do it differently? But to be honest we won't use PHP, since it is working everything except this little extra feature.
Thanks in advance!
The solution is to use preparedStatements, with simple SQL Injections like the one I used in my question, you will not succeed. By using preparedStatements, now functions like setBinaryStream and getBinaryStream are possible and can/will be used for uploading/downloading BLOBs from extern databases. I hope some people will get an epiphany when reading my answer. The comment from #danblack helped me a lot, since I focused on preparedStatements and found some useful information.
My application takes pictures via camera intent. How should I display their small size version in a grid view for viewing purpose. Should I create their thumbnails and store them in cache or external storage Or should I use the thumbnails created by Default Gallery application. My pictures are stored in external storage so I am expecting that Default Gallery Application would make their thumbnails automatically. If yes, then how should I map each image with the thumbnail created by Default Gallery Application.
Well, I have found that Async class could handle the memory usage scenario.
The relevant link is: http://developer.android.com/intl/es/reference/android/os/AsyncTask.html
Well, I have got an answer
public Bitmap getbitpam(String path) {
Bitmap imgthumBitmap = null;
try {
final int THUMBNAIL_SIZE =300 ;
FileInputStream fis = new FileInputStream(path);
imgthumBitmap = BitmapFactory.decodeStream(fis);
imgthumBitmap = Bitmap.createScaledBitmap(imgthumBitmap,
THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);
ByteArrayOutputStream bytearroutstream = new ByteArrayOutputStream();
imgthumBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytearroutstream);
} catch (Exception ex) {
}
return imgthumBitmap;
}
However, this is taking a lot of RAM. I Have also found a strange behavior. That as I am scrolling in grid view, it is taking more RAM. The growth in memory used is cumulative and finally the app is crashing due to Memory_Low exception. Any workaround for it??
Got answer for second problem too:-- Async class.
According to the official documentation which contains information about contact's photo handling (Android 4.0):
Large photos
Android now supports high resolution photos for contacts. Now, when
you push a photo into a contact record, the system processes it into
both a 96x96 thumbnail (as it has previously) and a 256x256 "display
photo" that's stored in a new file-based photo store (the exact
dimensions that the system chooses may vary in the future). You can
add a large photo to a contact by putting a large photo in the usual
PHOTO column of a data row, which the system will then process into
the appropriate thumbnail and display photo records.
So, I would like to know if I store a photo with the size of 400x400 px, is there any possibility to retrieve this photo with it's original size, or I have to be glad only having a photo with decreased size?
Try this example:
public void writeDisplayPhoto(long rawContactId, byte[] photo) {
Uri rawContactPhotoUri = Uri.withAppendedPath(
ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
RawContacts.DisplayPhoto.CONTENT_DIRECTORY
);
try {
AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor(
rawContactPhotoUri,
"rw"
);
OutputStream os = fd.createOutputStream();
os.write(photo);
os.close();
fd.close();
} catch (IOException e) {
// Handle error cases.
}
}
Using file descriptors you can read/write contact photo. Also I think you need store thumbnail of your photo to contact
For more info see ContactsContract.RawContacts.DisplayPhoto class
Simple solution:
Login to your gmail account from any PC, then search for "contacts"
From within contacts page: enter the contact name you want to search for
Click on the contact that you want & select "save image..."
Note: I don't know if there is a higher quality version inside the phone but I'm still working on it.
I've written an app, thats loading images either using the android gallery app or by taking a photo using the cam.
When I now load an image using the gallery, everything is fine. When the code is being executed a second time (for loading another image), the application crashes.
try {
Uri data = intent.getData();
ContentResolver cr = this.getContentResolver();
Bitmap mBitmap = null;
mBitmap = Media.getBitmap(cr, data);
imageView.setImageBitmap(mBitmap);
} catch(Exception e){
showToast(this, "Failed loading image from gallery");
return;
}
The code crashes at the line mBimap = Media.getBitmap(cr, data);. Everything is initialized, there are no null values etc. The strange thing is: no exception is thrown, I don't get into the catch block to determine whats going wrong.
Does anyone have an idea about this? Am I not allowed to "re-use" the content resolver? Do I have to free it after the first usage or something like this?