//check if permission to make a call has been granted
if (ContextCompact.checkSelfPermission(context!!, android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
// i permission has not been granted request it (opens OS popup, no listener aviable)
ActivityCompat.requestPermissions(context!!, arrrayOf(android.Manifest.permission.CALL_PHONE), requestCode) //request code neeeds to be specific for the permission
} else {
call() //if permission has been already given
}
}
@SuppressLint("MissingPermission") // suppress warnig of unhandled permission (handled in checkCallPermission)
fun call() {
val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel: <phonenumber>"))
startActivity(intent)
}
```
## Lists (with RecyclerView)
A [LayoutManager][1] is responsible for measuring and positioning item views within a `RecyclerView` as well as determining the policy for when to recycle item views that are no longer visible to the user.
By changing the `LayoutManager` a `RecyclerView` can be used to implement a standard vertically *scrolling list*, a *uniform grid*, *staggered grids*, *horizontally scrolling collections* and more.
Several stock layout managers are provided for general use.
[Adapters][2] provide a binding from an app-specific data set to views that are displayed within a `RecyclerView`.
Subsequnt requests sould be delayed to avoid allowing the user to make too frequent requests.
```kotlin
private lateinit var queue: RequestQueue
override fun onCreate(savedInstanceState: Bundle?){
queue = Volley.newRequestQueue(context)
}
// response is a String
private fun simpleRequest() {
var url = "www.website.domain"
var stringRequest = StringRequest(Request.Method.GET, url, Response.Listener<String> {
Log.d()
},
Response.ErrorListener{
Log.e()
})
stringRequest.TAG = "TAG" // assign a tag to the request
queue.add(stringRequest) // add request to the queue
}
// response is JSON Object
private fun getJsonObjectRequest(){
// GET -> jsonRequest = null
// POST -> jsonRequest = JsonObject
var stringRequest = JsonObjectRequest(Request.Method.GET, url, jsonRequest, Response.Listener<String> {
Log.d()
// read end use JSON
},
Response.ErrorListener{
Log.e()
})
queue.add(stringRequest) // add request to the queue
}
// response is array of JSON objects
private fun getJSONArrayRequest(){
// GET -> jsonRequest = null
// POST -> jsonRequest = JsonObject
var stringRequest = JsonArrayRequest(Request.Method.GET, url, jsonRequest, Response.Listener<String> {
Log.d()
// read end use JSON
},
Response.ErrorListener{
Log.e()
})
queue.add(stringRequest) // add request to the queue
}
override fun onStop() {
super.onStop()
queue?.cancellAll("TAG") // delete all request with a particular tag when the activity is closed (avoid crash)
}
```
### Parse JSON Request
```kotlin
Response.Litener { response ->
var value = response.getSting("key")
}
```
## Data Persistance
### Singleton
Object instantiated during app init and is destroid only on app closing. It can be used for data persistance since is not affected by the destruction of an activity.
```kotlin
// Context: Interface to global information about an application environment.
class Singleton consturctor(context: Context) {
companion object {
@Volatile
private var INSTANCE: Singleton? = null
// syncronized makes sure that all instances of the singleton are actually the only existing one
fun getInstance(context: Contecxt) = INSTANCE ?: syncronized(this) {
-`getSharedPreferences()` — Use this if you need multiple shared preference files identified by name, which you specify with the first parameter. You can call this from any Context in your app.
-`getPreferences()` — Use this from an Activity if you need to use only one shared preference file for the activity. Because this retrieves a default shared preference file that belongs to the activity, you don't need to supply a name.
```kotlin
val sharedPref = activity?.getSharedPreferences( getString(R.string.preference_file_key), Context.MODE_PRIVATE )
val sharedPref = activity?.getPreferences(Context.MODE_PRIVATE)
```
**Write to shared preferences**:
To write to a shared preferences file, create a `SharedPreferences.Editor` by calling `edit()` on your SharedPreferences.
Pass the keys and values to write with methods such as `putInt()` and `putString()`. Then call `apply()` or `commit()` to save the changes.
```kotlin
val sharedPref = activity?.getPreferences(Context.MODE_PRIVATE) ?: return
with (sharedPref.edit()) {
putInt(getString(R.string.key), value)
commit() // or apply()
}
```
`apply()` changes the in-memory `SharedPreferences` object immediately but writes the updates to disk *asynchronously*.
Alternatively, use `commit()` to write the data to disk *synchronously*. But because *commit()* is synchronous, avoid calling it from your main thread because it could pause the UI rendering.
**Read from shared preferences**:
To retrieve values from a shared preferences file, call methods such as getInt() and getString(), providing the key for the wanted value, and optionally a default value to return if the key isn't present.
```kotlin
val sharedPref = activity?.getPreferences(Context.MODE_PRIVATE) ?: return
val defaultValue = resources.getInteger(R.integer.default_value_key)
val value = sharedPref.getInt(getString(R.string.key), defaultValue)