# Mobile Application Development
<!-- ### Tables of Contents
- [Components of an Android App](#components-of-an-android-app)
- [Android Project Structure](#android-project-structure)
- [Layout Types](#layout-types)
- [Activity Lifecycle Methods](#activity-lifecycle-methods)
- [Views in Android](#views-in-android)
- [Navigating between Activities](#navigating-between-activities)
- [Adding Menu(s)](#adding-menus)
- [Persistant Storage using SharedPreferences](#persistant-storage-using-sharedpreferences)
- [Adding a Launcher Icon](#adding-a-launcher-icon)
- [Units of Measurement in Android](#units-of-measurement-in-android)
- [Database](#database)
- [OOP](#oop)
- [Appendix](#appendix)
<br>
<br>
<br>
---
<br>
<br>
<br> -->
# Before Mid
## Components of an Android App
1. Activity.
2. Service.
3. Broadcast Receiver.
4. Content Provider.
---
## Android Project Structure
### manifests/AndroidManifest.xml
- Contains metadata about the application.
- The manifest file is the root of the Android application.
- All android components are rgistered in the manifest file.
- The manifest file contains the following:
- Application name.
- Application version.
- Application package name.
- Application icon.
- Application description.
- Application permissions.
- Application activities.
- Application services.
- Application receivers.
- Application content providers.
### java/
- Contains the source code/ backend for the application (Java Files).
- Java files compile into classes (.class).
### res/
- Contains the resources for the application.
- drawable, menu, mipmap, values, layout, etc.
- **drawable:** images.
- **menu:** menu xml files.
- **mipmap:** icons.
- **values:** strings.
- **layout:** layout xml files.
**All resources are compiled into R class.**
**Dont use capital letters in resource names**
---
## Layout Types
1. Constraint Layout.
2. Linear Layout.
3. Table Layout.
4. Frame Layout.
5. Relative Layout (Legacy).
6. Grid Layout (Leagcy).
### Constraint Layout
- Similar to position (absoulte, relative, ...) in CSS.
- Postion of an element can be set releative to parent or sibling element.
```xml
<!-- XML -->
<ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/cl"
>
</ConstraintLayout>
```
```java
//JAVA
ContraintLayout cl;
// in onCreate()
cl = findViewById(R.id.cl);
```
### Linear Layout
- Two types of layout: horizontal and vertical.
- Horizontal layout:
- Left to right.
- Vertical layout:
- Top to bottom.
- Views are stacked after one another.
```xml
<!-- XML -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/vll"
>
</LinearLayout>
```
```java
//JAVA
LinearLayout vll;
// in onCreate()
vll = findViewById(R.id.vll);
```
### Table Layout
- Similar to HTML table.
- 2D layout.
- Consists of rows.
- Each row contains Views.
```xml
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
</TableRow>
</TableLayout>
```
### Frame Layout
- Only one view.
---
## Activity Lifecycle Methods
1. onCreate (Activity is created).
2. onStart (Activity is started).
3. onResume (Activity is resumed/ running/ in focus).
4. onPause (Activity is not in focus).
5. onStop(Activity is running in background, Home button pressed).
6. onRestart (Activity is restarted, in focus after onStop).
7. onDestroy (Removed from background).
---
## Views in Android
- TextView
- Button
- EditText
- ImageView
### TextView
```xml
<!-- XML -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello World"
android:id="@+id/tv"
/>
<!--
android:layout_width="match_parent" -> Defines width of the view same as its parent's
-->
<!--
android:layout_height="wrap_content" -> Defines height of the view so that it can wrap content inside it
-->
<!--
android:text="Hello World" -> Sets text to "Hello World"
-->
<!--
android:id="@+id/tv" -> Assigns id
-->
```
```java
//in onCreate()
//findViewById(id)
TextView tv=findViewById(R.id.tv);
String text=tv.getText().toString();
text=text+text;
//setText(String)
tv.setText(text);
```
<br>
### Button
```xml
<!-- XML -->
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btn"
android:text="Click Me"
android:layout_margin="10dp"
android:layout_gravity="center"
/>
<!--
android:layout_margin="10dp" -> Adds 10dp margin on all sides
-->
<!--
android:layout_gravity="center" -> Defines the position of text inside the button
-->
```
```java
//in onCreate()
//findViewById(id)
Button btn=findViewById(R.id.btn);
//setOnClickListener(View.OnClickListener)
btn.setOnClickListener(new View.OnClickListener() {
//onClick(View)
@Override
public void onClick(View v) {
btn.setText(btn.getText().toString()+"!");
}
});
```
<p style="font-weight:bold;font-size:32px">OR</p>
Set onClick in XML.
```xml
<!-- Set onClick Property in XML -->
<Button
...
android:id="@+id/btn"
android:onClick="changeTextHandler"
/>
<!--
android:onClick="changeTextHandler" -> Adds a method which executes when the click event is triggered
-->
```
Define changeTextHandler in Java.
```java
public void changeTextHandler(View v){
Button btn=findViewById(R.id.btn);
btn.setText(btn.getText().toString()+"!");
}
```
<br>
### EditText
```xml
<!-- XML -->
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et"
android:layout_margin="10dp"
android:layout_gravity="center"
android:hint="Enter Text"
/>
<!--
android:hint="Enter Text" Sets a placeholder text
-->
```
```java
//in onCreate()
//findViewById(id)
EditText et=findViewById(R.id.et);
String text=et.getText().toString();
```
<br>
### ImageView
```xml
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="16dp"
tools:srcCompat="@drawable/ic_launcher_background" />
<!--
tools:srcCompat="@drawable/ic_launcher_background" -> Source of the image to be displayed in ImageView
-->
```
---
## Navigating between Activities
### Navigation using Intent
- Intent is used for linking activities of same or separate applications.
- Intent is used to navigate between activities.
```Java
// Intent(Context, Class)
Intent intent = new Intent(this, NextActivity.class);
// startActivity(Intent)
startActivity(intent);
```
### Passing data using Intent
- Intent can be used to pass data between activities.
- putExtra() method is used to pass data.
```Java
// putExtra(String, StringOrIntOrFloat...)
intent.putExtra("name", "Hello World");
```
- For passing multiple values, putExtra() can be used multiple times.
- getStringExtra() method is used to get data.
```Java
// getStringExtra(String)
String recievedString=getIntent().getStringExtra("nameInString");
```
---
## Adding Menu(s)
- For adding a menu:
- Create a menu resource directory in res.
- Add a menu resource file in res/menu (main_menu.xml).
- Define the structure of menu in main_menu.xml.
```xml
<!-- XML -->
<!-- main_menu.xml -->
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/logout" android:title="Log Out"></item>
</menu>
```
### Types
In android, there are 3 types of menu(s):
1. Options Menu (3 dots in App header).
2. Context Menu (opens on longpress).
3. Popup Menu (popups on click).
#### Options Menu
1. Override onCreateOptionsMenu() method.
```java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//inflate(menu resource id, menu)
getMenuInflater().inflate(R.menu.main_menu,menu);
return true;
}
```
2. Override onOptionsItemSelected() method.
```java
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if(item.getItemId()==R.id.logout){
Intet intent = new Intent(this, FirstActivity.class);
startActivity(intent);
}
return super.onOptionsItemSelected(item);
}
```
#### Context Menu
1. Get the view that was longpressed.
```java
TextView tv;
//in onCreate()
tv = findViewById(R.id.tv);
```
2. Register the view with the context menu.
```java
registerForContextMenu(tv);
```
3. Override onCreateContextMenu() method.
```java
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.main_menu,menu);
}
```
4. Override onContextItemSelected() method.
```java
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
if(item.getItemId()==R.id.logout){
Intet intent = new Intent(this, FirstActivity.class);
startActivity(intent);
}
return true;
}
```
#### Popup Menu
1. Add a button and set its onClick property.
```xml
<!-- XML -->
<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<ConstraitLayout ...
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnPopup"
android:layout_margin="10dp"
android:text="Show Popup"
android:onClick="showPopup"
/>
</ConstraitLayout>
```
2. define showPopup() method in MainActivity.java.
```java
public void showPopup(View view){
}
```
3. Create a PopupMenu, set the anchor view and inflate the menu using getMenuInfater().inflate() and show() the menu.
```java
public void showPopup(View view){
//1. Create a PopupMenu
//PopupMenu(Context, View)
PopupMenu popupMenu = new PopupMenu(this,view);
//2. Inflate the menu
//inflate(menu resource id, menu)
//getMenu() method is used to get the menu.
getMenuInflater().inflate(R.menu.main_menu,popupMenu.getMenu());
//3. Show the menu
popupMenu.show();
}
```
4. Add a menu item click listener inside showPopup().
```java
public void showPopup(View view){
//1. Create a PopupMenu
//2. Inflate the menu
//3. Show the menu
//setOnMenuItemClickListener(MenuItemClickListener)
popupMenu.setOnMenuItemClickListener(
new PopupMenu.OnMenuItemClickListener() {
//onMenuItemClick(MenuItem)
public boolean onMenuItemClick(MenuItem item) {
if(item.getItemId()==R.id.red){
cl.setBackgroundColor(Color.RED);
}
return true;
}
});
}
```
---
## Persistant Storage using SharedPreferences
- For reading, SharedPreferences.
- For writing, SharedPreferences.Editor.
### Reading Preferences
1. Create a SharedPreferences object.
```Java
//in onCreate()
//getSharedPreferences(String PrefernceName, int mode: 0||1)
// 0 -> MODE_PRIVATE (Can only be accessed by the application)
// 1 -> MODE_WORLD_READABLE
SharePreferences sp = getSharedPreferences("MyPreferences", 0);
```
2. Get the value of a preference.
```Java
//getInt(String key, int defaultValue)
color=sp.getInt("primary_color", 0);
```
### Writing Preferences
1. Create a SharedPreferences.Editor object.
```Java
SharedPreferences.Editor editor;
//in onCreate()
editor = sp.edit();
//in any method
//putInt(String key, int value)
editor.putInt("primary_color", Color.RED);
//commit() method is used to save the changes.
editor.commit();
```
---
## Adding a Launcher Icon
1. Right Click on the mipmap directory.
2. New -> Image Asset.
3. Configure the image.
4. Click Finish.
5. In AndroidManifest.xml, change the application icon to the image asset.
```XML
android:icon="@mipmap/ic_launcher_2"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_2_round"
```
---
## Units of Measurement in Android
1. Pixels (px)
2. Density-independent Pixels (dp)
- 160 dp standard screen size.
- 160dp is equivalent to one inch of physical screen size.
3. Scaled Pixels (sp)
- Similar to dp and is recommended for specifying font sizes.
4. Point (pt)
- 1 pt is 1/72 of an inch.
5. Inches (in)
6. Millimeters (mm)
**Dots per Inch: dpi**
---
## OOP
**Object**
- Representation of a real world entity in programming.
- Also called as an instance of a class.
```Java
Person p=new Person();
```
**Class**
- A blueprint for creating objects.
```java
public class Person{
}
```
**Interface**
- An abstract class that defines methods that must be implemented by any class that implements it.
- All methods in an interface are public and abstract by default.
- "implements" keyword is used to implement an interface.
```java
interface Man{
public void speak();
public boolean isMan();
}
public class Person implements Man{
}
```
**Abstract Class**
- A class that can't be instantiated.
- Contains at least one abstract method.
```java
public abstract class Male{
}
public class Person extends Male{
}
```
**Abstract Method**
- A method without body.
```java
public abstract class Male{
public void getName();
}
```
**Instance Method**
- A method that belongs to an object.
- Must be called on an object.
- Can be overridden by subclasses.
```java
public class Person{
public void setName(String name){
this.name=name;
}
}
```
**Static Method**
- A method that belongs to a class.
- Can be called on a class (without initializing an object).
```java
public class Person{
public static int count=0;
public static void getCount(){
return count;
}
}
```
**Constant**
- A variable that can't be changed.
```java
public class Person{
public static final int MAX_AGE=100;
}
```
**Inheritance**
- "is a" relationship.
- parent child relationship.
- public and protected access.
- "extends" keyword.
```Java
public class Person{
}
public class Student extends Person{
}
```
**Constructor**
- A method that is called when an object is created.
- Used for initializing the object.
- Of two types:
1. Default constructor.
2. Parameterized constructor.
- Default constructor is called when no constructor is defined.
- If a constructor is defined, the default constructor is not called.
- Default contructor has to be defined if any other constructor is defined.
```Java
public class Person{
public Person(){
//Default constructor
}
public Person(String name){
//Parameterized constructor
this.name=name;
}
}
```
**this**
- refers to caller/calling object.
```java
public class Person{
public void setName(String name){
this.name=name;
}
}
```
**super**
- refers to constructor of the super/parent class.
```Java
public class Person{
public Person(){
this.name="";
}
}
public class Student extends Person{
public Student(){
super();
}
}
```
**Polymorphism**
- The ability of an object to take on many forms.
- Same method name with different parameters in same class (Overloading).
- Same method name with different implementation in different classes (Overriding).
**Enumerator OR Enum**
- Collection of constant values.
- Key/ Value pair.
```Java
enum Levels{
LOW,
MEDIUM,
HIGH
}
```
---
# After Mid
## Database
### SQLite Database
1. Extend class from `SQLiteOpenHelper`.
2. Create a parameterized constructor of class.
3. Overrride onCreate and onUpgrade.
#### Querying Database
For Reading data:
```java
SQLiteDatabase db=this.getReadableDatabase();
```
For Writing data:
```java
SQLiteDatabase db=this.getWriteableDatabase();
```
`SQLiteDatabase` provides built-in methods for inserting, updating and deleting data. For reading, raw queries are passed.
1. Insert
```java
//db.insert(tbl_name<String>,nullValueReplacement, cv<ContentValues>);
long result=db.insert("tbl_name",null,cv);
//result= -1-> failed to insert,
//result= 0-> 0 rows changed,
//result n-> n rows changed
```
2. Update
```java
//db.update(tblName<String>,cv<ContentValues>,where_string<String>,new String[]{whereArgs<String>});
int result=db.update("tbl_name",cv,"col_1=?",new String[]{String.valueOf(col_1)});
//result= -1-> failed to update,
//result= 0-> 0 rows changed,
//result n-> n rows changed
```
3. Delete
```java
//db.update(tblName<String>,where_string<String>,new String[]{whereArgs<String>});
int result=db.delete("Student","col_1=?",new String[]{String.valueOf(col_1)});
//result= -1-> failed to delete,
//result= 0-> 0 rows changed,
//result n-> n rows changed
```
4. Read
```java
//db.rawQuery("query"<String>,new String[]{whereArgs<String>});
Cursor csr=db.rawQuery("Select * from tbl_name where col_1=?", new String[]{String.valueOf(col_1)});
```
#### Example
```java
class DB extends SQLiteOpenHelper{
//parameterized constructor
public DB(Context context){
//super(context,db-name,factory,version);
super(context,"Db_Name.db",null,1);
}
//Override onCreate
public void onCreate(SQLiteDatabase db){
//db.execSQL("SQL Query");
db.execSQL("Create table if not exists tbl_name(col_1 data_type autoIncrement Primary Key, col_2 data_type unique)");
}
//Override onUpgrade
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("Drop table if exists tbl_name");
}
//Create a method for inserting data
public boolean createData(String col_1, int col_2){
ContentValues cv=new ContentValues();
//put("key <String>", value);
cv.put("col_1",col_1);
cv.put("col_2",col_2);
SQLiteDatabase db=this.getWritableDatabase();
//db.insert(tbl_name <String>, nullValueReplacement, ContentValues);
long result=db.insert("tbl_name",null,cv);
//result= -1-> failed to insert, result= 0-> 0 rows changed, result n-> n rows changed
return result != -1;
}
//Create a method for updating data
public boolean updateData(String col_1,int col_2){
ContentValues cv=new ContentValues();
cv.put("col_1",col_1);
cv.put("col_2",col_2);
SQLiteDatabase db=this.getWritableDatabase();
//db.update("tbl_name",ContentValues,"where_string like col_1=?",new String[]{col_1, col_2});
int result=db.update("tbl_name",cv,"col_1=?",new String[]{String.valueOf(col_1)});
//result= -1-> failed to insert, result= 0-> 0 rows changed, result n-> n rows changed
return result != -1;
}
//Create a method for deleting data
public boolean deleteData(int col_1){
SQLiteDatabase db=this.getWritableDatabase();
//db.delete("tbl_name","where_string",new String[]{col_1})
int res=db.delete("Student","col_1=?",new String[]{String.valueOf(col_1)});
//result= -1-> failed to insert, result= 0-> 0 rows changed, result n-> n rows changed
return result != -1;
}
//Create a method for reading data
public Cursor readUser(String col_1, int col_2){
SQLiteDatabase db=this.getReadableDatabase();
//db.rawQuery("SQL Query where col_1=? AND col_2=?",new String[]{col_1,col_2});
Cursor csr=
db.rawQuery("Select * from tbl_name where col_1=?", new String[]{col_1});
return csr;
}
}
```
---
## Layouts
## Views
0. (ArrayAdapter)
2. Spinner (Static + Dynamic)
3. ListView (Static + Dynamic)
4. RadioButton & RadioGroup
5. TimePicker
6. SeekBar
7. ProgressBar
8. RatingBar
9. DatePicker
### ArrayAdapter
- Modifies an array into the array of widgets or something else.
- Follows Adapter design pattern.
### Spinner
- The Spinner Items can be set statically, in xml by assigning a string array to `entries` property and dynamically, in java by creating a Array of Spinner List Items using `ArrayAdapter`.
```xml
<!-- XML -->
<Spinner
android:id="@+id/spinner2"
android:layout_width="409dp"
android:layout_height="wrap_content" />
```
```java
//JAVA
String[] cities = {"A","B","C","D"};
String selectedCity;
Spinner sp=findViewById(R.id.spinner2);
ArrayAdapter<String> a1=new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item,cities);
sp.setAdapter(a1);
sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
selectedCity = adapterView.getItemAtPosition(i).toString();
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
```
### ListView
```xml
<!-- XML -->
<ListView
android:id="@+id/lv"
android:divider="@color/black"
/>
```
```java
//JAVA
String[] cities = {"A","B","C","D"};
ListView lv=findViewById(R.id.lv);
ArrayAdapter<String> a1=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1
, android.R.id.text1,cities);
lv.setAdapter(a1);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//i is the index of item.
Toast.makeText(MainActivity.this, cities[i], Toast.LENGTH_SHORT).show();
}
});
```
### RadioButton & RadioGroup
```xml
<!-- XML -->
<RadioGroup
android:id="@+id/rgGender"
android:layout_width="0dp"
android:layout_height="wrap_content" >
<RadioButton
android:id="@+id/rbMale"
android:layout_width="wrap_content"
android:layout_height="55dp"
android:checked="true"
android:text="Male"/>
<RadioButton
android:id="@+id/rbFemale"
android:layout_width="wrap_content"
android:layout_height="55dp"
android:checked="false"
android:text="Female" />
</RadioGroup>
```
```java
//JAVA
radioGroup = findViewById(R.id.rgGender);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
if(radioGroup.getCheckedRadioButtonId()==R.id.rbMale)
gender="Male";
else if(radioGroup.getCheckedRadioButtonId()==R.id.rbFemale)
gender="Female";
}
});
```
### TimePicker
```xml
<!-- XML -->
<TimePicker
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tp"/>
```
```java
//JAVA
TimePicker tp=findViewById(R.id.tp);
tp.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
@Override
public void onTimeChanged(TimePicker timePicker, int i, int i1) {
Toast.makeText(MainActivity.this,timePicker.getHour()+":"+timePicker.getMinute(),
Toast.LENGTH_LONG).show();
}
});
```
### SeekBar
```xml
<!-- XML -->
<SeekBar
android:id="@+id/sb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
```
```java
//JAVA
SeekBar sb=findViewById(R.id.sb);
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
Toast.makeText(MainActivity.this, ""+i, Toast.LENGTH_SHORT).show();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
```
### ProgressBar
```xml
<!-- XML -->
<ProgressBar
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
```
```java
//JAVA
ProgressBar pb=findViewById(R.id.pb);
pb.setProgress(50);
Toast.makeText(MainActivity.this, ""+pb.getProgress(), Toast.LENGTH_SHORT).show();
```
### RatingBar
```xml
<!-- XML -->
<RatingBar
android:id="@+id/rb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:stepSize="0.5"
/>
```
```java
//JAVA
RatingBar rb=findViewById(R.id.rb);
rb.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
@Override
public void onRatingChanged(RatingBar ratingBar, float v, boolean b) {
Toast.makeText(MainActivity.this, ""+ratingBar.getRating(), Toast.LENGTH_SHORT).show();
}
});
```
### DatePicker
```xml
<!-- XML -->
<DatePicker
android:id="@+id/dp"
android:layout_width="match_parent"
android:layout_height="0dp" />
```
```java
//JAVA
DatePicker dp=findViewById(R.id.dp);
Calendar c=Calendar.getInstance();
dp.init(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH), new DatePicker.OnDateChangedListener() {
@Override
public void onDateChanged(DatePicker datePicker, int i, int i1, int i2) {
//i2=Day
//i1=Month
//1=Year
Toast.makeText(MainActivity.this, i2+"/"+(i1+1)+"/"+i, Toast.LENGTH_SHORT).show();
}
});
```
## Debugging
- `Log` class is used for showing logs in Logcat console.
- `Log`
## Activity Lifecycle Methods
![](https://i.imgur.com/ZlMaglz.png)
## Fragments
- Mutliple screens on one Activity.
- One fragment can be reused on multiple Activities.
- Views can be added in a fragment.
- A fragment has its own xml and java file.
- A fragment also has a lifecycle.
- A fragment can be added statically or dynamically.
### Creating a fragment
- Create a new fragment.
- Right click on MainActivity.java
- Goto New -> Fragment -> Fragment(Blank)
- Add Fragment Details and click Finish.
This will create a java and a xml file for the Fragment.
### Adding a fragment
#### Placing a fragment statically
```xml
<!-- In activity_main.xml, -->
<!-- add a FramLayout and a fragment in it-->
<FrameLayout
android:id="@+id/fl"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.mad.BlankFragment"
/>
<!-- android:name-> Refernce to the java file of Fragment (statically placed) -->
</FrameLayout>
```
#### Placing a fragment dynamically
1. Add a FrameLayout in Activity.
```xml
<!-- in activity_main.xml -->
<FrameLayout
android:id="@+id/fl"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</FrameLayout>
```
2. Place/ Change fragment dynamically from java file.
For performing opertaions on fragments dynamically, we need an instance of `FragmentTransaction` which is octained from `FragmentManager`.
```java
FragmentManager manager=getSupportFragmentManager();
FragmentTransaction transaction=manager.beginTransaction();
//add(ContainerId<int>,<Fragment>) -> adds Fragment on top.
transaction.add(R.id.fl,new FragmentNew());
//Completes the transaction
transaction.commit();
//Other transaction methods
// transaction.remove(<Fragment>); --Removes a fragment
// transaction.replace(ContainerId<int>,<Fragment>) -> replaces top Fragment with another Fragment.
```
__Fragments & Activites work on Stack. When back button is pressed the top fragment is poped out from the Fragment Stack and the new top fragment is displayed. Similarly, when a new Fragment is opened from a button on Previous Fragment, the New Fragment is pushed into Fragment Stack and becomes top Fragment.__
### Fragment Lifecycle Methods
![](https://i.imgur.com/lwwZo3w.png)
---
## Services
- Services are the tasks/ processes running in the background.
- Two main Types:
1. Starting Service.
1. Foreground Service.
2. Background Service.
2. Bound Service.
- Service Lifecycle Methods.
### Service Lifecycle Methods
![Service Lifecycle](https://developer.android.com/images/service_lifecycle.png)
#### 1. Creating a Service
- Create a ServiceClass extended from `Service`
- Override:
- `onBind` (for Bound Service).
- `onStartCommand` (for Starting Service).
- `onUnbind` (for unbinding a Bound Service).
- `onDestroy` (for stoping a service).
```java
class ServiceClass extends Service{
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate() {
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
public void onDestroy() {
super.onDestroy();
}
}
```
#### 2. Registering a Service.
- In AndroidManifest.xml
```xml
<service android:name=".FirstService" android:exported="false"/>
```
#### 3. Starting a Service.
- In MainActivity.java,
```java
//Create a new Intent
Intent serviceIntent=new Intent(this, ServiceClass.class);
```
- In MainActivity.java, In onStart,
```java
//Start Service using Intent
startService(serviceIntent);
// startService will call onCreate + onStartCommand or onBind
```
#### 4. Stoping a Service.
- In MainActivity.java, In onStop,
```java
//Stop Service using Intent
stopService(serviceIntent);
// startService will call onDestroy
```
##### Service Example
```java
public class FirstService extends Service {
MediaPlayer player;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
player=MediaPlayer.create(this,R.raw.mp3file);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
player.stop();
}
}
```
### Foreground Service
- Foreground services perform operations that are noticeable to the user.
- Foreground services show a status bar notification, so that users are actively aware that your app is performing a task in the foreground and is consuming system resources.
- The notification cannot be dismissed unless the service is either stopped or removed from the foreground.
- Examples of apps that would use foreground services include the following:
- A music player app that plays music in a foreground service. The notification might show the current song that is being played.
- A fitness app that records a user's run in a foreground service, after receiving permission from the user. The notification might show the distance that the user has traveled during the current fitness session.
#### 1. Add Permission in the App for Foreground Service
- In AndroidManifest.xml
```java
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
```
#### 2. Create a Service
- Override the `onStartCommand` to start a notification. If this step is missed, Android will kill the service after around a 1 minute of execution time.
```java
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent= new Intent(this, MainActivity.class);
PendingIntent pi=PendingIntent.getActivity(this,0,notificationIntent,0);
//Check if OS version is Android 8 or above.
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.O){
//Create a Notification Channel
NotificationChannel channel=new NotificationChannel("channel_id","channel_name",
NotificationManager.IMPORTANCE_DEFAULT);
//Set channel description
channel.setDescription("Hello World");
//Register channel
NotificationManager manager=getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder=new NotificationCompat.Builder(this,"channel_id");
builder.setContentTitle("Forground Service");
builder.setContentText("Running...");
builder.setSmallIcon(R.drawable.ic_launcher_foreground);
builder.setContentIntent(pi);
startForeground(121212,builder.build());
return super.onStartCommand(intent, flags, startId);
}
```
#### 3. Start the forground Service
- In MainActivity,
```java
Intent i = new Intent(context, ForegroundService.class);
// Check if Android version is 8 or above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(i);
} else {
startService(i);
}
```
### Bound Service
- A bound service is the server in a client-server interface.
- It allows components (such as activities) to bind to the service, send requests, receive responses.
- A bound service typically lives only while it serves another application component and does not run in the background indefinitely.
- To provide binding for a service, the `onBind()` method must be implemented. This method returns an `IBinder` object that defines the programming interface that clients can use to interact with the service.
- For allowing a client to bind to the service, call `bindService()`.
- Bound Service must be explicitly stopped by the service by calling `stopSelf()` or `stopService()`.
---
## Broadcast Reciever
### Global Broadcast Reciever
#### Creating a Reciever class
```java
public class FirstBroadcastReciever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Airplane Mode Chnaged", Toast.LENGTH_LONG).show();
}
}
```
#### Register the global braodcast reciever statically (in Android Manifest)
- In AndroidManifext.xml
```xml
<receiver android:name=".FirstBroadcastReciever" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
</intent-filter>
</receiver>
```
#### Register the global broadcast dynamically (in java)
```java
//In MainActivity, in onCreate,
// Create instance of FirstBroadcastReciever
FirstBroadcastReciever reciever= new FirstBroadcastReciever();
//Create an Intent Filter
IntentFilter intentFilter = new IntentFilter();
//Register an Action
intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
//Register the boradcast Reciever and action
registerReceiver(reciever, intentFilter);
```
### Local Broadcast Reciever
#### Creating a Reciever class
```java
public class FirstBroadcastReciever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String log=intent.getStringExtra("log");
Toast.makeText(context, log, Toast.LENGTH_LONG).show();
}
}
```
#### Creating and Sending a Local Broadcast
```java
//in MainActivity, in onCreate
LocalBroadcastManager m=LocalBroadcastManager.getInstance(this);
Intent localIntent=new Intent("LOCAL_ACTION");
//Attaching data with local broadcast
localIntent.putExtra("log","Data attached with Local broadcast");
//Sending local broadcast
m.sendBroadcast(localIntent);
```
- Local broadcast reciever can be registered in java only.
#### Listening to the local broadcast
```java
//In OtherActivity, in onCreate,
// Create instance of FirstBroadcastReciever
FirstBroadcastReciever reciever= new FirstBroadcastReciever();
//Create intent-filter
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("LOCAL_ACTION");
//Register BroadcastReciever
LocalBroadcastManager m=LocalBroadcastManager.getInstance(this);
m.registerReceiver(reciever, intentFilter);
```
---
## Notifications
1. Register Notification Channel (A Notification Channel is like a Notification Category).
2. Build Notification.
3. Setup Action on Noification (The actions perform on Notifications are handled by OS. We need to tell Os how to handle these actions. For that `PendingIntent` is used. `PendingIntent` is an `Intent` that is triggered by OS).
4. Trigger a Notification.
#### 1. Registering a Notification Channel
Notification Channels are available in Android 8 or above.
```java
//Check if OS version is Android 8 or above.
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
//Create a Notification Channel
NotificationChannel channel=new NotificationChannel("channel_id","channel_name",
NotificationManager.IMPORTANCE_DEFAULT);
//Set channel description
channel.setDescription("Hello World");
//Register channel
NotificationManager manager=getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
```
#### 2. Building a Notification
```java
//Build Notification
NotificationCompat.Builder builder=new NotificationCompat.Builder(this,"channel_id");
builder.setContentTitle("Notification Title");
builder.setContentText("Notification Content");
builder.setSmallIcon(R.drawable.ic_launcher_foreground);
```
##### Adding a Button
```java
//Create a pending intent
PendingIntent pi=PendingIntent.getActivity(this,0,i,0);
//Add Button and add PendingIntent to that button.
//PendingIntent will be triggered when the button on notification will be pressed.
//addAction(iconId<int>,ButtonText<String>,<PendingIntent>)
builder.addAction(R.drawable.ic_btn,"Press Me",pi);
```
#### 3. Setting up Action on Notification
For setting up action on a notification `Pending Intent` is used. A `PendingIntent` is an intent that is triggered by the OS.
##### Creating a PendingIntent
```java
//Perform Action On Notification
Intent i=new Intent(this,MainActivity.class);
//getActivity(<Context>, requestCode<int>, i<Intent>, flags<int>)
PendingIntent p=PendingIntent.getActivity(this,0,i,0);
```
##### Adding PendingIntent to Notification
```java
//setContentIntent(p<PendingIntent>)
builder.setContentIntent(p);
```
#### 4. Triggering a Notification
```java
NotificationManagerCompat manager=NotificationManagerCompat.from(this);
//void notify(id<int>,notification<Notification>)
manager.notify(121212,builder.build());
//build() builds and returns the Notification instance based on the configurations set using builder
```
---
## Appendix
**Activity**
- A collection of views that are displayed together on the screen.
- An activity is a single screen that is displayed to the user.
- Consists of a java file and an xml file.
**Service**
- Service is a background process that runs in the background.
**AppCompatActivity**
- It is used to extend the Activity class.
- Life cycle methods are declared in AppCompatActivity.
**Toast.makeText**
- Static Method (Can be called directly from the class).
**Toast.LENGTH_LONG**
- Static Constant.
**In Programming, It is a convention to declare the constants in CAPITAL LETTERS.**
**R**
- All resources are compiled into R class.
- R.id contains all the ids of the views.
**Color**
- Color class contains all the color constants (RED, GREEN, etc).
**findViewById(id)**
- It is used to get the view by its id.
- Then the view is further stored in a variable of the same type.
**setText(String)**
- It is used to set the text of the view.
**getText()**
- returns the text of the view as an Editable object which is then converted to String.
**setBackgroundColor(int)**
- It is used to set the background color of the view.
**Context**
- It is used to get the context of the activity.
- Context means the environment in which the activity is running.
**setOnClickListener(View.OnClickListener)**
- It is used to set the OnClickListener of the view.
**View.OnClickListener**
- An interface.
- Has to be implemented at the moment of creating the object.
**onClick(View)**
- It is called when the view is clicked.