milosev.com
  • Home
    • List all categories
    • Sitemap
  • Downloads
    • WebSphere
    • Hitachi902
    • Hospital
    • Kryptonite
    • OCR
    • APK
  • About me
    • Gallery
      • Italy2022
      • Côte d'Azur 2024
    • Curriculum vitae
      • Resume
      • Lebenslauf
    • Social networks
      • Facebook
      • Twitter
      • LinkedIn
      • Xing
      • GitHub
      • Google Maps
      • Sports tracker
    • Adventures planning
  1. You are here:  
  2. Home

Example of making HTTP Post and Get request from Android Kotlin to Web Api .NET Core

Details
Written by: Stanko Milosev
Category: Android
Published: 26 March 2023
Last Updated: 26 March 2023
Hits: 1169
  • core
  • kotlin
This example works only in Android Studio emulator and with accepting all certificates, and it is made with Retrofit library.

First example of Web Api in .NET Core:

using Microsoft.AspNetCore.Mvc;

namespace WebApi.Controllers;

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    [HttpGet]
    public string Get()
    {
        return "test";
    }

    [HttpGet("{id}")]
    public string Get(int id)
    {
        return "value";
    }

    [HttpPost]
    public string Post([FromBody] string value)
    {
        return $"Sent: {value}";
    }
}
Now example in Kotlin.

In \app\src\main\AndroidManifest.xml I have added internet permissions:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

In \app\src\main\res\layout\activity_main.xml I have added the button:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button"
        android:onClick="postHttp"
        tools:layout_editor_absoluteX="166dp"
        tools:layout_editor_absoluteY="441dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
        />

</androidx.constraintlayout.widget.ConstraintLayout>
In \app\build.gradle I have added

implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.okhttp3:okhttp:4.9.0"
implementation 'com.squareup.retrofit2:converter-scalars:2.1.0'
Code to trust all certificates taken from here.

val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
    override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
        Log.i(MainActivity::class.simpleName, "checkClientTrusted")
    }

    override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
        Log.i(MainActivity::class.simpleName, "checkServerTrusted")
    }

    override fun getAcceptedIssuers() = arrayOf<X509Certificate>()
})
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, java.security.SecureRandom())

// Create an ssl socket factory with our all-trusting manager
val sslSocketFactory = sslContext.socketFactory

// connect to server
val client = OkHttpClient.Builder().sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager).hostnameVerifier{ _, _ -> true }.build()
Next building Retrofit:
val retro = Retrofit.Builder()
    .baseUrl("https://10.0.2.2:7037")
    .client(client)
    .addConverterFactory(ScalarsConverterFactory.create())
    .build()

Here notice baseUrl: https://10.0.2.2:7037 - 10.0.2.2 is localhost for Android Studio emulator

Add WebApiService interface:

interface WebApiService {
    @Headers("Content-Type: text/json")
    @POST("/api/Values")
    fun postMethod(@Body value: String): Call<String>
}
Create request:
val service = retro.create(WebApiService::class.java)
val webApiRequest = service.postMethod("\"test\"")
Here notice "\"test\"" since I am trying to send a raw string, otherwise would be rejected.

Last but not least, onResponse and onFailure:

val alertDialogBuilder = AlertDialog.Builder(this@MainActivity)

webApiRequest.enqueue(object : Callback<String> {
    override fun onResponse(call: Call<String>, response: Response<String>) {

        if (!response.isSuccessful) {
            alertDialogBuilder.setMessage(response.errorBody()!!.charStream().readText())
                .setCancelable(false)
                .setNeutralButton("OK", DialogInterface.OnClickListener { dialog, _ ->
                    dialog.dismiss()
                })

            val alert = alertDialogBuilder.create()
            alert.setTitle("Error")
            alert.show()
        }
        else {
            alertDialogBuilder.setMessage("Response: ${response.body().toString()}")
                .setCancelable(false)
                .setNeutralButton("OK", DialogInterface.OnClickListener { dialog, _ ->
                    dialog.dismiss()
                })

            val alert = alertDialogBuilder.create()
            alert.setTitle("Error")
            alert.show()
        }
    }

    override fun onFailure(call: Call<String>, t: Throwable) {
        alertDialogBuilder.setMessage(t.message)
            .setCancelable(false)
            .setNeutralButton("OK", DialogInterface.OnClickListener {
                    dialog, _ -> dialog.dismiss()
            })

        val alert = alertDialogBuilder.create()
        alert.setTitle("Error")
        alert.show()
    }

})
.NET solution download from here and Android source code download from here here.

