Upload of pre-existing files

This commit is contained in:
Marcello Lamonaca 2021-01-31 11:05:37 +01:00
commit 4c21152830
150 changed files with 730703 additions and 0 deletions

437
Android/Activity.kt.md Normal file
View file

@ -0,0 +1,437 @@
# Android App Activity.kt
## Logging
```kotlin
Log.i("tag", "logValue") //info log
Log.d("tag", "logValue") //debug log
Log.w("tag", "logValue") //warning log
Log.e("tag", "logValue") //error log
Log.c("tag", "logValue") //critical log
```
## Activity Life Cycle
![Life Cycle](https://developer.android.com/images/activity_lifecycle.png)
```kotlin
package com.its.<appname>
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
//entry point of the activity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.<activity_xml>)
}
override fun onStart() {
}
override fun onResume() {
}
override fun onPause() {
}
override fun onStop() {
}
override fun onRestart() {
}
override fun onDestroy() {
}
}
```
### Passing data between activities
In *lauching* activity:
```kotlin
private fun openActivity() {
//target to open Intent(opener, opened)
val intent = Intent(this, Activity::class.java)
//pass data to lauched activity
intent.putExtra("identifier", value)
startActivity(intent) //launch another activity
}
```
In *launched* activity:
```kotlin
val identifier = intent.get<Type>Extra("identifier")
```
## Hooks
### Resources Hooks
```kotlin
R.<resourceType>.<resourceName> //access to reource
ContextCompat.getColor(this, colorResource) //extract color from resources
getString(stringResource) //extract string from resources
```
### XML hooks
Changes in xml made in kotlin are applied after the app is drawn thus overwriting instructions in xml.
In `activity.xml`:
```xml
<View
android:id="@+id/<id>"/>
```
in `Activity.kt`:
```kotlin
var element = findViewById(R.id.<id>) //old method
<id>.poperty = value //access and modify view contents
```
## Activity Components
### Snackbar
Componed derived from material design. If using old API material design dependency must be set in gradle.
In `build.gradle (Module:app)`:
```gradle
dependencies {
implementation 'com.google.android.material:material:<sem_ver>'
}
```
In `Activity.kt`:
```kotlin
import com.google.android.material.snackbar.Snackbar
Snackbar
.make(activityID, message, Snackbar.TIME_ALIVE) //create snackbar
.setAction("Button Name", { action }) //add button to snackbar
.show()
```
## Opening External Content
### Opening URLs
```kotlin
val url = "https://www.google.com"
val intent = Intent(Intent.ACTION_VIEW)
intent.setData(Uri.parse(url))
startActivity(intent)
```
### Sharing Content
```kotlin
val intent = Intent(Intent.ACTION_SEND)
intent.setType("text/plain") //specifying shared content type
intent.putExtra(Intent.EXTRA_MAIL, "mail@address") //open mail client and precompile field if share w/ mail
intent.putExtra(Intent.EXTRA_SUBJECT, "subject")
intent.putExtra(Intent.EXTRA_TEXT, "text") //necessary since type is text
startActivity(Initent.startChooser(intent, "chooser title")) //let user choose the share app
```
### App Google Maps
[Documentation](https://developers.google.com/maps/documentation/urls/android-intents)
```kotlin
val uri = Uri.parse("geo: <coordinates>")
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.setPackage("com.google.android.apps.maps") //app to be opened
startActivity(intent)
```
### Make a call (wait for user)
Preset phone number for the call, user needs to press call button to initiate dialing.
```kotlin
fun call() {
val intent = Intent(Intent.ACTION_DIAL)
intent.setData(Uri.parse("tel: <phone number>"))
startActivity(intent)
}
```
### Make a call (directly)
In `AndroidManifest.xml`:
```xml
<uses-permission android:name="android.permission.CALL_PHONE" />
```
```kotlin
//https://developer.android.com/training/permissions/requesting
//intercept OS response to permission popup
override fun onRequestPermissionResult(requestCode: Int, permissins: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
fun checkCallPermission() {
//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: <phone number>"))
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`.
[1]:https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView.LayoutManager
[2]:https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView.Adapter
```kotlin
var array: ArrayList<T>? = null //create ArrayList of elements to be displayed
var adapter: RecyclerViewItemAdapter? = null //create adapter to draw the list in the Activity
array.add(item) //add item to ArrayList
// create LayoutManager for the recyclerView
val layoutManager = <ViewGroup>LayoutManager(context, <ViewGroup>LayoutManager.VERTICAL, reverseLayout: Bool)
recycleView.LayoutManager = layoutManager // assign LayoutManager for the recyclerView
// handle adapter var containing null value
if (array != null) {
adapter = RecyclerViewItemAdapter(array!!) // valorize adapter with a adaper object
recyclerView.adapter = adapter // assing adapter to the recyclerView
}
// add or remom item
// tell the adapter that something is changed
adapter?.notifyDataSetChanged()
```
## WebView
[WebView Docs](https://developerandroid.com/reference/android/webkit/WebView)
```kotlin
webView.webViewClient = object : WebViewClient() {
// avoid openiing browsed by default, open webview instead
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
view?.loadUrl(url) // handle every url
return true
}
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
// stay in WebView until website changes
if (Uri.parse(url).host == "www.website.domain") {
return false
}
Intent(Intent.ACTION_VIEW, Uri.parse(url).apply){
startActivity(this) // open br br owser/app when the website changes to external URL
}
return true
}
webView.settings.javaScriptEnabled = true // enable javascript
webView.addJavaScriptInterface(webAppInterface(this, "Android")) // create bridge between js on website an app
// if in webView use android back butto to go to previous webpage (if possible)
override fun onKeyDown(keyCode: Int, event: KeyEvent?) :Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && webVew,canGoBack()) { // if previous url exists & back button pressed
webView.goBack() // go to previous URL
return true
}
}
}
```
## Web Requests (Using Volley)
[Volley Docs](https://developer.android.com/training/volley)
### Import & Permissions
Import in `build.gradle`:
```kotlin
implementation 'com.android.volley:volley:1.1.1'
```
Perrmissions in `AndroidManifest.xml`:
```xml
<uses-permission android:name="android.permission.INTERNET" />
```
### Make the request
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) {
INSTANCE ?: Singleton(context).also {
INSTANCE = it
}
}
}
}
```
### SharedPreferences
[SharedPreferences Docs](https://developer.android.com/training/data-storage/shared-preferences)
**Get a handle to shared preferences**:
- `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)
```

86
Android/Adapter.kt.md Normal file
View file

@ -0,0 +1,86 @@
# RecycleView Cell Adapter
[Adapters][1] provide a binding from an app-specific data set to views that are displayed within a `RecyclerView`.
[1]:https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView.Adapter
```kotlin
package <package>
import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class RecipeAdapter : RecyclerView.Adapter<RecipeAdapter.ViewHolder> {
private var mDataset: ArrayList<Recipe> // RecyclerView data
class ViewHolder : RecyclerView.ViewHolder {
var viewGroup: ViewGroup? = null
constructor(v: ViewGroup?) : super(v!!) {
viewGroup = v
}
}
//adapter contructor, takes list of data
constructor(myDataset: ArrayList<Recipe>/*, mContext: Context?*/){
mDataset = myDataset
//mContenxt = mContext
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v : ViewGroup = LayoutInflater.from(parent.context).inflate(R.layout.view_recipe_item, parent, false) as ViewGroup
val vh = ViewHolder(v)
return vh
}
override fun getItemCount(): Int {
return mDataset.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val mItem : Recipe = mDataset.get(position)
val titleText = holder.viewGroup?.findViewById<TextView>(R.id.titleText)
titleText?.text = mItem.title
Log.d("Adapter","Title: "+mItem.title)
val deleteButton = holder.viewGroup!!.findViewById<Button>(R.id.deleteButton)
deleteButton.setOnClickListener { removeItem(position) }
//Click
holder.viewGroup?.setOnClickListener {
mListener?.select(position)
}
}
private fun removeItem(position: Int) {
mDataset.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, mDataset.size)
}
/*
* Callback
* */
private var mListener: AdapterCallback? = null
interface AdapterCallback {
fun select(position: Int)
}
fun setOnCallback(mItemClickListener: AdapterCallback) {
this.mListener = mItemClickListener
}
}
```

9
Android/Firebase.md Normal file
View file

@ -0,0 +1,9 @@
# [Firebase](https://firebase.google.com/) notes
> A comprehensive app development platform
[Firebase Docs](https://firebase.google.com/docs)
**Warning**: Google Analitycs can cause conflicts with the GDPR if user data is used in the app.
To link Firebase with the app it's necessary to download `google-services.json`.

154
Android/Fragment.md Normal file
View file

@ -0,0 +1,154 @@
# Fragments & FragmentActivity
[Documentation](https://developer.android.com/guide/components/fragments)
A **Fragment** represents a behavior or a portion of user interface in a `FragmentActivity`. It's possible to combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities.
Think of a fragment as a *modular section of an activity*, which has its *own* lifecycle, receives its *own* input events, and which you can add or remove while the activity is running (sort of like a "sub activity" that you can reuse in different activities).
![Fragment](https://developer.android.com/images/fundamentals/fragments.png)
A fragment must always be hosted in an activity and the fragment's lifecycle is *directly affected* by the host activity's lifecycle.
![Fragment Lifecycle](https://developer.android.com/images/fragment_lifecycle.png)
## Minimal Fragment Functions
Usually, you should implement at least the following lifecycle methods:
`onCreate()`
The system calls this when creating the fragment. Within your implementation, you should initialize essential components of the fragment that you want to retain when the fragment is paused or stopped, then resumed.
`onCreateView()`
The system calls this when it's time for the fragment to draw its user interface for the first time. To draw a UI for your fragment, you must return a View from this method that is the root of your fragment's layout. You can return null if the fragment does not provide a UI.
`onPause()`
The system calls this method as the first indication that the user is leaving the fragment (though it doesn't always mean the fragment is being destroyed). This is usually where you should commit any changes that should be persisted beyond the current user session (because the user might not come back).
## Fragment Subclasses
`DialogFragment`
Displays a floating dialog. Using this class to create a dialog is a good alternative to using the dialog helper methods in the Activity class, because you can incorporate a fragment dialog into the back stack of fragments managed by the activity, allowing the user to return to a dismissed fragment.
`ListFragment`
Displays a list of items that are managed by an adapter (such as a SimpleCursorAdapter), similar to ListActivity. It provides several methods for managing a list view, such as the onListItemClick() callback to handle click events. (Note that the preferred method for displaying a list is to use RecyclerView instead of ListView. In this case you would need to create a fragment that includes a RecyclerView in its layout. See Create a List with RecyclerView to learn how.)
`PreferenceFragmentCompat`
Displays a hierarchy of Preference objects as a list. This is used to create a settings screen for your application.
## Fragment Insertion in Layout (Method 1)
In `Activity.xml`:
```xml
<!-- Activity.xml boilerplate -->
<!-- Fragment drawn at Activity start cannot be drawn on event -->
<fragment
android:name="com.<app>.<Fragment>"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment_id" />
<!-- Activity.xml boilerplate -->
```
In `Fragment.kt`:
```kotlin
package <package>
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
/**
* A simple [Fragment] subclass.
*/
class FirstFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? {
// Inflate the layout for this fragment (draw and insert fragment in Activity)
return inflater.inflate(R.layout.<fragment_xml>, container, false)
}
//called after fragment is drawn (ACTIONS GO HERE)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
}
}
```
## Fragment Insertion in Layout (Method 2)
```xml
<!-- Activity.xml boilerplate -->
<layout
android:id="@+id/containerID"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Activity.xml boilerplate -->
```
In `Activity.kt`:
```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.<activity_xml>)
val fragmentID = FragmentClass()
//insert fragment from kotlin (can be triggered by event)
supportFragmentManager
.beginTransaction()
.add(R.id.<containerID>, fragmentID)
.commit()
//replace fragment from kotlin (can be triggered by event)
supportFragmentManager
.beginTransaction()
.replace(R.id.<containerID>, fragmentID)
.addToBackStack(null) // remember order of loaded fragment (keep alive previous fragments)
.commit()
}
```
## Passing Values from Activity to Fragment
In `Activity.kt`:
```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.<activity_xml>)
val fragmentID = FragmentClass()
val bundle = Bundle()
bundle.putString("key", "value") //passed value
fragmentID.arguments = bundle
//insert fragment from kotlin (can be triggered by event)
supportFragmentManager
.beginTransaction()
.add(R.id.<containerID>, fragmentID)
.commit()
}
```
In `Fragment.kt`:
```kotlin
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? {
value = arguments?.getString("key") //read passed value
// Inflate the layout for this fragment (draw and insert fragment in Activity)
return inflater.inflate(R.layout.<fragment_xml>, container, false)
}
```
![f](https://blog.avenuecode.com/hs-fs/hubfs/The%20activity%20and%20fragment%20lifecycles%20(1).png?width=640&name=The%20activity%20and%20fragment%20lifecycles%20(1).png)

View file

@ -0,0 +1,35 @@
# Gradle & Building
## `build.gradle` (Module)
```gradle
android {
defaultconfig{
applicationId <string> // app package name
minSdkVersion <int> // min API version
targetSdkVersion <int> // actual API version
versionCode <int> // unique code for each release
versionName "<string>"
}
}
```
## Distribuiting the app
### APK vs Bundle
- APK: android executable, contains all assets of the app (multiplr versions for each device). The user downloads all the assets.
- Bundle: split the assets based on dedvice specs. The users donwloads only the assest needed for the target device.
### APK generation & [App Signing](https://developer.android.com/studio/publish/app-signing)
- **Key store path**: location where the keystore file will be stored.
- **Key store password**: secure password for the keystore (**to be rememberd**).
- **Key alias**: identifying name for the key (**to be rememberd**).
- **Key password**: secure password for the key (**to be rememberd**).
The ketstore identifies the app and it's developers. It's needed for APK generation and releases distribution.

84
Android/MapsActivity.md Normal file
View file

@ -0,0 +1,84 @@
# Maps Activity
[Google Maps Docs](https://developers.google.com/maps/documentation/android-sdk/intro)
Activity sould be **Google Maps Activity**.
In `google_maps_api.xml`:
```xml
<resources>
<string name="google_maps_key" templateMergeStartegy="preserve", translateble="false">API_KEY</string>
</resources>
```
## Activity Layout (xml)
```xml
<!-- a fragment to contain the map -->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/<fragment_id>"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".<Activity>" />
```
## Activity Class (kotlin)
```kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker
import com.google.android.gms.maps.model.MarkerOptions
class MapsActivity : AppCompatActivity(), OnMapReadyCallback,
GoogleMap.OnInfoWindowClickListener,
GoogleMap.OnMarkerClickListener,
GoogleMap.OnCameraIdleListener{
private lateinit var mMap: GoogleMap // declare but not valorize
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.<activity_xml>)
// add the map to a fragment
val mapFragment = supportFragmentManager.findFragmentById(R.id.<fragment_id>) as SupportMapFragment
mapFragment.getMapAsync(this)
}
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
mMap.setOnMarkerClickListener(this)
mMap.setOnInfoWindowClickListener(this)
// Add a marker and move the camera
val location = LatLng(-34.0, 151.0) // set loaction with latitude and longitude
mMap.addMarker(MarkerOptions().position(location).title("Marker in ...")) // ad the marker to the map with a name and position
mMap.moveCamera(CameraUpdateFactory.newLatLng(location)) // move camera to the marker
}
override fun onInfoWindowClick(p0: Marker?) {
}
override fun onMarkerClick(p0: Marker?): Boolean {
}
override fun onCameraIdle() {
}
}
```

101
Android/SQLite.md Normal file
View file

@ -0,0 +1,101 @@
# SQLite in Android
[Kotlin SQLite Documentation](https://developer.android.com/training/data-storage/sqlite)
[NoSQL DB Realm Docs](https://realm.io/docs)
## Database Helper
Create database in memory and its tables.
```kotlin
class DatabaseHelper(
context: Context?,
name: String?,
factory: SQLiteDatabase.CursorFactory?,
version: Int
) : SQLiteOpenHelper(context, name, factory, version) { // super constructor?
// called on db creation if it does not exists (app installation)
override fun onCreate() {
sqLiteDatabase?.execSQL("CREATE TABLE ...") // create table
}
override fun onUpgrade(sqLiteDatabase: SQLiteDatabase?, ...) {
// table update logic
}
}
```
## AppSingleton
Make data persistent.
```kotlin
class AppSingleton consturctor(context: Context) {
var dataabse: SQLiteDatabase? = null // point to database file in memory
companion object {
@Volatile
private var INSTANCE: AppSingleton? = null
// syncronized makes sure that all instances of the singleton are actually the only existing one
fun getInstance(context: Contecxt) = INSTANCE ?: syncronized(this) {
INSTANCE ?: Singleton(context).also {
INSTANCE = it
}
}
}
// called to create DB in device memory
fun openDatabase(context: Context?) {
var databaseHelper = DatabaseHelper(context, "AppDB_Name.sqlite", null, version) {
database = databaseHelper.writeDatabase //?
}
}
}
```
## Activity
```kotlin
override fun onCreate() {
// either creates or reads DB
AppSingleton.getInstance().openDatabase(this) // context is this
val controller = ModelController()
controller.insert(model) // insert data from object
}
```
## ModelController
Controller to handle data from the objects and interact with the Database
```kotlin
sqLiteDatabse = AppISngleton.getInstance().database // reference to the database from the singleton
contentValues = ContentValues() // dict like structure to insert data in DB
contentValuest.put("DB_Column", value) // put data in the structure
// insertion query V1
sqLiteDatabase?.insert("table", null, contentValue)
//insertion query V2
sqLiteDatabase?.rawQuey("INSERT INTO ...")
// returns a Cursor()
val cursor = sqLiteDatabase?.query("table", ArrayOf(columns_to_read), "WHERE ...", "GROUP BY ...", "HAVING ...", "ORDER BY ...")
try {
if (cursor != null) {
while(cursor.moveToNext()) { // loop through cursor data
data = cursor.getString(cursor.getColumnIndex("DB_Column")) // read data from the cursor
}
}
} finally {
cursor?.close()
}
```

215
Android/activity.xml.md Normal file
View file

@ -0,0 +1,215 @@
# Activity.xml
## Resources
### Colors, Style, Strings
These resorsces are located in `app/src/main/res/values/<resource_type>.xml`
`@color/colorName` -> access to *color definition* in `colors.xml`
`@string/stringName` -> access to *string definition* in `strings.xml` (useful for localization)
`@style/styleName` -> access to *style definition* in `styles.xml`
In `colors.xml`:
```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- app bar color -->
<color name="colorPrimary">#6200EE</color>
<!-- status bar color -->
<color name="colorPrimaryDark">#3700B3</color>
<color name="colorAccent">#03DAC5</color>
<!-- other color definitions -->
</resources>
```
In `strings.xml`:
```xml
<resources>
<string name="app_name"> AppName </string>
<!-- other strings definitions -->
</resources>
```
In `styles.xml`:
```xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
```
## View & View Group
A **View** contains a specific element of the layout.
A **View Group** or **Layout** is a container of Views.
```xml
<View settings/>
<ViewGroup settings>
...
</ViewGroup>
```
`android:layout_width`, `android:layout_heigth`:
* fixed value (dp, sp)
* match_parent
* wrap_content
## ViewGroups
### [RelativeLayout](https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams)
The relative layout containing the view uses the value of these layout parameters to determine where to position the view on the screen.
If the view is not contained within a relative layout, these attributes are ignored.
```xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
</RelativeLayout>
```
`android:layout_above`: Positions the bottom edge of this view above the given anchor view ID.
`android:layout_alignBaseline`: Positions the baseline of this view on the baseline of the given anchor view ID.
`android:layout_alignBottom`: Makes the bottom edge of this view match the bottom edge of the given anchor view ID.
`android:layout_alignEnd`: Makes the end edge of this view match the end edge of the given anchor view ID.
`android:layout_alignLeft`: Makes the left edge of this view match the left edge of the given anchor view ID.
`android:layout_alignParentBottom`: If true, makes the bottom edge of this view match the bottom edge of the parent.
`android:layout_alignParentEnd`: If true, makes the end edge of this view match the end edge of the parent.
`android:layout_alignParentLeft`: If true, makes the left edge of this view match the left edge of the parent.
`android:layout_alignParentRight`: If true, makes the right edge of this view match the right edge of the parent.
`android:layout_alignParentStart`: If true, makes the start edge of this view match the start edge of the parent.
`android:layout_alignParentTop`: If true, makes the top edge of this view match the top edge of the parent.
`android:layout_alignRight`: Makes the right edge of this view match the right edge of the given anchor view ID.
`android:layout_alignStart`: Makes the start edge of this view match the start edge of the given anchor view ID.
`android:layout_alignTop`: Makes the top edge of this view match the top edge of the given anchor view ID.
`android:layout_alignWithParentIfMissing`: If set to true, the parent will be used as the anchor when the anchor cannot be be found for layout_toLeftOf, layout_toRightOf, etc.
`android:layout_below`: Positions the top edge of this view below the given anchor view ID.
`android:layout_centerHorizontal`: If true, centers this child horizontally within its parent.
`android:layout_centerInParent`: If true, centers this child horizontally and vertically within its parent.
`android:layout_centerVertical`: If true, centers this child vertically within its parent.
`android:layout_toEndOf`: Positions the start edge of this view to the end of the given anchor view ID.
`android:layout_toLeftOf`: Positions the right edge of this view to the left of the given anchor view ID.
`android:layout_toRightOf`: Positions the left edge of this view to the right of the given anchor view ID.
`android:layout_toStartOf`: Positions the end edge of this view to the start of the given anchor view ID.
### [LinearLayout](https://developer.android.com/reference/android/widget/LinearLayout.LayoutParams)
Layout that arranges other views either horizontally in a single column or vertically in a single row.
```xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <!-- or horizontal -->
</LinearLayout>
```
`android:layout_weight`: Indicates how much of the extra space in the LinearLayout is allocated to the view associated with these LayoutParams.
`android:layout_margin`: Specifies extra space on the left, top, right and bottom sides of this view.
`android:layout_marginBottom`: Specifies extra space on the bottom side of this view.
`android:layout_marginEnd`: Specifies extra space on the end side of this view.
`android:layout_marginHorizontal`: Specifies extra space on the left and right sides of this view.
`android:layout_marginLeft`: Specifies extra space on the left side of this view.
`android:layout_marginRight`: Specifies extra space on the right side of this view.
`android:layout_marginStart`: Specifies extra space on the start side of this view.
`android:layout_marginTop`: Specifies extra space on the top side of this view.
`android:layout_marginVertical`: Specifies extra space on the top and bottom sides of this view.
`android:layout_height`: Specifies the basic height of the view.
`android:layout_width`: Specifies the basic width of the view.
## Views
```xml
<!--ID is necessary for identification -->
<View
android:id="@+id/uniquieId"
android:layout_width="value"
android:layout_height="value"
/>
```
### TextView
To add `...` to truncate a string:
```xml
<!-- maxLines + ellipsize works only in API 22+ -->
<TextView
maxLines="n"
ellipsize="end" />
```
### ScrollView
The scroll view can only have one child. If the child is a layout than the layout can contain many elements.
```xml
<ScrollView
android:id="@+id/uniquieId"
android:layout_width="value"
android:layout_height="value">
<!-- single child -->
</ScrollView>
```
### RecyclerView
List of items
In `build.gradle`:
```gradle
dependencies {
implementation "androidx.recyclerview:recyclerview:<version>"
// For control over item selection of both touch and mouse driven selection
implementation "androidx.recyclerview:recyclerview-selection:<version>"
}
```
In `activity.xml`:
```xml
<!-- VIewGroup for a list of items -->
<androidx.recycleview.widget.RecycleView
android:id="@+id/uniquieId"
android:layout_width="value"
android:layout_height="value">
```
In `recyclerViewItem.xml`:
```xml
<!-- list item layout -->
```
### WebView
```xml
<WebView
android:id="@+id/uniquieId"
android:layout_width="value"
android:layout_height="value">
```
## Constraints
If a view is *anchored on both sides* and the width/height is set to `0dp` the view will expand to touch the elements to which is anchored.