How to convert apache httpclient code to okhttp - android

I am using api with oauth2 in my application. This code is provided by the api developers, but it was written for java and, as I understand it, httpclient is not supported on android. Alternatively, I think okhttp can be used. Please help me to write similar code for okhttp. I'm not familiar with okhttp and may be stuck here for a long time
class DiagnosisClient(
userName: String,
password: String,
authServiceUrl: String,
language: String,
healthServiceUrl: String?
) {
var token: AccessToken? = null
private val language: String
private val healthServiceUrl: String?
private val httpclient: CloseableHttpClient
#Throws(Exception::class)
private fun LoadToken(username: String, password: String, url: String) {
val keySpec = SecretKeySpec(
password.toByteArray(),
"HmacMD5"
)
var computedHashString = ""
computedHashString = try {
val mac: Mac = Mac.getInstance("HmacMD5")
mac.init(keySpec)
val result: ByteArray = mac.doFinal(url.toByteArray())
val encoder = BASE64Encoder()
encoder.encode(result)
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
throw Exception("Can not create token (NoSuchAlgorithmException)")
} catch (e: InvalidKeyException) {
e.printStackTrace()
throw Exception("Can not create token (InvalidKeyException)")
}
val httpPost = HttpPost(url)
httpPost.setHeader("Authorization", "Bearer $username:$computedHashString")
token = try {
val response: CloseableHttpResponse = httpclient.execute(httpPost)
val objectMapper = ObjectMapper()
if (response.getStatusLine().getStatusCode() !== HttpStatus.SC_OK) {
RetrieveException(response, objectMapper)
}
val accessToken: AccessToken = objectMapper.readValue(
response.getEntity().getContent(),
AccessToken::class.java
)
accessToken
} catch (e: ClientProtocolException) {
e.printStackTrace()
throw Exception("Can not create token (ClientProtocolException)")
} catch (e: IOException) {
e.printStackTrace()
throw Exception("Can not create token (IOException)")
}
}
#Throws(Exception::class)
private fun RetrieveException(response: CloseableHttpResponse, objectMapper: ObjectMapper) {
val errorMessage: String = objectMapper.readValue(
response.getEntity().getContent(),
String::class.java
)
System.out.println(
"Resposne with status code: " + response.getStatusLine().getStatusCode()
.toString() + ", error message: " + errorMessage
)
throw Exception(errorMessage)
}
init {
httpclient = HttpClients.createDefault()
this.healthServiceUrl = healthServiceUrl
this.language = language
LoadToken(userName, password, authServiceUrl)
}
}
```

Related

Where i put decryption code for responce in retrofit andriod

I want to decrypt server data where can I decrypt it in android using retrofit
before using enc/dec I get this data from server
{
"success": true,
"secret": "NVARWBA4MAGSAW2F"
}
When I hit this API
#Headers("Content-Type: application/json")
#POST("user")
suspend fun addUser(#Body addUser: AddUser): Response<com.pryze.repository.model.User>
and after using enc/dec in response from server only I get encrypted text
'JAdS9hy168A2fG6FVTyzmFY739iawyk9qZ/yynRLtFTtE9nXxHyEas5ZrLzpl9IhpdgD27RpPBS5HsFHnVParg=='
and my app is crushed due to illegal response how can I solve this where I can put my dec code to first decrypt it then assign that to the response.
please try this code in your inspector class for Encryption and Decryption both.
override fun intercept(chain: Interceptor.Chain): Response {
if (!isInternetAvailable()){
throw NoInternetException("Make sure you have an active data connection")
}
try {
val aesUtil = AesUtil(keySize, iterationCount)
var request: Request = chain.request()
val buffer = Buffer()
request.body?.writeTo(buffer)
val strOldBody: String = buffer.readUtf8()
val encText = aesUtil.encrypt(salt,iv,passphrase,strOldBody)
val mediaType: MediaType? = "text/plain; charset=utf-8".toMediaTypeOrNull()
val strNewBody: String = encText
val body: RequestBody = RequestBody.create(mediaType, strNewBody)
request = request.newBuilder().addHeader("authorization", "Bearer " + t.getToken("JWT")).header("Content-Length", body.contentLength().toString()).method(request.method, body).build()
var req= chain.proceed(request)
var enc_data=""+req.body?.string().toString()
enc_data = aesUtil.decrypt(salt,iv,passphrase,enc_data)
return req.newBuilder().body(ResponseBody.create(req.body?.contentType(), enc_data)).build()
}
catch (e:ServiceConfigurationError){
}
catch (e: SSLHandshakeException){
throw NoInternetException("Request Time Out")
}
catch (e: ConnectException){
throw NoInternetException("Request Time Out")
}
catch (e: SocketTimeoutException){
throw NoInternetException("Make sure you have an active data connection")
}
catch (e:UnknownHostException){
throw NoInternetException("Make sure you have an active data connection")
}
catch (e: ErrnoException){
throw NoInternetException("Request Time Out")
}
throw NoInternetException("Request Time Out")
}

using gmail api getting exception no object DCH for MIME type multipart/mixed >> , nothing solved my issue

I'm trying to send email with attachment by using gmail api. I coppied and added some changes to my code and try to send it.
Although sending text email was successful, sending mail with attachment is failed. The exception is triggered after writing from email to buffer.
no object DCH for MIME type multipart/mixed
here is my code
fun sendMail(
c: Context,
ac: Account,
from: String,
tos: List<String>,
subject: String,
content: String,
vararg f: File
) {
val props = Properties()
val session = Session.getDefaultInstance(props, null)
var email = MimeMessage(session)
try {
email.setFrom(InternetAddress(from));
for (to in tos) {
email.addRecipient(
javax.mail.Message.RecipientType.TO,
InternetAddress(to)
);
}
email.setSubject(subject);
var mimeBodyPart = MimeBodyPart();
mimeBodyPart.setContent(content, "text/plain");
val multipart = MimeMultipart()
multipart.addBodyPart(mimeBodyPart);
for (file in f) {
mimeBodyPart = MimeBodyPart();
var source: DataSource = FileDataSource(file)
mimeBodyPart.dataHandler = DataHandler(source)
mimeBodyPart.fileName = file.name;
}
multipart.addBodyPart(mimeBodyPart);
email.setContent(multipart);
var message = createMessageWithEmail(email)
val gmailService = getService(c, ac)
val returnedMessage = gmailService?.users()?.messages()?.send("me", message)?.execute()
message.id = returnedMessage?.id
message.labelIds = returnedMessage?.labelIds
println("returnedMessage : $returnedMessage");
println("currentMessage : " + message.toPrettyString())
} catch (e: MessagingException) {
Log.e(TAG, "sendMail: $e")
} catch (e: IOException) {
Log.e(TAG, "sendMail: $e")
}
}
fun createMessageWithEmail(emailContent: MimeMessage): Message {
val message = Message()
try {
val buffer = ByteArrayOutputStream()
emailContent.writeTo(buffer)
val bytes = buffer.toByteArray()
val encodedEmail = encodeBase64URLSafeString(bytes)
message.raw = encodedEmail
} catch (e: MessagingException) {
Log.e(TAG, "createMessageWithEmail: $e")
} catch (e: IOException) {
Log.e(TAG, "createMessageWithEmail: $e")
}
return message
}
I have tried to add Thread.currentThread().setContextClassLoader(javax.mail.Message::class.java.getClassLoader())
but it didnt solved.
I'm so confused about it. How does not the code which is in the documentation work? I don't understand what I'm missing.
I'm getting file from internal storage. I don't think it is about it. Can you help me what I'm missing?
Thank you !

Huawei Mobile Services (HMS) exception: Token is invalid or expired when using ML kit Real-Time Translation on cloud?

exception: Token is invalid or expired.
What is this error? I have already set the api key. And what does this token represent?
val setting: MLRemoteTranslateSetting =
MLRemoteTranslateSetting.Factory()
.setSourceLangCode("en")
.setTargetLangCode("hu")
.create()
val mlRemoteTranslator: MLRemoteTranslator =
MLTranslatorFactory.getInstance().getRemoteTranslator(setting)
try {
val result = MLTranslateLanguage.syncGetCloudAllLanguages()
} catch (e: MLException) {
Log.e("ML exception", e.message.toString())
}
var output = ""
try {
output = mlRemoteTranslator.syncTranslate("SOURCE")
} catch (e: MLException) {
Log.e("ML exception", e.message.toString())
}
mlRemoteTranslator.stop()
I get this error here: val result = MLTranslateLanguage.syncGetCloudAllLanguages()
and here: output = mlRemoteTranslator.syncTranslate("SOURCE")
I set the api key like this: MLApplication.getInstance().apiKey = Utils.apiKey
object Utils {
private const val TAG = "Utils"
#JvmStatic
val apiKey: String?
get() {
// get apiKey from AppGallery Connect
val apiKey = "myApiKey"
// need encodeURI the apiKey
return try {
URLEncoder.encode(apiKey, "utf-8")
} catch (e: UnsupportedEncodingException) {
Log.e(TAG, "encode apikey error")
null
}
}}

Android: JSON object getString

I use this JSON https://api.github.com/users
I need to get string name, followers, following, and more. But on the program says "No value for name". I think I need to go to a specific user example: https://api.github.com/users/mojombo to getting that info, but I don't know-how.
And I using loopj library.
Here's My Code
private fun getDataGitDetail() {
progressBar.visibility = View.VISIBLE
val client = AsyncHttpClient()
client.addHeader("Authorization", "token 6fe9dff2e5e43d25eb3abe9ff508a750b972f725")
client.addHeader("User-Agent", "request")
val url = "https://api.github.com/users"
client.get(url, object : AsyncHttpResponseHandler() {
override fun onSuccess(
statusCode: Int,
headers: Array<Header>,
responseBody: ByteArray
) {
progressBar.visibility = View.INVISIBLE
val result = String(responseBody)
Log.d(TAG, result)
try {
val jsonArray = JSONArray(result)
for (i in 0 until jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(i)
val username: String? = jsonObject.getString("login")
val name: String? = jsonObject.getString("name")
val avatar: String? = jsonObject.getString("avatar_url")
val company: String? = jsonObject.getString("url")
val location: String? = jsonObject.getString("url")
val repository: Int = 0
val followers: Int = 0
val following: Int = 0
listData.add(
Data(
username,
name,
avatar,
company,
location,
repository,
followers,
following
)
)
}
showRecyclerList()
} catch (e: Exception) {
Toast.makeText(this#MainActivity, e.message, Toast.LENGTH_SHORT)
.show()
e.printStackTrace()
}
}
override fun onFailure(
statusCode: Int,
headers: Array<Header>,
responseBody: ByteArray,
error: Throwable
) {
progressBar.visibility = View.INVISIBLE
val errorMessage = when (statusCode) {
401 -> "$statusCode : Bad Request"
403 -> "$statusCode : Forbidden"
404 -> "$statusCode : Not Found"
else -> "$statusCode : ${error.message}"
}
Toast.makeText(this#MainActivity, errorMessage, Toast.LENGTH_LONG)
.show()
}
})
}
The current response you are getting does not contain a key name in the JSONObject.
If you want the Name of all the users you will have to go to each users endpoint in the api. You'll need to make another request inside your for loop that gets datafrom an endpoint like https://api.github.com/users/mojombo
val jsonArray = JSONArray(result)
for (i in 0 until jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(i)
val username: String? = jsonObject.getString("login")
//Make the request here using "https://api.github.com/users/" + login
You can then choose to get the rest of the data from either the first response or the 2nd one as both contain that information.
I hope this helps.
No need for a JSON array, cz API https://api.github.com/users/mojombo is JSON Object.
Example:
client.get(url, object : AsyncHttpResponseHandler() {
override fun onSuccess(statusCode: Int, headers: Array<Header>, responseBody: ByteArray) {
try {
//parsing json
val result = String(responseBody)
val responseObject = JSONObject(result)
textView2.text = responseObject.getString("login")
textView3.text = responseObject.getString("name")
textView9.text = responseObject.getString("location")
desc.text = responseObject.getString("company")
view?.let { Glide.with(it).load(responseObject.getString("avatar_url")).into(imageView2) }
} catch (e: Exception) {
Log.d("Exception", e.message.toString())
}
}
}

I can't find the files I uploaded to Google Drive

I'm trying to upload a file to Google Drive using Google Drive REST API v3. After the upload process is completed, it returns a status code of 200 (successful). But I can't find the files in my Google Drive. Please tell me what am I doing wrong? I will really appreciate if you provide a proper illustration or better still code snippet while helping me with this problem of mine. I am really anticipating your answers.
I have tried following the documentation but I am still getting the same error. I have searched everywhere online and stackoverflow, but none seems to provide the solution to my problem.
here is the code
private val AUTHORIZATION_PARAM = "Authorization"
private val BEARER_VAL = "Bearer "
private val CONTENT_TYPE_PARAM = "Content-Type: "
private val LINE_FEED = "\r\n"
private val APP_FOLDER_ID = "appDataFolder"
fun connectAndStartOperation() {
if (mAuthCode == null) {
signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestProfile()
.requestScopes(Scope(Scopes.DRIVE_APPFOLDER))
.requestIdToken(resources.getString(R.string.gdrive_clientId))
.requestServerAuthCode(resources.getString(R.string.gdrive_clientId))
.build()
mGoogleSignInClient = GoogleSignIn.getClient(this, signInOptions!!)
startActivityForResult(mGoogleSignInClient?.signInIntent, CLOUD_STORAGE)
Log.i("mAuthCode", "false")
} else {
Log.i("mAuthCode", "true")
writeDbToDrive()
mNextGoogleApiOperation = INVALID;
}
}
fun disconnect() {
mGoogleSignInClient?.signOut()
mActivity = null
mNextGoogleApiOperation = INVALID
mAuthCode = null
mAccessToken = null
mTokenExpired = 0
}
override fun onDestroy() {
disconnect()
super.onDestroy()
}
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == CLOUD_STORAGE) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
.addOnSuccessListener(this)
.addOnFailureListener(this)
}
}
override fun onSuccess(googleSignInAccount: GoogleSignInAccount?) {
Log.i("mAuthCode", "Success")
val scope = "oauth2:https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/userinfo.profile"
idTokenString = googleSignInAccount?.idToken
mAuthCode = googleSignInAccount?.serverAuthCode
mGoogleSignInAccount = googleSignInAccount
doAsync {
try {
mAccessToken = GoogleAuthUtil.getToken(this#SettingsActivity, mGoogleSignInAccount?.account, scope)
} catch (e: Exception) {
Log.i("Error AccessToken", "${e.message}")
e.printStackTrace()
}
uiThread {
Log.i("AccessTokenMy", "$mAccessToken")
}
}
}
override fun onFailure(p0: java.lang.Exception) {
Log.i("mAuthCode", "Failed")
p0.printStackTrace()
}
private fun writeDbToDrive() {
var conn: HttpURLConnection? = null
var os: OutputStream? = null
val accessToken = requestAccessToken(mGoogleSignInAccount!!)
if (accessToken == null)
return
try {
val boundary = "pb" + System.currentTimeMillis()
val url = URL("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart")
conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "POST"
conn.useCaches = false
conn.doOutput = true
conn.doInput = true
conn.connectTimeout = 5000
conn.setRequestProperty(AUTHORIZATION_PARAM, BEARER_VAL + accessToken!!)
conn.setRequestProperty("Content-Type", "multipart/related; boundary=$boundary")
Log.i("Action", "Parameter set for server")
/////// Prepare data
//val timestamp = SimpleDateFormat("yyyy-MM-dd_HH:mm:ss", Locale.getDefault()).format(Date())
// Prepare file metadata (Change your backup file name here)
val b = StringBuilder()
b.append('{')
.append("\"name\":\"").append(exportedFileName).append('\"')
.append(',')
.append("\"mimeType\":").append("\"text\\/csv\"")
.append(',') //"\"application\\/vnd.google-apps.unknown\""
.append("\"parents\":").append("[\"").append(APP_FOLDER_ID).append("\"]")
.append('}')
val metadata = b.toString()
val data = readFile(File(filePath))
/////// Calculate body length
var bodyLength = 0
// MetaData part
b.setLength(0)
b.append("--").append(boundary).append(LINE_FEED)
b.append(CONTENT_TYPE_PARAM).append("application/json; charset=UTF-8")
.append(LINE_FEED)
b.append(LINE_FEED)
b.append(metadata).append(LINE_FEED)
b.append(LINE_FEED)
b.append("--").append(boundary).append(LINE_FEED)
b.append(CONTENT_TYPE_PARAM).append("text/csv").append(LINE_FEED)
b.append(LINE_FEED)
val beforeFilePart = b.toString().toByteArray(charset("UTF_8"))
bodyLength += beforeFilePart.size
bodyLength += data.size // File
b.setLength(0)
b.append(LINE_FEED)
b.append("--").append(boundary).append("--")
val afterFilePart = b.toString().toByteArray(charset("UTF_8"))
bodyLength += afterFilePart.size
conn.setRequestProperty("Content-Length", bodyLength.toString())
//if (BuildConfig.DEBUG_MODE) DebugHelper.log("LENGTH", bodyLength)
/////// Write to socket
os = conn.outputStream
try {
os!!.write(beforeFilePart)
os!!.write(data)
os!!.write(afterFilePart)
os!!.flush()
} catch (e: Exception) {
e.printStackTrace()
}
val msg = conn.responseMessage
val code = conn.responseCode
if (code == 200) {
Log.i("writeDbToDrive", "Exported Successfully: $code $msg")
} else {
Log.i("writeDbToDrive", "Error: $code $msg")
}
} catch (e: Exception) {
e.printStackTrace()
Log.i("writeDbToDrive", e.message!!)
} finally {
if (os != null) {
try {
os!!.close()
} catch (e: IOException) {
}
}
conn?.disconnect()
}
}
#Throws(IOException::class)
private fun readFile(file: File): ByteArray {
val f = RandomAccessFile(file, "r")
try {
val longlength = f.length()
val length = longlength.toInt()
if (length.toLong() != longlength)
throw IOException("File size >= 10 Mb")
val data = ByteArray(length)
f.readFully(data)
return data
} finally {
f.close()
}
}
private fun requestAccessToken(mGoogleSignInAccount: GoogleSignInAccount): String? {
val scope = "oauth2:https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/userinfo.profile"
doAsync {
try {
mAccessToken = GoogleAuthUtil.getToken(this#SettingsActivity, mGoogleSignInAccount?.account, scope)
} catch (e: Exception) {
Log.i("Error AccessToken", "${e.message}")
e.printStackTrace()
}
uiThread {
Log.i("AccessTokenMy", "$mAccessToken")
}
}
return mAccessToken
}
After reading through this Files: create Documentation, I have finally fixed the problem. Unknown to me is that the files where being saved in the AppData folder created by my app. The AppData folder is hidden which can only be accessible by and through my app. For me to be able to save the file to My Drive folder, I removed the part of the metadata
` .append(',')
.append("\"parents\":").append("[\"").append(APP_FOLDER_ID).append("\"]")`
So the metadata part is now like this
val b = StringBuilder()
b.append('{')
.append("\"name\":\"").append(exportedFileName).append('\"')
.append(',')
.append("\"mimeType\":").append("\"text\\/csv\"")
.append('}')
val metadata = b.toString()
Every other thing remains the same

Categories

Resources