Hi Dev,
my AsyncHttpHandler() Codes i used in my ongoing project netmeme App...
What does this do?
AsyncHttpHandler() make an asynchronous request to your server,
- you can use this piece of codes to upload File from the android app to your server,
- make a POST request to your server
- make a GET request to your server
Can i upload a file and send $_POST data?
yes
Now Let's get started!
Step 1
Create Kotlin Class name it AsyncHttpHandler
Step 2
Make the Class open class by this
open class AsyncHttpHandler {
}
Step 3
Add Interface Listener to your AsyncHttpHandler Class
interface Listener {
fun onStart(){}
fun onProgress(result: Int){}
fun onSuccess(result: String?){}
fun onFailed(result: String?){}
}
Step 4
Set the listener and Add setListener method to the class
private var mListener: Listener = object : Listener {
}
fun setListener(listener: Listener): AsyncHttpHandler{
mListener = listener
return this
}
Step 5
Add inner AysncTask class name MakeServiceCallGet
@SuppressLint("StaticFieldLeak")
inner class MakeServiceCallGet : AsyncTask<String,Void,String?>(){
override fun onPreExecute() {
mListener.onStart()
}
override fun doInBackground(vararg urls: String?): String? {
var response: String? = null
try {
val url = URL(urls[0])
val conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "GET"
// read the response
val input = BufferedInputStream(conn.inputStream)
response = if (conn.responseCode == HttpURLConnection.HTTP_OK) {
// read the response
convertStreamToString(input)
} else {
null
}
} catch (e: MalformedURLException) {
Log.e(TAG, "MalformedURLException: " + e.message)
} catch (e: ProtocolException) {
Log.e(TAG, "ProtocolException: " + e.message)
} catch (e: IOException) {
Log.e(TAG, "IOException: " + e.message)
} catch (e: Exception) {
Log.e(TAG, "Exception: " + e.message)
}
return response
}
override fun onPostExecute(result: String?) {
if (result == null){
mListener.onFailed(result)
} else {
mListener.onSuccess(result)
}
}
}
Step 6
Add another AsyncTask class name MakeServiceCallPostWithFile
@SuppressLint("StaticFieldLeak")
inner class MakeServiceCallPostWithFile(val params: JSONObject) : AsyncTask<String,Int,String?>(){
override fun onPreExecute() {
mListener.onStart()
}
override fun doInBackground(vararg urls: String?): String? {
var response: String? = null
try {
val boundary = "*****"
val lineEnd = "\r\n"
val twoHyphens = "--"
val url = URL(urls[0])
val conn = url.openConnection() as HttpURLConnection
conn.readTimeout = 15000
conn.connectTimeout = 15000
conn.requestMethod = "POST"
conn.doInput = true
conn.doOutput = true
conn.useCaches = false
conn.setRequestProperty("Connection", "Keep-Alive")
conn.setRequestProperty("ENCTYPE", "multipart/form-data")
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=$boundary")
val dos = DataOutputStream(conn.outputStream)
val itr = params.keys()
while (itr.hasNext()) {
val key = itr.next()
val value = params.get(key)
when(value){
is File -> {
var bytesRead: Int
var bytesAvailable: Int
var bufferSize: Int
val maxBufferSize = 1 * 1024 * 1024
val fileInputStream = FileInputStream(value)
dos.writeBytes(twoHyphens + boundary + lineEnd)
dos.writeBytes("Content-Disposition: form-data; name=\"$key\";filename=\"${value.path}\"$lineEnd")
dos.writeBytes("Content-Type: ${Constants.fileMimeType(value.path)}$lineEnd")
dos.writeBytes(lineEnd)
// create a buffer of maximum size
bytesAvailable = fileInputStream.available()
bufferSize = Math.min(bytesAvailable, maxBufferSize)
val buffer = ByteArray(bufferSize)
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize)
var process: Int
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize)
//Progress
process = (bufferSize * 100 / bytesAvailable)
publishProgress(process)
bytesAvailable = fileInputStream.available()
bufferSize = Math.min(bytesAvailable, maxBufferSize)
bytesRead = fileInputStream.read(buffer, 0, bufferSize)
}
// send multipart form data necesssary after file
// data...
dos.writeBytes(lineEnd)
fileInputStream.close()
}
else -> {
dos.writeBytes(twoHyphens + boundary + lineEnd)
dos.writeBytes("Content-Disposition: form-data; name=\"$key\"$lineEnd")
dos.writeBytes("Content-Type: text/plain$lineEnd")
dos.writeBytes(lineEnd)
dos.writeBytes(URLEncoder.encode("$value", "UTF-8"))
dos.writeBytes(lineEnd)
}
}
}
dos.writeBytes(twoHyphens + boundary + twoHyphens
+ lineEnd)
// Responses from the server (code and message)
val responseCode = conn.responseCode
val serverResponseMessage = conn
.responseMessage
response = if (responseCode == HttpsURLConnection.HTTP_OK) {
// read the response
val `in` = BufferedInputStream(conn.inputStream)
convertStreamToString(`in`)
} else {
serverResponseMessage
}
// close the streams //
dos.flush()
dos.close()
} catch (e: MalformedURLException) {
Log.e(TAG, "MalformedURLException: " + e.message)
} catch (e: ProtocolException) {
Log.e(TAG, "ProtocolException: " + e.message)
} catch (e: IOException) {
Log.e(TAG, "IOException: " + e.message)
} catch (e: Exception) {
Log.e(TAG, "Exception: " + e.message)
}
return response
}
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
mListener.onProgress(values[0] ?: 0)
}
override fun onPostExecute(result: String?) {
if (result == null){
mListener.onFailed(result)
} else {
mListener.onSuccess(result)
}
}
}
Step 7
Add convertStreamToString method, this convert inputstream to strings, i used this to convert stream response from the server to string
private fun convertStreamToString(`is`: InputStream): String {
// val reader = BufferedReader(InputStreamReader(`is`))
val sb = StringBuilder()
try {
BufferedReader(InputStreamReader(`is`)).use { r ->
r.lineSequence().forEach {
sb.append(it).append('\n')
}
}
} catch (e: IOException) {
e.printStackTrace()
} finally {
try {
`is`.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
return sb.toString()
}
Step 8
Add companion object
companion object {
private val TAG = AsyncHttpHandler::class.java.simpleName
}
Usage
val asyncHttpHandler = AsyncHttpHandler()
asyncHttpHandler.setListener(object : AsyncHttpHandler.Listener {
override fun onStart() {
super.onStart()
}
@SuppressLint("SetTextI18n")
override fun onProgress(result: Int) {
Log.d("upload_progress", "$result")
}
@SuppressLint("SetTextI18n")
override fun onSuccess(result: String?) {
Log.d("upload_data", "$result")
}
override fun onFailed(result: String?) {
Log.d("upload_data_fail", "$result")
}
})
val params = JSONObject()
params.put("username","masterjosh")
params.put("caption","Happy Dev")
params.put("uploaded_file",File("/sdcard/masterjosh.png"))
asyncHttpHandler.MakeServiceCallPostWithFile(params).execute("https://forum.masterjosh.com/upload.php")
The full Code has been attached...