I need to make a post request to an endpoint from my android project. I am using Kotlin. Will I need to create a separate OKHttpClient Class for this.
Here's how you can achieve this:
val payload = "test payload"
val okHttpClient = OkHttpClient()
val requestBody = payload.toRequestBody()
val request = Request.Builder()
.method("POST", requestBody)
.url("url")
.build()
okHttpClient.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// Handle this
}
override fun onResponse(call: Call, response: Response) {
// Handle this
}
})
Don't forget to import:
import okhttp3.RequestBody.Companion.toRequestBody
Related
I've been developing an Android Q&A app using Jetpack Compose. I've been trying to make Post requests in Retrofit but the data I send isn't on my API website. I've succeeded in making Get requests though. I've read many documents but I cannot find out what is wrong with this code.
This is data class.
data class UsersEntity(
val id: Int? = null,
val name: String? = null,
val uid: String? = null
)
This is Service interface.
interface UserService {
#POST("createusers")
fun createUsers(#Body usersinfo: UsersEntity): Call<Unit>
}
When I click a button, I'd like to send data to the server. I get the log "Hi, good job" but I cannot see the data on my API.
Button(
onClick = {
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://api.*****.com/")
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
val service: UserService = retrofit.create(UserService::class.java)
val usersInfo = UsersEntity(
3, "Alex", "164E92FC-D37A")
service.createUsers(usersInfo).enqueue(object: Callback<Unit> {
override fun onResponse(call: Call<Unit>, response: Response<Unit>) {
Log.d("Hi", "good job")
}
override fun onFailure(call: Call<Unit>, t: Throwable) {
Log.d("Hi", "error")
}
})
}
I changed the code like this.
Button(
onClick = {
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://api.*****.com/")
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
thread {
try {
val service: UserService = retrofit.create(UserService::class.java)
val usersInfo = UsersEntity(
3, "Alex", "164E92FC-D37A")
service.createUsers(usersInfo).enqueue(object: Callback<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
Log.d("Response", "${response.body()}")
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
Log.d("Hi", "error")
}
})
} catch (e: Exception) {
Log.d("response", "debug $e")
}
}
},
Could someone help me? Thank you.
I think your baseurl shouldn't end with a slash. Try this.
.baseUrl("https://api.*****.com")
And for your interface (also the Call<ResponseBody>):
interface UserService {
#POST("/createusers/")
fun createUsers(#Body usersinfo: UsersEntity): Call<ResponseBody>
}
Got some issues with this in the past so this might help. If not it atleasts cleans the code a bit :p
Also you can use ProxyMan to intercept your request and read what your application is actually sending to the server, might be a issue to find there!
Proxyman.io
I used retrofit2 to call API. But, when I called it, my app was just shut down. There are not errors in the Logcat. I googled it, but there is not a solution.
And Retrofit2 and converter-gson version is 2.9.0. I set internet permission in AndroidManifest.xml
MainActivity.kt
private fun loadMembers() {
val retrofit = Retrofit.Builder()
.baseUrl(MemberAPI.base_domain)
.addConverterFactory(GsonConverterFactory.create())
.build()
val retrofitService = retrofit.create(MemberInterface::class.java)
retrofitService
.getMember(Constants.api_key)
.enqueue(object: Callback<Member> {
override fun onResponse(call: Call<Member>, response: Response<Member>) {
val members = response.body() as Member
var names = ""
for (member in members.response.body.items.item) {
names += "\n${member.empNm}"
}
binding.text.text = names
}
override fun onFailure(call: Call<Member>, t: Throwable) {
Toast.makeText(baseContext, "실패", Toast.LENGTH_LONG).show()
}
})
}
Interface.kt
interface MemberInterface {
#GET("{api_key}&numOfRows=5&pageNo=1&_type=json")
fun getMember(#Path("api_key") Key: String): Call<Member>
}
Youtube
Video
Try to add an interceptor so you can see all calls logs (headers, body, URLs, etc...). The crash could be related with the parse of the JSON response to the object Member.
Add OkHtpp to your grade dependencies:
implementation "com.squareup.okhttp3:okhttp:5.0.0-alpha.2"
implementation "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2"
And after that, when you create your Retrofit instance, add the interceptor, should look something like this:
val httpClient = OkHttpClient.Builder()
val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
httpClient.addInterceptor(interceptor)
httpClient.addInterceptor(Interceptor { chain: Interceptor.Chain ->
val original: Request = chain.request()
val request: Request = original.newBuilder()
.header("Content-Type", "application/json")
.method(original.method, original.body)
.build()
chain.proceed(request)
})
val okHttpClient = httpClient.build()
val retrofit = Retrofit.Builder()
.baseUrl(MemberAPI.base_domain)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
Issues:
1. The request is not hitting my python flask server.
2. My app crashes whenever this code is run.
*Note: I have used Postman to test the localhost address, which is successful
I am trying to create an okHttp request in my kotlin android application.
I have implemented the needed dependencies in my build.gradle file:
implementation 'com.squareup.okhttp3:okhttp:3.10.0
edit: I included the Internet permission in the manifest file
<uses-permission android:name="android.permission.INTERNET" />
I have tried using my IP as part of the URL, along with a few different localhost links and have determined that the URL is not the issue.
If I am not mistaken, the app crash error occurs during build (), but I cannot wrap my mind around why.
Ideally, this code would hit the rest API and return data (printed as text)
on my login screen.
After a couple of days of researching and trying other request methods, I am unable to find a solution.
val mTextviewResult: TextView = findViewById(R.id.text_view_result)
//http client
var client = OkHttpClient()
val url = "http://localhost:5000/test"
val request = Request.Builder()
.url(url)
.build()
Log.d(request.toString(), ": I build Request")
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d(url, ": I fail")
e.printStackTrace()
}
#Throws(IOException::class)
override fun onResponse(call: Call, response: Response) {
if (response.isSuccessful()) {
Log.d(url, ": I success")
val myResponse = response.body()?.string()
this#LoginActivity.runOnUiThread(object : Runnable {
override fun run() {
mTextviewResult.setText(myResponse)
}
})
}
}
})
To access localhost you should use local IPv4 + server PORT for localhost.
How to get this IPv4:
https://www.whatismybrowser.com/detect/what-is-my-local-ip-address
KOTLIN async request:
private val client = OkHttpClient()
fun run() {
val request = Request.Builder()
.url("http://IPv4_FROM_THE_LINK_ABOVE:5000/test")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
}
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
for ((name, value) in response.headers) {
println("$name: $value")
}
println(response.body!!.string())
}
}
})
}
Install OkHttp: https://square.github.io/okhttp/
I found a youtube video on how to do a get url but I need to do a post to a REST api. I am unsure on how to do so.
Ive tried to look around on here but most of it is java.
fun fetchJson() {
println ("attempting to fetch JSON")
val url = "https://utgapi.shift4test.com/api/rest/v1/transactions/sale"
val request = Request.Builder().url(url).build()
val client = OkHttpClient()
client.newCall(request).enqueue(object: Callback {
override fun onResponse(call: Call?, response: Response?) {
val body = response?.body()?.string()
println(body)
println("try and get json api working there was an error")
}
override fun onFailure(call: Call, e: IOException) {
println("failed to execute request")
}
with the GET i just receive a error because i am not doing a POST request.
Found something here https://stackoverflow.com/a/29795501/5182150
Converting it to kotlin would be like
private val client = OkHttpClient();
fun run() throws Exception {
val formBody = FormEncodingBuilder()
.add("search", "Jurassic Park")
.build() as RequestBody;
val request = new Request.Builder()
.url("https://en.wikipedia.org/w/index.php")
.post(formBody)
.build();
val response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
This should be the gist. You can deal with nullable issues as the studio gives you warnings.
Another tip is You can use Retrofit too which works using OkHTTP for network calls. You can find more about retrofit here https://square.github.io/retrofit/ and a good tutorial here https://medium.com/#prakash_pun/retrofit-a-simple-android-tutorial-48437e4e5a23
If you are using OkHttp you can check to this code
fun POST(url: String, parameters: HashMap<String, String>, callback: Callback): Call {
val builder = FormBody.Builder()
val it = parameters.entries.iterator()
while (it.hasNext()) {
val pair = it.next() as Map.Entry<*, *>
builder.add(pair.key.toString(), pair.value.toString())
}
val formBody = builder.build()
val request = Request.Builder()
.url(url)
.post(formBody)
.build()
val call = client.newCall(request)
call.enqueue(callback)
return call
}
I'm trying to upload files to firebase storage from android app using url instead of SDK using Retrofit. This is my upload image method,
fun uploadImageToUrl() {
val url = "https://firebasestorage.googleapis.com/v0/b/xxxxxxx-xxxx.appspot.com/o/${bean.firebaseUid}/idProofs/${bean.documentTitle}.jpg/"
var client = OkHttpClient.Builder().build()
val retrofit = Retrofit.Builder()
.baseUrl(url).addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
var service = retrofit.create(UploadService::class.java)
var params = HashMap<String, RequestBody>()
var reqFile = RequestBody.create(MediaType.parse("image/*"), photoFile)
var header = "Bearer ${bean.firebaseToken}"
var body = MultipartBody.Part.createFormData("image", bean.documentTitle, reqFile)
var response = service.uploadDocument(header, body)
response.enqueue(object: Callback<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>?, response: Response<ResponseBody>?) {
Log.e("Upload Response", response!!.message())
}
override fun onFailure(call: Call<ResponseBody>?, t: Throwable?) {
Log.e("Upload Failed", t!!.localizedMessage)
}
})
}
This is the method in service interface.
interface UploadService {
#Multipart
#Headers("Accept: application/json")
#POST("/?alt=media")
fun uploadDocument(#Header("Authorization") header: String, #Part image: MultipartBody.Part): retrofit2.Call<ResponseBody>
}
But nothing is happening, no error messages, onResponse, onFailure methods not called, image not appearing.
My bad. The URL should be like this
https://firebasestorage.googleapis.com/v0/b/xxxxxxx-xxxx.appspot.com/o/${bean.firebaseUid}%2FidProofs%2F${bean.documentTitle}.jpg/
instead of this
https://firebasestorage.googleapis.com/v0/b/xxxxxxx-xxxx.appspot.com/o/${bean.firebaseUid}/idProofs/${bean.documentTitle}.jpg/
I don't know why, but it's working.