Creating never ending application v2

Details
Written by: Stanko Milosev
Category: Android
Published: 05 June 2022
Last Updated: 06 June 2022
Hits: 1348
  • kotlin
Here I gave one example of never ending application, which, unfortunately, after latest Huwaei update on my phone is not working. I gonna leave that article as is, and here I will show another possible example using mix of my original article and this and this answer.

I have added Service and BroadcastReceiver, in Manifest I have added permissions:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

Then in the MainActivity I have added the method "checkOptimization" and "openBatteryOptimization ":

@SuppressLint("NewApi", "BatteryLife")
private fun checkOptimization(context: Context) {
	val packageName = applicationContext.packageName
	val pm = applicationContext.getSystemService(POWER_SERVICE) as PowerManager
	if (!pm.isIgnoringBatteryOptimizations(packageName)) {
		val intent = Intent()
		intent.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
		intent.data = Uri.parse("package:" + context.packageName)
		context.startActivity(intent)
	}
}

fun openBatteryOptimization(context: Context) {
	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
		val intent = Intent()
		intent.action = Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
		context.startActivity(intent)
	} else {
		//Timber.d("Battery optimization not necessary")
	}
}
Both methods "checkOptimization" and "openBatteryOptimization" I have added to "onCreate" of MainActivity. For
Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
In import list I have added:
import android.provider.Settings
import android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS

In Gradle I added:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"
Service and receiver first I have copied from original article, then I have added following methods:
private val wakeLock: PowerManager.WakeLock by lazy {
	(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
		newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "neverEndingApplication:ServiceWakelock")
	}
}

private fun acquireWakelock() {
	try {
		wakeLock.let {
			wakeLock.setReferenceCounted(false)
			if (!wakeLock.isHeld) {
				wakeLock.acquire()
			}
		}
	} catch (e: RuntimeException) {
	}
}

private fun releaseWakelock() {
	try {
		wakeLock.let {
			if (it.isHeld) {
				it.release()
			}
		}
	} catch (e: RuntimeException) {
	}
}
Still in Service I have added acquireWakelock in onCreate:
override fun onCreate() {
	super.onCreate()
	acquireWakelock()
}
releaseWakelock() I have added when I want to stop the app:
if (intent?.action.equals("stopForeground")) {
	job?.cancel()
	releaseWakelock()
	stopForeground(true)
	stopSelfResult(startId)
}
MainActivity I also copied from my original article.

Example download from here.

Disable / Enable manifest broadcast receiver

Details
Written by: Stanko Milosev
Category: Android
Published: 17 May 2022
Last Updated: 27 May 2022
Hits: 1437
  • kotlin
To enable:
val component = ComponentName(this, MyBroadcastReceiver::class.java)
getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Disable:
val component = ComponentName(this, MyBroadcastReceiver::class.java)
getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED , PackageManager.DONT_KILL_APP);

Creating never ending application

Details
Written by: Stanko Milosev
Category: Android
Published: 17 May 2022
Last Updated: 01 November 2025
Hits: 1867
  • kotlin
UPDATE: 2025-10-26 LocalBroadcastManager is deprecated

Please refer to this article for BroadcastReceiver in a separate class

While I was trying to create my tracking application in Android, I have noticed that application is getting killed, from time to time. After some research I have found this web site, which it seems that solved my problem, but please note that I am testing only on one device, since I am doing it for my self as a hobby.

First I have started empty activity.

Second I have added File -> New -> Service -> Service

Last one I have added File -> New -> Other -> Broadcast Receiver

