In android studio I used this code to convert image to byte array and send to server:
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] byteArrayImage = baos.toByteArray();
String encodedImage = Base64.encodeToString(byteArrayImage, Base64.DEFAULT);
ServerService.sendProfileImage(encodedImage);
In node-js back-end I use this code to write data to file:
let imageBuffer = new Buffer.from(data.info, 'Base64');
fs.writeFile(fd, imageBuffer, (err, written) => {
if(err) {
callBack(err);
return;
} else{
fs.close(fd, () => {
callBack(null);
return;
});
}
})
Note: back-end works perfect with browser and saved images show correctly, > no problem; Android data is saved too, but image is not in correct format.
But some thing is wrong and Image is not a valid file.
The java code produces correct Base64 image String.
There might be an issue while sending this string to your server. Try to print your base64 string on the server end to check whether you are getting full string from the request or not. if the string is correct then try following code to save the image
app.post('/save-image', (req, res) => {
require("fs").writeFile("out.jpg", req.body.info, 'base64', function(err) {
console.log(err);
});
})
The above code uses body-parser package to access the info field.
This is my code which i've used in Android
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.util.Base64
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import okhttp3.*
import java.io.ByteArrayOutputStream
import java.io.IOException
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
submit.setOnClickListener {
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.out)
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val imageBytes: ByteArray = baos.toByteArray()
val imageString = Base64.encodeToString(imageBytes, Base64.DEFAULT)
send(imageString)
}
}
private fun send(imageString: String) {
val body = FormBody.Builder()
body.add("info",imageString)
val request = Request.Builder().url("http://192.168.1.4:3000/save-image").post(body.build())
OkHttpClient.Builder().build().newCall(request.build()).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("Failure",Log.getStackTraceString(e))
}
override fun onResponse(call: Call, response: Response) {
Log.e("response",response.body?.string() ?: "failed")
}
})
}
}
Related
I want to parse an excel file in "external storage" with apache POI on an android phone. I put the file in the downloads folder when I downloaded it. I can always expect it to be there, not on a cloud, not being edited by other apps, not ephemeral in any way. The Apache POI workbookfactory needs a FileInputStream. After trying many different things I am burnt out.
Other similar questions on here involve huge swaths of code that deal in images and fanciful sources. All the examples I find use startActivityForResult which is DEPRECATED. So I tried some registerForActivityResult using contracts. No dice. Anyone know why the mime type "application/vnd.ms-excel.sheet.macroEnabled.12" doesn't work for xlsm files but images/png does? I also tried copying the file from content URI to local/app/scoped/cachedir storage and I wasn't successful either.
I was expecting the ability to point to a file and say "into the Apache POI excel file wood chipper with you!" and like in Fargo the Apache POI would spit little red cell values all over Log.d and eventually I'll do stuff with that information.
import android.content.ContentResolver
import android.net.Uri
import android.os.Bundle
import android.os.ParcelFileDescriptor
import android.provider.OpenableColumns
import android.util.Log
import android.widget.Button
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import org.apache.commons.compress.utils.IOUtils
import org.apache.poi.ss.usermodel.WorkbookFactory
import java.io.*
import java.nio.channels.FileChannel
fun readingxl(input: InputStream?) {
//Workbook wb = Workbookfactory.create(new File(bob.getPath()))
//Log.d("wtf",bob.toString())
//val input = FileInputStream("./text.xlsm")
//val xlWb = WorkbookFactory.create(input)
//val input = FileInputStream(bob.getPath())
val xlWb = WorkbookFactory.create(input)
Log.d("wtf","b")
//val xlWb = WorkbookFactory.create(input)
Log.d("wtf","c")
val xlWs = xlWb.getSheet("Daily Recording")
Log.d("wtf","d")
for (j in 44..50) {
for (i in 0..11) {
//Log.d("wtf",((("${xlWs.getRow(j).getCell(i)}, ")).toString()))
Log.d("wtf", "${xlWs.getRow(j).getCell(i)}, ")
}
}
}
fun ContentResolver.getFileName(fileUri: Uri): String {
var name = ""
val returnCursor = this.query(fileUri, null, null, null, null)
if (returnCursor != null) {
val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
returnCursor.moveToFirst()
name = returnCursor.getString(nameIndex)
returnCursor.close()
}
return name
}
class MainActivity : AppCompatActivity() {
val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
// 'ActivityResultCallback': Handle the returned Uri
if (uri != null) {
Log.d("wtf",uri.getPath().toString())
val inputStream = applicationContext.contentResolver.openInputStream(uri)
readingxl(inputStream)
/*
val parcelFileDescriptor = applicationContext.contentResolver.openFileDescriptor(uri, "r", null)
parcelFileDescriptor?.let {
val inputStream = FileInputStream(parcelFileDescriptor.fileDescriptor)
val file = File(applicationContext.cacheDir, "text.xlsm")//applicationContext.contentResolver.getFileName(uri))
val outputStream = FileOutputStream(file)
IOUtils.copy(inputStream, outputStream)
}*/
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
///storage/emulated/0/Download
var button = findViewById<Button>(R.id.button)
button.setOnClickListener{
//getContent.launch("*/*")
getContent.launch("*/*")
}
}
}
I get the following error when trying to iterate over the uploadTasks inside an addOnSuccessListener method.
java.lang.ClassCastException: com.google.firebase.storage.UploadTask$TaskSnapshot cannot be cast to com.google.firebase.storage.UploadTask
So how can i get the Download String of each Img inside addOnSuccessListener?
val baos = ByteArrayOutputStream()
val tasks = mutableListOf<UploadTask>()
listImg.forEach {
if(bitmap!!.byteCount != it.byteCount) {
val bitmap = it
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val data = baos.toByteArray()
var uploadTask = spaceRef.putBytes(data)
tasks.add(uploadTask)
}
}
Tasks.whenAllSuccess<UploadTask>(tasks).addOnSuccessListener { uploadTasks ->
//uploadTasks has size of 2
val urls = mutableListOf<Uri>()
lifecycleScope.launch
{
//Error throws here
uploadTasks.forEach{
urls.add(it.await().storage.downloadUrl.await())
}
}
}
The type of whenAllSuccess is <TResult>, so you should use the result type of UploadTask (UploadTask.TaskSnapshot) instead:
Tasks.whenAllSuccess<UploadTask.TaskSnapshot>(tasks).addOnSuccessListener { uploadTasks ->
And then you can drop the the first await() on that last line:
urls.add(it.storage.downloadUrl.await())
Bonus: Don't block the main thread
Note that Tasks.whenAllSuccess() will block the main thread until all uploads succeed, meaning your UI might freeze while uploading files.
To avoid that, consider uploading your files with Coroutines:
val baos = ByteArrayOutputStream()
val urls = mutableListOf<Uri>()
lifecycleScope.launch {
listImg.forEach {
if(bitmap!!.byteCount != it.byteCount) {
val bitmap = it
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val data = baos.toByteArray()
// Upload the image first
val taskSnapshot = spaceRef.putBytes(data).await()
// Get the download Url
val downloadUri = taskSnapshot.storage.downloadUrl.await()
// Add it to the list of Uris
urls.add(downloadUri)
}
}
}
I recently asked a question on how to get the HTML code from a Google API Script that fed me an IP Address, and received an answer that told me to use this Utility Class. (I am coding this in Kotlin)
package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.MalformedURLException
import java.net.URL
object ContentScrapper {
fun getHTMLData(activity: AppCompatActivity,url: String, scrapListener: ScrapListener) {
Thread(Runnable {
val google: URL?
val `in`: BufferedReader?
var input: String?
val stringBuffer = StringBuffer()
try {
google = URL(url)
`in` = BufferedReader(InputStreamReader(google.openStream()))
while (true) {
if (`in`.readLine().also { input = it } == null)
break
stringBuffer.append(input)
}
`in`.close()
activity.runOnUiThread {
scrapListener.onResponse(stringBuffer.toString())
}
} catch (e: MalformedURLException) {
e.printStackTrace()
activity.runOnUiThread {
scrapListener.onResponse(null)
}
}
}).start()
}
interface ScrapListener {
fun onResponse(html: String?)
}
}
And called it using this
ContentScrapper.getHTMLData(this, url, object : ContentScrapper.ScrapListener{
override fun onResponse(html: String?) {
if(html != null) {
editTexttest.setText(html)
} else {
editTexttest.setText("Not Found")
}
}
})
However, I was unable to find the string that was displayed on my screen. Below is the link that I am currently using to get the string. The HTML code that is returned to me doesn't seem to contain the string that the url below provides. Is there anything wrong with how I called it? Any help is appreciated. Thanks.
https://script.google.com/macros/s/AKfycbyjRIRl2ca_pnfz8XgccjDlaRPUNz6KY_WcyPZAROsy9EZkD35F/exec?command=GetLock1IPAddress
I am making a specimen inventorying android app in Kotlin using Google Firebase. I use the firebase Realtime Datebase to store the specimen details & use firebase storage to store a picture of the specimen.
Eventually I will want to pull all of this data into the app to browse.
My Question: What is the best way to link the specimen's details in Realtime db to it's associated picture in Storage?
my code
RockEntry.kt
package com.inven.rock_stock
import android.util.Log
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener
import java.util.*
class RockEntry {
var name = ""
var purchDate = ""
var local = ""
var mine = ""
var weight = ""
var paid = ""
var asking = ""
var description = ""
var dimensions = ""
var specimenNumber = ""
var Uid = ""
var database = FirebaseDatabase.getInstance()
var ref = database.getReference("Rocks")
constructor(name:String,purchDate:String,local:String,mine:String,
weight:String,dimensions:String,paid:String,asking:String,
description:String,Uid:String){
this.name = name
this.purchDate = purchDate.toString()
this.local = local
this.mine = mine
this.weight = weight
this.dimensions = dimensions
this.paid = paid
this.asking = asking
this.description = description
this.Uid = UUID.randomUUID().toString()
}
MainActivity.kt
package com.inven.rock_stock
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.tasks.Continuation
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.storage.FirebaseStorage
import com.google.firebase.storage.StorageReference
import kotlinx.android.synthetic.main.activity_main.*
import java.io.ByteArrayOutputStream
import java.io.File
import java.net.URI
var CAMERA_REQUEST_CODE = 0
var database = FirebaseDatabase.getInstance()
var ref = database.getReference("Rocks")
private var mStorageRef: StorageReference? = null
class MainActivity : AppCompatActivity() {
private val TAG = "MyActivity"
override fun onCreate(savedInstanceState: Bundle?) {
mStorageRef = FirebaseStorage.getInstance().getReference("ImagesBB")
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
makeQuery()
}
imageBtn.setOnClickListener {
takePicture()
}
}
private fun makeQuery(){
var name = name.text.toString()
var purchDate = purchDate.toString()
var local = locality.text.toString()
var mine = mine.text.toString()
var weight = weight.text.toString()
var dimensions = dimensions.text.toString()
var paid = paid.text.toString()
var asking = asking.text.toString()
var description = description.text.toString()
if (!name.isBlank()) {
ref.child(name.toLowerCase()).setValue(
RockEntry(
name,
purchDate,
local,
mine,
weight,
paid,
asking,
dimensions,
description
)
)
}
else {
Toast.makeText(applicationContext, "Type in a name", Toast.LENGTH_LONG).show()
}
}
private fun takePicture() {
CAMERA_REQUEST_CODE = 222
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
try {
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE)
} catch (e: ActivityNotFoundException) {
// display error state to the user
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
CAMERA_REQUEST_CODE -> {
if (resultCode == Activity.RESULT_OK && data != null) {
val imageBitmap = data.extras?.get("data") as Bitmap
val baos = ByteArrayOutputStream()
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val datar = baos.toByteArray()
mStorageRef!!.putBytes(datar)
}
}
}
}
}
'Linking' a FireBase Storage file to your Realtime Database can be accomplished by either
getting the location where a file lives in FireBase storage, via
toString() on the storage reference
or
getting a URL where you can download the file, via the .downloadUrl function.
Either of these options can then be stored as text into a Realtime Database 'entry'.
code example:
yourStorageBase?.putFile(element)?.addOnSuccessListener {
yourStorageBase?.downloadUrl?.addOnSuccessListener { downloadUri ->
// #1
var filepath = yourStorageBase.toString()
// #2
var downloadLink = downloadUri.toString()
}
}
Note:
If the following code is used within a function, you may 'prematurely' return to the caller before the picture has finished uploading, meaning you can't use the 'links' immediately. You can write a coroutine to ensure the IO has time to complete.
User RecyclerView to load all data in your app using live model class with data adapter.
User DataSnapShot in firebase to get all of the child nodes from a parent.
In Firebase DB, You have specimen which holds a number of Specimen, then you need to have one picture node as a child of each specimen node. When you upload the picture to Firebase Storage fetch its URL and insert it to the picture node under that particular Specimen.
i want request to Flask server.
so, i converted a img to JSON data in Kotlin(Android Studio)
Although JSON data is well sent and received from the server, the size of the transmitted data is five times larger than the original data.
what should i do to get exact data from server??
Simple Server Code(python)...
print(len(request.json['file']))
img_data = base64.b64decode(request.json['file'])
filename = 'received_now_starry_night.png'
with open(filename, 'wb') as f:
f.write(img_data)
dic = {
"msg":"hello"
}
return jsonify(dic)
Android Studio, kotlin Code...
val bitmap:Bitmap = BitmapFactory.decodeResource(resources, R.drawable.starry_night)
val bos:ByteArrayOutputStream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos)
val image:ByteArray = bos.toByteArray()
val base64Encoded = java.util.Base64.getEncoder().encodeToString(image)
val rootObject = JSONObject()
rootObject.put("file", base64Encoded)
To convert an image to Base64 String :
You can also create a resized Bitmap and compress it to decrease the size
private fun CreateImageStringFromBitmap(): String {
val bitmap:Bitmap = BitmapFactory.decodeResource(resources, R.drawable.starry_night)
val resized = Bitmap.createScaledBitmap(
bitmap:Bitmap, (desired width).toInt(),
(desired height).toInt(), true
)
val stream = ByteArrayOutputStream()
resized.compress(Bitmap.CompressFormat.PNG, 75, stream)
val byteArray: ByteArray = stream.toByteArray()
return Base64.encodeToString(byteArray, Base64.DEFAULT)
}