In the manifest I added FOREGROUND_SERVICE permission:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
and android:process=":MyService". My Manifest looks like:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.milosev.myapplication">

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication">
        <receiver
            android:name=".MyBroadcastReceiver"
            android:enabled="true"
            android:exported="true" />

        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"
            android:process=":MyService" />

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
In Gradle I added:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"
So my gradle looks like:
plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.milosev.myapplication"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.6.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"
}
MyBroadcastReceiver.kt looks like:
package com.milosev.myapplication

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.milosev.getgpslocation.MyService

class MyBroadcastReceiver : BroadcastReceiver() {

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onReceive(context: Context, intent: Intent) {
        when (intent?.action) {
            "MyAction" -> {
                val myIntent = Intent(context, MainActivity::class.java).setAction("MyAction")
                LocalBroadcastManager.getInstance(context).sendBroadcast(myIntent)
            }
            "Restart" -> {
                val intent = Intent(context, MyService::class.java)
                intent.action = "startForeground"
                context.startForegroundService(intent)
            }
        }
    }
}
MyService.kt looks like:
package com.milosev.getgpslocation

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.os.CountDownTimer
import android.os.IBinder
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import kotlinx.coroutines.*

class MyService : Service(),CoroutineScope by MainScope() {

    private var job: Job? = null

    override fun onBind(intent: Intent): IBinder {
        TODO("Return the communication channel to the service.")
    }

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        when (intent?.action) {
            "startForeground" -> {

                val channelId = createNotificationChannel("my_service", "My Background Service")
                val notificationBuilder = NotificationCompat.Builder(this, channelId)
                val notification = notificationBuilder.setOngoing(true)
                    .setContentTitle("test")
                    .setContentText("test")
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setPriority(1)
                    .setCategory(Notification.CATEGORY_SERVICE)
                    .build()

                startForeground(101, notification)
                val context = this

                job = launch {
                    while(true) {
                        val myIntent = Intent(context, MyBroadcastReceiver::class.java).setAction("MyAction")
                        sendBroadcast(myIntent);
                        delay(1_000)
                    }
                }
            }
        }
        if (intent?.action.equals("stopForeground")) {
            job?.cancel()
            stopForeground(true)
            stopSelfResult(startId)
        }
        return START_STICKY;
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel(channelId: String, channelName: String): String {
        val chan = NotificationChannel(
            channelId,
            channelName, NotificationManager.IMPORTANCE_LOW
        )
        chan.lightColor = Color.RED
        chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
        val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        service.createNotificationChannel(chan)
        return channelId
    }

    override fun onDestroy() {
        super.onDestroy()
        val myIntent = Intent(this, MyBroadcastReceiver::class.java).setAction("Restart")
        sendBroadcast(myIntent);
    }

    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        val myIntent = Intent(this, MyBroadcastReceiver::class.java).setAction("Restart")
        sendBroadcast(myIntent);
    }
}
POI:
override fun onDestroy() {
	super.onDestroy()
	val myIntent = Intent(this, MyBroadcastReceiver::class.java).setAction("Restart")
	sendBroadcast(myIntent);
}

override fun onTaskRemoved(rootIntent: Intent?) {
	super.onTaskRemoved(rootIntent)
	val myIntent = Intent(this, MyBroadcastReceiver::class.java).setAction("Restart")
	sendBroadcast(myIntent);
}
In main activity:
@RequiresApi(Build.VERSION_CODES.O)
override fun onResume() {
	super.onResume()
	LocalBroadcastManager.getInstance(this)
		.registerReceiver(broadCastReceiver, IntentFilter("MyAction"))

	val intent = Intent(this, MyService::class.java)
	intent.action = "startForeground"
	startForegroundService(intent)
}
Notice that there is a problem with onResume because it will start the service immediately.

Edit: 2022-06-05: Unfortunately after latest update of Huawei my app is again getting killed. Here you can find informations about this issuse.

  1. Send broadcast from separate service and update UI
  2. android:process=":MyService"
  3. Few more examples of broadcast receiver declared in manifest
  4. SharedPreferences

Subcategories

C#

Azure

ASP.NET

JavaScript

Software Development Philosophy

MS SQL

IBM WebSphere MQ

MySQL

Joomla

Delphi

PHP

Windows

Life

Lazarus

Downloads

Android

CSS

Chrome

HTML

Linux

Eclipse

Page 143 of 165

  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147