Unit V - Activity and Multimedia with Databases - Copy
Unit V - Activity and Multimedia with Databases - Copy
Unit - V
Syllabus
5.1 Intent, Intent_Filter
5.2 Activity Lifecycle; Broadcast Lifecycle
5.3 Content Provider; Fragments
5.4 Service: Features of service, Android platforms service, Defining new service, Service
Lifecycle, Permission, example of service
5.5 Android System Architecture, Multimedia Framework, Play Audio and Video, Text to
Speech, Sensors, Async tasks
5.6 Audio Capture, Camera
5.7 Bluetooth, Animation
5.8 SQLite Database, necessity of SQLite, Creation and connection of the database, Extracting
value from cursors, Transactions.
Intent:
java.lang.Object
↳ android.content.Intent
In android, Intent is a messaging object which is used to request an action from another app
component such as activities, services, broadcast receivers and content providers.
Generally in android, Intents will help us to maintain the communication between app
components from the same application as well as with the components of other applications.
In android, Intents are the objects of android.content.Intent type and intents are mainly useful
to perform following things:
Component Description
Starting an Activity By passing an Intent object to startActivity() method we can start
a new Activity or existing Activity to perform required things.
Starting a Service By passing an Intent object to startService() method we can start a
new Service or send required instructions to an existing
Service.
Delivering a Broadcast By passing an Intent object to sendBroadcast() method we
can deliver our messages to other app broadcast receivers.
For example: Intent facilitate you to redirect your activity to another activity on occurrence of
any event. By calling, startActivity() you can perform this task.
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
startActivity(intent);
In the above example, foreground activity is getting redirected to another activity i.e.
SecondActivity.java. getApplicationContext() returns the context for your foreground activity.
Types of Intents:
Intent are of two types: Explicit Intent and Implicit Intent.
Explicit Intent:
Explicit Intents are used to connect the application internally.
In Explicit we use the name of component which will be affected by Intent. For Example: If we
know class name then we can navigate the app from One Activity to another activity using Intent.
In the similar way we can start a service to download a file in background process.
Explicit Intent work internally within an application to perform navigation and data transfer. The
below given code snippet will help you understand the concept of Explicit Intents:
Here SecondActivity is the JAVA class name where the activity will now be navigated.
/>
<EditText
android:id="@+id/secondNum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="100dp"
android:ems="10" />
<Button
android:id="@+id/addBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="100dp"
android:text="Add" />
</LinearLayout>
Now we will create another layout resource file result.xml in \src\main\res\layout path to get
the first activity (activity_main.xml) details in second activity file for that right click on your layout
folder à Go to New à select Layout Resource File and give name as result.xml.
Once we create a new layout resource file result.xml, open it and write the code like as shown
below:
result.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/resultView"
android:layout_marginLeft="100dp"
android:layout_marginTop="150dp"/>
</LinearLayout>
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText firstNum = (EditText)findViewById(R.id.firstNum);
final EditText secNum = (EditText)findViewById(R.id.secondNum);
Button btnAdd = (Button)findViewById(R.id.addBtn);
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int num1 = Integer.parseInt(firstNum.getText().toString());
int num2 = Integer.parseInt(secNum.getText().toString());
Intent intent = new
Intent(MainActivity.this,ResultActivity.class);
intent.putExtra("SUM",num1+" + "+num2+" = "+(num1+num2));
startActivity(intent);
}
});
}
}
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
super.onCreate(savedInstanceState);
setContentView(R.layout.result);
TextView result = (TextView)findViewById(R.id.resultView);
Intent intent = getIntent();
String addition = (String)intent.getSerializableExtra("SUM");
result.setText(addition);
}
}
Now we need to add this newly created activity in ActivityManifest.xml file in like as shown
below.
ActivityMainfest.xml
If you observe above example we are performing an addition operation in one activity
(MainActivity.java) and sending those details to another activity (ResultActivity.java) and added
all the activities in AndroidManifest.xml file.
Implicit Intent:
In android, Implicit Intents won’t specify any name of the component to start, instead it declare
an action to perform and it allow a component from other app to handle it. For example, by
using implicit intents we can request another app to show the location details of user or etc.
Following is the pictorial representation of how Implicit intents send a request to android system
to start another activity.
If you observe above image Activity A creates an intent with required action and send it to an
android system using startActivity() method. The android system will search for an intent filter
that matches the intent in all apps. Whenever the match found the system starts matching
activity (Activity B) by invoking onCreate() method.
In android when we create an implicit intents, the android system will search for matching
component by comparing the contents of an intent with intent filters which defined in manifest
file of other apps on the device. If matching component found, the system starts that component
and send it to Intent object. In case if multiple intent filters are matched then the system display
a dialog so that user can pick which app to use.
In android, Intent Filter is an expression in app’s manifest file and it is used to specify the type of
intents that the component would like to receive. In case if we create an Intent Filter for activity,
there is a possibility for other apps to start our activity by sending a certain type of intent
otherwise the activity can be started only by an explicit intent.
Following is the simple code snippet of implicit intent in android application.
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://developer.android.com"));
startActivity(intent);
If you observe above implicit intent we didn’t defined any specific name of component to start,
instead we defined an action (ACTION_VIEW) to open the defined URL
(http://developer.android.com) in browser within the device.
MainActivity.java
package com.jamiapolytechnic.implicitintentex;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.net.Uri;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText editText = (EditText)findViewById(R.id.urlText);
Button btn = (Button) findViewById(R.id.btnNavigate);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String url = editText.getText().toString();
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(url));
startActivity(intent);
}
});
}
}
IntentFilter:
Intent filter is used to specify the type of intents that an activity, service, or broadcast receiver
can respond to. It declares the capability of its parent component, what an activity or service can
do and what type of broadcasts a receiver can handle.
It opens the component to receiving intents of the advertised type, while filtering out those that
are not meaningful for the component.
Intent filters are very powerful feature of the Android platform. They provide the ability to launch
an activity based not only on an explicit request, but also an implicit one. For example, an explicit
request might tell the system to start “Start the Send Email activity in the Gmail app”.
By contrast, an implicit request tells the system to “Start a Send Email screen in any activity that
can do the job”. When the system UI asks a user which app to use to perform a task, that’s an
intent filter at work.
Syntax:
<intent-filter android:icon=”drawable resource”
android:label=”sting resource”
android:priority=”integer”
android:order=”integer”
…
</intent-filter>
contained in:
<activity>
<activity-alias>
<service>
<receiver>
must contain:
<action>
can contain:
<category>
<data>
Attributes:
android:icon : An icon represents the parent activity, service, or broadcast receiver when that
component is existing to the user as having the potential described by the filter.
The attribute must be set as a reference to drawable resource containing the image definition.
The defaulting value is the icon set by the parent component’s icon attribute. If theparent do not
specify an icon, the default is the icon set by the <application> element.
android:label : A user-readable label for the parent component. This label, rather than the single
set by the parent component, is used when the component is offered to the user as having the
capability described by the filter.
The label should be set asa reference to a string resource, so that it can be localized like other
strings in the user interface. However, for convenience while we are just beginning the
application, it can also be set as an unprocessed string. The value is the label set by parent
component. if the parent do not specify a label, the default is the label set by the <application>
element’s label attribute.
android:priority
The priority that should be given to the parent component with regard to handling intents of the
type described by the filter.
android:order
The order in which the filter should be processed when multiple filters match.
Activity:
In Android, Activity represents a single screen with a user interface (UI) of an application and it
will acts an entry point for users to interact with an app.
Generally, the android apps will contain multiple screens and each screen of our application will
be an extension of Activity class. By using activities, we can place all our android application UI
components in a single screen.
From the multiple activities in android app, one activity can be marked as a main activity and
that is the first screen to appear when we launch the application. In android app each activity
can start another activity to perform different actions based on our requirements.
For example, a contacts app which is having a multiple activities, in that the main activity screen
will show a list of contacts and from the main activity screen we can launch other activities that
provides a screens to perform a tasks like add a new contact and search for the contacts. All
these activities in contact app are loosely bound to other activities but will work together to
provide a better user experience.
Generally, in android there is a minimal dependencies between the activities in an app. To use
activities in application we need to register those activities information in our app’s manifest
file (AndroidMainfest.xml) and need to manage activity life cycle properly.
To use activities in our application we need to define an activities with required attributes in
manifest file (AndroidMainfest.xml) like as shown below:
<?xml version="1.0" encoding="utf-8"?>
<manifest …..>
<application …..>
<activity android:name=".MainActivity" >
…….
…….
</activity>
…….
</application>
</manifest>
The activity attribute android:name will represent the name of class and we can also add
multiple attributes like icon, label, theme, permissions, etc. to an activity element based on our
requirements.
In android application, activities can be implemented as a subclass of Activity class like as
shown below.
public class MainActivity extends Activity {
//….
}
This is how we can activities in android application based on our requirements.
Android system initiates its program within an Activity starting with a call on onCreate() callback
method. There is a sequence of callback methods that start up an activity and a sequence of
callback methods that tear down an activity.
This section will give you a detailed information about callback methods to handle activity
transitions between states during lifecycle.
onCreate()
This is the first callback method and it fires when the system creates an activity for the first
time. During the activity creation, activity entered into a Created state.
If we have an application start-up logic that needs to perform only once during the life cycle of
an activity, then we can write that logic in onCreate() method.
Following is the example of defining a onCreate() method in android activity.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Once onCreate() method execution is finished, the activity will enter into Started state and
system calls the onStart() method.
onStart()
The onStart() callback method will invoke when an activity entered into Started State by
completing onCreate() method. The onStart() method will make an activity visible to the user
and this method execution will finish very quickly.
Following is the example of defining a onStart() method in android activity.
@Override
protected void onStart()
{
super.onStart();
}
After completion of onStart() method execution, the activity enters into Resumed state and
system invoke the onResume() method.
onResume()
When an activity entered into Resumed state, the system invoke onResume() call back method.
In this state activity start interacting with user that means user can see the functionality and
designing part of an application on the single screen.
Mostly the core functionality of an app is implemented in onResume() method.
The app will stays in this Resumed state until an another activity happens to take focus away
from the app like getting a phone call or screen turned off, etc.
In case if any interruption events happen in Resumed state, the activity will entered into Paused
state and the system will invoke onPause() method.
After an activity returned from Paused state to Resumed state, the system again will call
onResume() method due this we need to implement onResume() method to initialize the
components that we release during onPause() method
Following is the example of defining a onResume() method in android activity.
@Override
protected void onResume() {
super.onResume();
if (mCamera == null) {
initializeCamera();
}
}
If any interruption happen in Resumed state, the activity will entered into Paused state and the
system will invoke onPause() method.
onPause()
Whenever the user leaves an activity or the current activity is being Paused then the system
invoke onPause() method. The onPause() method is used to pause an operations like stop
playing the music when the activity is in paused state or pause an activity while switching from
one app to another app because every time only one app can be focused.
Following is the example of defining a onPause() method in android activity.
@Override
protected void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
After completion of onPause() method execution, the next method is either onStop() or
onResume() depending on what happens after an activity entered into Paused state.
onStop()
The system will invoke onStop() callback method when an activity no longer visible to the user,
the activity will enter into Stopped state. This happens due to current activity entered into
Resumed state or newly launched activity covers complete screen or it’s been destroyed.
The onStop() method is useful to release all the app resources which are no longer needed to
the user.
Following is the example of defining a onStop() method in android activity.
@Override
protected void onStop()
{
super.onStop();
}
The next callback method which raised by system is either onRestart(), in case if the activity
coming back to interact with the user or onDestroy(), in case if the activity finished running.
onRestart()
The system will invoke onRestart() method when an activity restarting itself after stopping it.
The onRestart() method will restore the state of activity from the time that is being stopped.
The onRestart() callback method in android activity will always followed by onStart() method.
onDestroy()
The system will invoke onDestroy() method before an activity is destroyed and this is the final
callback method which received by the android activity.
The system will invoke this onDestory() callback method either the activity is finishing or system
destroying the activity to save space.
Following is the example of defining a onDestroy() method in android activity.
@Override
protected void onDestroy()
{
super.onDestroy();
The onDestroy() method will release all the resources which are not released by previous
callback onStop() method.
Generally, in android activity class uses different callback methods like onCreate(), onStart(),
onPause(), onRestart(), onResume(), onStop() and onDestroy() to go through a different stages
of activity life cycle.
Above is the pictorial representation of Android Activity Life cycle which shows how Activity will
behave in different stages using callback methods.
Whenever the user trying to leave an activity like switching from one app to another app, the
system will use callback methods to dismantle the activity completely or partially to resume the
activity from where the user left off.
Based on our requirements we can implement the activity in android app using callback method
and it’s not necessary to use all callback methods in each android application.
BroadCast:
Android apps can send or receive broadcast messages from the Android system and other
Android apps, similar to the publish-subscribe design pattern. These broadcasts are sent when
an event of interest occurs. For example, the Android system sends broadcasts when various
system events occur, such as when the system boots up or the device starts charging. Apps can
also send custom broadcasts, for example, to notify other apps of something that they might be
interested in (for example, some new data has been downloaded).
Apps can register to receive specific broadcasts. When a broadcast is sent, the system
automatically routes broadcasts to apps that have subscribed to receive that particular type of
broadcast.
Generally speaking, broadcasts can be used as a messaging system across apps and outside of
the normal user flow.
Many broadcasts originate in system code (eg, "I got mail") but any other application can also
initate broadcasts.
Broadcast receivers do not display a user interface. However, they may perhaps start an activity
in response to the information they receive, or - as services do - they may possibly use the
notification manager to alert the user.
• Register to intent to observe
• Gets notification when intents occur
OR
In Android, Broadcast Receiver is a component which will allow Android system or other apps to
deliver events to the app like sending a low battery message or screen turned off message to the
app. The apps can also initiate broadcasts to let other apps know that required data available in
a device to use it.
Generally, we use Intents to deliver broadcast events to other apps and Broadcast Receivers use
status bar notifications to let user know that broadcast event occurs.
In android, Broadcast Receiver is implemented as a subclass of BroadcastReceiver and each
broadcast is delivered as an Intent object.
We can register an app to receive only few broadcast messages based on our requirements.
When a new broadcast received, the system will check for specified broadcasts have subscribed
or not based on that it will routes the broadcasts to the apps.
Receiving Broadcasts
In android, we can receive broadcasts by registering in two ways.
1. Specify the <receiver> element in your app's manifest (AndroidManifest.xml).
<receiver android:name=".SampleBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
The above statement will fire the defined system broadcast event whenever the boot process is
completed.
2. Subclass BroadcastReceiver and implement onReceive(Context, Intent).
public class MyActivity extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, log, Toast.LENGTH_LONG).show();
}
}
If you observe above code snippet we create a custom Intent “sintent”. We need to register our
intent action in android manifest file like as shown below
<receiver android:name=".SampleBroadcastReceiver">
<intent-filter>
<action android:name="
com.jamiapolytechnic.broadcastex.MY_NOTIFICATION" />
</intent-filter>
</receiver>
This is how we can create our own custom broadcasts using Intents in android applications.
System Broadcasts
In android, several system events are defined as final static fields in the Intent class. Following
are the some of system events available in android applications.
Event Description
android.intent.action.BOOT_COMPLETED It raise an event, once boot completed.
android.intent.action.POWER_CONNECTED It is used to trigger an event when power
connected to the device.
android.intent.action.POWER_DISCONNECTED It is used to trigger an event when power
got disconnected from the device.
android.intent.action.BATTERY_LOW It is used to call an event when battery is
low on device.
android.intent.action.BATTERY_OKAY It is used to call an event when battery is
OKAY again.
android.intent.action.REBOOT It call an event when the device rebooted
again.
Likewise we have many system events available in android application.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
Now open activity_main.xml file from \src\main\res\layout path and write the following code.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/txtMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="100dp"
android:layout_marginTop="180dp"
android:ems="10"/>
<Button
android:id="@+id/btnShow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="130dp"
android:text="Show Broadcast"/>
</LinearLayout>
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
});
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
Now we need to register our broadcast receiver in android manifest file (AndroidManifest.xml)
using <receiver> attribute like as shown below.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jamiapolytechnic.broadcastreceiverex">
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
provider using a provider client object. Together, providers and provider clients offer a
consistent, standard interface to data that also handles inter-process communication and
secure data access.
A content provider presents data to external applications as one or more tables that are similar
to the tables found in a relational database. A row represents an instance of some type of data
the provider collects, and each column in the row represents an individual piece of data
collected for an instance.
A content provider coordinates access to the data storage layer in your application for a
number of different APIs and components as illustrated in figure 1, these include:
• Sharing access to your application data with other applications
• Sending data to a widget
• Returning custom search suggestions for your application through the search framework
using SearchRecentSuggestionsProvider
• Synchronizing application data with your server using an implementation of
AbstractThreadedSyncAdapter
• Loading data in your UI using a CursorLoader
Relationship between content provider and other components.
Accessing a provider
When you want to access data in a content provider, you use the ContentResolver object in
your application's Context to communicate with the provider as a client. The ContentResolver
object communicates with the provider object, an instance of a class that implements
ContentProvider. The provider object receives data requests from clients, performs the
requested action, and returns the results. This object has methods that call identically-named
methods in the provider object, an instance of one of the concrete subclasses of
ContentProvider. The ContentResolver methods provide the basic "CRUD" (create, retrieve,
update, and delete) functions of persistent storage.
A common pattern for accessing a ContentProvider from your UI uses a CursorLoader to run an
asynchronous query in the background. The Activity or Fragment in your UI call a CursorLoader
to the query, which in turn gets the ContentProvider using the ContentResolver. This allows the
UI to continue to be available to the user while the query is running. This pattern involves the
interaction of a number of different objects, as well as the underlying storage mechanism, as
illustrated in figure below.
Content URIs
In android, Content URI is an URI which is used to query a content provider to get the required
data. The Content URIs will contain the name of entire provider (authority) and the name that
points to a table (path).
Generally the format of URI in android applications will be like as shown below
content://authority/path
Following are the details about various parts of an URI in android application.
content:// - The string content:// is always present in the URI and it is used to represent the
given URI is a content URI.
authority - It represents the name of content provider, for example phone, contacts, etc. and
we need to use fully qualified name for third party content providers like
com.example.contactprovider
path - It represents the table’s path.
The ContentResolver object use the URI’s authority to find the appropriate provider and send
the query objects to the correct provider. After that ContentProvider uses the path of content
URI to choose the right table to access.
Following is the example of simple example of URI in android applications.
content://contacts_info/users
Here the string content:// is used to represent URI is a content URI, contacts_info string is the
name of provider’s authority and users string is the table’s path.
query() - It receives a request from the client. By using arguments it will get a data from
requested table and return the data as a Cursor object.
insert() - This method will insert a new row into our content provider and it will return the
content URI for newly inserted row.
update() - This method will update an existing rows in our content provider and it return the
number of rows updated.
delete() - This method will delete the rows in our content provider and it return the number of
rows deleted.
getType() - This method will return the MIME type of data to given content URI.
onCreate() - This method will initialize our provider. The android system will call this method
immediately after it creates our provider.
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import java.util.HashMap;
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case uriCode:
return "vnd.android.cursor.dir/users";
default:
throw new IllegalArgumentException("Unsupported URI: " +
uri);
}
}
@Override
public boolean onCreate() {
Context context = getContext();
DatabaseHelper dbHelper = new DatabaseHelper(context);
db = dbHelper.getWritableDatabase();
if (db != null) {
return true;
}
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(TABLE_NAME);
switch (uriMatcher.match(uri)) {
case uriCode:
qb.setProjectionMap(values);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (sortOrder == null || sortOrder == "") {
sortOrder = id;
}
Cursor c = qb.query(db, projection, selection, selectionArgs, null,
null, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
long rowID = db.insert(TABLE_NAME, "", values);
if (rowID > 0) {
Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(_uri, null);
return _uri;
}
throw new SQLiteException("Failed to add a record into " + uri);
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)) {
case uriCode:
count = db.update(TABLE_NAME, values, selection,
selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)) {
case uriCode:
count = db.delete(TABLE_NAME, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
private SQLiteDatabase db;
static final String DATABASE_NAME = "EmpDB";
static final String TABLE_NAME = "Employees";
static final int DATABASE_VERSION = 1;
static final String CREATE_DB_TABLE = " CREATE TABLE " + TABLE_NAME
+ " (id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ " name TEXT NOT NULL);";
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_DB_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int
newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
}
Now open an activity_main.xml file from \src\main\res\layout path and write the code like as
shown below.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name"
android:layout_marginLeft="100dp"
android:layout_marginTop="100dp"/>
<EditText
android:id="@+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="100dp"
android:ems="10"/>
<Button
android:id="@+id/btnAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClickAddDetails"
android:layout_marginLeft="100dp"
android:text="Add User"/>
<Button
android:id="@+id/btnRetrieve"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClickShowDetails"
android:layout_marginLeft="100dp"
android:text="Show Users"/>
<TextView
android:id="@+id/res"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="100dp"
android:clickable="false"
android:ems="10"/>
</LinearLayout>
Now open MainActivity.java file and write the code like as shown below:
MainActivity.java
package com.jamiapolytechnic.contentproviderex;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
InputMethodManager imm =
(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
return true;
}
public void onClickAddDetails(View view) {
ContentValues values = new ContentValues();
values.put(UsersProvider.name, ((EditText)
findViewById(R.id.txtName)).getText().toString());
getContentResolver().insert(UsersProvider.CONTENT_URI, values);
Toast.makeText(getBaseContext(), "New Record Inserted",
Toast.LENGTH_LONG).show();
}
strBuild.append("\n"+cursor.getString(cursor.getColumnIndex("id"))+ "-"+
cursor.getString(cursor.getColumnIndex("name")));
cursor.moveToNext();
}
resultView.setText(strBuild);
}
else {
resultView.setText("No Records Found");
}
}
}
We need to include this newly created content provider in android manifest file
(ActivityManifest.xml) using <provider> attribute like as shown below.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jamiapolytechnic.contentproviderex">
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest>
Fragments:
In android, Fragments are the modular section of an activity design and these are used to
represent the behaviour of user interface (UI) in an activity. By using fragments we can create a
flexible UI designs that can be adjusted based on the device screen size such as tablets,
smartphones.
We can build multi-pane UI by combining multiple fragments in a single activity and we can
reuse same fragment in multiple activities. The fragment has its own lifecycle call-backs and
accept its own input events.
We can add or remove fragments in an activity while activity is running. In android, the
fragment will act as a sub-activity and we can reuse it in multiple activities.
Generally, in android the fragment must be included in an activity due to that the fragment
lifecycle will always effected by the host activity life cycle. In case if we pause an activity, all the
fragments related to an activity will also be stopped.
In android, we can insert fragment into activity layout by using <fragment> element and by
dividing the layout of an activity into fragments, we can modify the appearance of an app
design at runtime. We can also implement a fragment without having any user interface (UI).
It’s an optional to use fragments into activity but by doing this it will improve the flexibility of
our app UI and make it easier to adjust our app design based on the device size.
Following is the example of defining a multiple fragments in single activity for the tablet design
to display the details of an item which we selected in app, but separated for mobile design.
If you observe above example for Tablet we defined an Activity A with two fragments such as
one is to show the list of items and second one is to show the details of item which we selected
in first fragment.
For Handset device, there is no enough space to show both the fragments in single activity, so
the Activity A includes first fragment to show the list of items and the Activity B which includes
another fragment to display the details of an item which is selected in Activity A.
For example, GMAIL app is designed with multiple fragments, so the design of GMAIL app will
be varied based on the size of device such as tablet or mobile device.
Same way create another file details_info.xml, open it and write the code like as shown below:
details_info.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0079D6">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:layout_marginTop="200px"
android:layout_marginLeft="200px"
android:id="@+id/Name"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="200px"
android:textColor="#ffffff"
android:id="@+id/Location"/>
</LinearLayout>
Now we need to create our own custom fragment class files (ListMenuFragment.java,
DetailsFragment.java) in \java\com.jamiapolytechnic.fragmentsex path to bind and display data
in fragments for that right click on your application folder -> Go to New -> select Java Class and
give name as DetailsFragment.java.
Once we create a new file DetailsFragment.java, open it and write the code like as shown
below:
DetailsFragment.java
package com.jamiapolytechnic.fragmentex;
//import androidx.fragment.app.Fragment;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
If you observe above code we extended class with Fragment and used LayoutInflater to show
the details of fragment. We defined a function change() to change the text in textview.
Same way create another file ListMenuFragment.java, open it and write the code like as shown
below:
ListMenuFragment.java
package com.jamiapolytechnic.fragmentex;
//import androidx.fragment.app.ListFragment;
import android.app.ListFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
If you observe above code we extended our class using ListFragment and we defined two array
of strings users, location which contains names and locations. We defined onListItemClick event
to update the name and location in DetailsFragment based on the list item which we clicked.
Now we need to display our fragments horizontally side by side in main layout for that open
activity_main.xml file and write code like as shown below:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context="com.jamiapolytechnic.fragmentex.MainActivity">
<fragment
android:layout_height="match_parent"
android:layout_width="350px"
android:name="com.jamiapolytechnic.fragmentex.ListMenuFragment"
android:id="@+id/fragment"/>
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name ="com.jamiapolytechnic.fragmentex.DetailsFragment"
android:id="@+id/fragment2"/>
</LinearLayout>
We are not going to make any modifications for our main activity file (MainActivity.java) and
manifest file (AndroidMainfest.xml).
OR
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="fill_parent"
android:layout_height="fill_parent"
tools:context="com.jamiapolytechnic.fragmentex.MainActivity">
<fragment
android:id="@+id/fragment1"
android:name="com.jamiapolytechnic.fragmentex.Fragment1"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="@+id/fragment2"
android:name="com.jamiapolytechnic.fragmentex.Fragment2"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
MainActivity.java
package com.jamiapolytechnic.fragmentex;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
frag1_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F5F5DC"
tools:context="com.jamiapolytechnic.fragmentex.Fragment1">
</FrameLayout>
frag2_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0FFFF"
tools:context="com.jamiapolytechnic.fragmentex.Fragment2">
</FrameLayout>
Fragment1.java
package com.jamiapolytechnic.fragmentex;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.frag1_layout, container, false);
}
}
Fragment2.java
package com.jamiapolytechnic.fragmentex;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,Bundle savedInstanceState) {
// Inflate the layout for this fragment
// View inflate(int resource, ViewGroup root, boolean attachToRoot)
// Inflate a new view hierarchy from the specified xml resource.
return inflater.inflate(R.layout.frag2_layout, container, false);
}
}
Service
A Service is an application component that can perform long-running operations in the
background. It does not provide a user interface. Once started, a service might continue
running for some time, even after the user switches to another application. Additionally, a
component can bind to a service to interact with it and even perform interprocess
communication (IPC). For example, a service can handle network transactions, play music,
perform file I/O, or interact with a content provider, all from the background.
Service features:
I. Services perform long running operations in the background.
2. It does not contain a user interface.
3. It is useful for things like playing music, network operations, etc.
4. Services are run independently of the component that created it.
5. It can be bound to by other application components if allowed.
Types of Services
These are the three different types of services:
Foreground
A foreground service performs some operation that is noticeable to the user. For example, an
audio app would use a foreground service to play an audio track. Foreground services must
display a Notification. Foreground services continue running even when the user isn't
interacting with the app.
When you use a foreground service, you must display a notification so that users are actively
aware that the service is running. This notification cannot be dismissed unless the service is
either stopped or removed from the foreground.
Background
A background service performs an operation that isn't directly noticed by the user. For
example, if an app used a service to compact its storage, that would usually be a background
service.
Bound
A service is bound when an application component binds to it by calling bindService(). A bound
service offers a client-server interface that allows components to interact with the service, send
requests, receive results, and even do so across processes with interprocess communication
(IPC). A bound service runs only as long as another application component is bound to it.
Multiple components can bind to the service at once, but when all of them unbind, the service
is destroyed.
Generally services are either started or bound, your service can work both ways—it can be
started (to run indefinitely) and also allow binding. It's simply a matter of whether you
implement a couple of callback methods: onStartCommand() to allow components to start it
and onBind() to allow binding.
Regardless of whether your service is started, bound, or both, any application component can
use the service (even from a separate application) in the same way that any component can use
an activity—by starting it with an Intent. However, you can declare the service as private in the
manifest file and block access from other applications.
The basics
To create a service, you must create a subclass of Service or use one of its existing subclasses. In
your implementation, you must override some callback methods that handle key aspects of the
service lifecycle and provide a mechanism that allows the components to bind to the service, if
appropriate. These are the most important callback methods that you should override:
onStartCommand()
The system invokes this method by calling startService() when another component (such as an
activity) requests that the service be started. When this method executes, the service is started
and can run in the background indefinitely. If you implement this, it is your responsibility to
stop the service when its work is complete by calling stopSelf() or stopService(). If you only
want to provide binding, you don't need to implement this method.
onBind()
The system invokes this method by calling bindService() when another component wants to
bind with the service (such as to perform RPC). In your implementation of this method, you
must provide an interface that clients use to communicate with the service by returning an
IBinder. You must always implement this method; however, if you don't want to allow binding,
you should return null.
onCreate()
The system invokes this method to perform one-time setup procedures when the service is
initially created (before it calls either onStartCommand() or onBind()). If the service is already
running, this method is not called.
onDestroy()
The system invokes this method when the service is no longer used and is being destroyed.
Your service should implement this to clean up any resources such as threads, registered
listeners, or receivers. This is the last call that the service receives.
The Android system stops a service only when memory is low and it must recover system
resources for the activity that has user focus. If the service is bound to an activity that has user
focus, it's less likely to be killed; if the service is declared to run in the foreground, it's rarely
killed.
In the following sections, you'll see how you can create the startService() and bindService()
service methods, as well as how to use them from other application components.
There are other attributes that you can include in the <service> element to define properties
such as the permissions that are required to start the service and the process in which the
service should run. The android:name attribute is the only required attribute—it specifies the
class name of the service. After you publish your application, leave this name unchanged to
avoid the risk of breaking code due to dependence on explicit intents to start or bind the
service.
You can ensure that your service is available to only your app by including the android:exported
attribute and setting it to false. This effectively stops other apps from starting your service,
even when using an explicit intent.
Starting a service
You can start a service from an activity or other application component by passing an Intent to
startService() or startForegroundService(). The Android system calls the service's
onStartCommand() method and passes it the Intent, which specifies which service to start.
For example, an activity can start the example service in the previous section (HelloService)
using an explicit intent with startService(), as shown here:
startService(new Intent(this, MyService.class));
The startService() method returns immediately, and the Android system calls the service's
onStartCommand() method. If the service isn't already running, the system first calls
onCreate(), and then it calls onStartCommand().
If the service doesn't also provide binding, the intent that is delivered with startService() is the
only mode of communication between the application component and the service. However, if
you want the service to send a result back, the client that starts the service can create a
PendingIntent for a broadcast (with getBroadcast()) and deliver it to the service in the Intent
that starts the service. The service can then use the broadcast to deliver a result.
Multiple requests to start the service result in multiple corresponding calls to the service's
onStartCommand(). However, only one request to stop the service (with stopSelf() or
stopService()) is required to stop it.
Stopping a service
A started service must manage its own lifecycle. That is, the system doesn't stop or destroy the
service unless it must recover system memory and the service continues to run after
onStartCommand() returns. The service must stop itself by calling stopSelf(), or another
component can stop it by calling stopService().
Once requested to stop with stopSelf() or stopService(), the system destroys the service as soon
as possible.
a moment before disappearing. A status bar notification provides an icon in the status bar with
a message, which the user can select in order to take an action (such as start an activity).
Usually, a status bar notification is the best technique to use when background work such as a
file download has completed, and the user can now act on it. When the user selects the
notification from the expanded view, the notification can start an activity (such as to display the
downloaded file).
The lifecycle of a service is much simpler than that of an activity. However, it's even more
important that you pay close attention to how your service is created and destroyed because a
service can run in the background without the user being aware.
The service lifecycle—from when it's created to when it's destroyed—can follow either of these
two paths:
A started service
The service is created when another component calls startService(). The service then runs
indefinitely and must stop itself by calling stopSelf(). Another component can also stop the
service by calling stopService(). When the service is stopped, the system destroys it.
A bound service
The service is created when another component (a client) calls bindService(). The client then
communicates with the service through an IBinder interface. The client can close the
connection by calling unbindService(). Multiple clients can bind to the same service and when
all of them unbind, the system destroys the service. The service does not need to stop itself.
These two paths aren't entirely separate. You can bind to a service that is already started with
startService(). For example, you can start a background music service by calling startService()
with an Intent that identifies the music to play. Later, possibly when the user wants to exercise
some control over the player or get information about the current song, an activity can bind to
the service by calling bindService(). In cases such as this, stopService() or stopSelf() doesn't
actually stop the service until all of the clients unbind.
Figure illustrates the typical callback methods for a service. Although the figure separates
services that are created by startService() from those created by bindService(), keep in mind
that any service, no matter how it's started, can potentially allow clients to bind to it. A service
that was initially started with onStartCommand() (by a client calling startService()) can still
receive a call to onBind() (when a client calls bindService()).
By implementing these methods, you can monitor these two nested loops of the service's
lifecycle:
The entire lifetime of a service occurs between the time that onCreate() is called and the time
that onDestroy() returns. Like an activity, a service does its initial setup in onCreate() and
releases all remaining resources in onDestroy(). For example, a music playback service can
create the thread where the music is played in onCreate(), and then it can stop the thread in
onDestroy().
The active lifetime of a service begins with a call to either onStartCommand() or onBind(). Each
method is handed the Intent that was passed to either startService() or bindService().
If the service is started, the active lifetime ends at the same time that the entire lifetime ends
(the service is still active even after onStartCommand() returns). If the service is bound, the
active lifetime ends when onUnbind() returns.
Example of service:
In this example, we create four buttons to start, stop, bind, and unbind to the service. When we
click on the particular button the corresponding service method will call and a toast message
will appear.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btnStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startService"
android:layout_marginLeft="130dp"
android:layout_marginTop="150dp"
android:text="Start Service"/>
<Button
android:id="@+id/btnstop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="stopService"
android:layout_marginLeft="130dp"
android:layout_marginTop="20dp"
android:text="Stop Service"/>
</LinearLayout>
MainActivity.java
package com.jamiapolytechnic.serviceexample;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Start the service
public void startService(View view) {
startService(new Intent(this, MyService.class));
}
// Stop the service
public void stopService(View view) {
stopService(new Intent(this, MyService.class));
}
}
MyService.java
package com.jamiapolytechnic.serviceexample;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.provider.Settings;
import android.widget.Toast;
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
// Stopping the player when service is destroyed
player.stop();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jamiapolytechnic.serviceexample">
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest>
Multimedia Framework
The Android multimedia system includes multimedia applications, multimedia framework,
OpenCore engine and hardware abstract for audio/video input/output devices. And the goal of
the android multimedia framework is to provide a consistent interface for Java services. The
multimedia framework consists of several core dynamic libraries such as libmediajni, libmedia,
libmediaplayservice and so on.
A general multimedia framework architecture is shown in figure below.
From figure, we can see that, Java classes call the Native C library Libmedia through Java JNI (Java
Native Interface). Libmedia library communicates with Media Server guard process through
Android’s Binder IPC (inter process communication) mechanism. Media Server process creates
the corresponding multimedia service according to the Java multimedia applications. The whole
communication between Libmedia and Media Server forms a Client/Server model.
From figure below, we can see that the typical video/audio data stream works in Android as
follows. Specially, Java applications first set the URI of the media (from file or network) to
PVPlayer through Java framework, JNI and Native C. In this process, there are no data stream
flows. Then PVPlayer processes the media data stream with the following steps: demux the media
data to sperate video/audio data stream, decode video/audio data, sync video/audio
time, send the decoded data out.
The below is the description of media codec/format, container and networkprotocol supported
by Android platform:
A. Container: The audio file format is a file for storing digital audio data on a system. This data
can be manipulated to reduce the size or change the quality of the audio. It is a kind of
container to store audio information.
B. Audio Format: any format orcodec can be used including the ones provided by Android or
those which are specific to devices. However, it is recommended ot use the specified file
formats as per devices.
C. Network protocols: The following network protocols are supported for audio and video
playback:
• RTSP (RTP, SDP) - Real Time Streaming Protocol (Real-time Transport Protocol, Session
Description Protocol)
• HTTP/HTTPS progressive streaming
• HTTP/HTTPS live streaming draft protocol:
Manifest Declarations
Before starting development on your application using MediaPlayer, make sure your manifest
has the appropriate declarations to allow use of related features.
Internet Permission - If you are using MediaPlayer to stream network-based content, your
application must request network access.
<uses-permission android:name="android.permission.INTERNET" />
Wake Lock Permission - If your player application needs to keep the screen from dimming or
the processor from sleeping, or uses the MediaPlayer.setScreenOnWhilePlaying() or
MediaPlayer.setWakeMode() methods, you must request this permission.
<uses-permission android:name="android.permission.WAKE_LOCK" />
Using MediaPlayer
One of the most important components of the media framework is the MediaPlayer class. An
object of this class can fetch, decode, and play both audio and video with minimal setup. It
supports several different media sources such as:
• Local resources
• Internal URIs, such as one you might obtain from a Content Resolver
• External URLs (streaming)
Here is an example of how to play audio that's available as a local raw resource (saved in your
application's res/raw/ directory):
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you
In this case, a "raw" resource is a file that the system does not try to parse in any particular
way. However, the content of this resource should not be raw audio. It should be a properly
encoded and formatted media file in one of the supported formats.
And here is how you might play from a URI available locally in the system (that you obtained
through a Content Resolver, for instance):
Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();
Playing from a remote URL via HTTP streaming looks like this:
String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();
android:layout_alignBaseline="@+id/txtVw1"
android:text="TextView" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageButton
android:id="@+id/btnPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:src="@android:drawable/ic_media_play" />
<ImageButton
android:id="@+id/btnPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:src="@android:drawable/ic_media_pause" />
</LinearLayout>
</LinearLayout>
MainActivity.java
package com.jamiapolytechnic.mediaplayerexample;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.media.MediaPlayer;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playbtn = (ImageButton)findViewById(R.id.btnPlay);
pausebtn = (ImageButton)findViewById(R.id.btnPause);
fileName = (TextView)findViewById(R.id.txtSname);
fileName.setText("Ad-Duha");
mPlayer = MediaPlayer.create(this, R.raw.ad_duha);
playbtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Playing Audio",
Toast.LENGTH_SHORT).show();
mPlayer.start();
pausebtn.setEnabled(true);
playbtn.setEnabled(false);
}
});
pausebtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPlayer.pause();
pausebtn.setEnabled(false);
playbtn.setEnabled(true);
Toast.makeText(getApplicationContext(),"Pausing Audio",
Toast.LENGTH_SHORT).show();
}
});
}
}
OR
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Now Playing: " />
<TextView
android:id="@+id/txtfileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Now Playing: " />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Play"
android:onClick="playAudio"/>
<Button
android:id="@+id/btnPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pause"
android:onClick="pauseAudio"/>
<Button
android:id="@+id/btnStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop"
android:onClick="stopAudio"/>
</LinearLayout>
</LinearLayout>
MainActivity.java
package com.jamiapolytechnic.audioplayerex;
import androidx.appcompat.app.AppCompatActivity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
mp.start();
btnPlay.setEnabled(false);
btnPause.setEnabled(true);
}
public void pauseAudio(View v){
mp.pause();
btnPause.setEnabled(false);
btnPlay.setEnabled(true);
}
public void stopAudio(View v){
mp.stop();
mp.release();
mp = null;
System.exit(0);
}
}
Play Video
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<VideoView
android:id="@+id/vdVw"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
</RelativeLayout>
MainActivity.java
package com.jamiapolytechnic.videoplayerex;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.net.Uri;
import android.widget.MediaController;
import android.widget.VideoView;
Text To Speech
Android allows you convert your text into voice. Not only you can convert it but it also allows
you to speak text in variety of different languages.
Android provides TextToSpeech class for this purpose. In order to use this class, you need to
instantiate an object of this class and also specify the initListener. Its syntax is given below −
private EditText write;
ttobj=new TextToSpeech(getApplicationContext(), new
TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
}
});
In this listener, you have to specify the properties for TextToSpeech object , such as its
language, pitch e.t.c. Language can be set by calling setLanguage() method. Its syntax is given
below −
ttobj.setLanguage(Locale.US);
The method setLanguage takes an Locale object as parameter. The list of some of the locales
available are given below −
Sr.No Locale
1 US
2 CANADA_FRENCH
3 GERMANY
4 ITALY
5 JAPAN
6 CHINA
Once you have set the language, you can call speak method of the class to speak the text. Its
syntax is given below −
ttobj.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null);
Apart from the speak method, there are some other methods available in the TextToSpeech
class. They are listed below −
Example
The below example demonstrates the use of TextToSpeech class. It crates a basic application
that allows you to set write text and speak it.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView android:text="Text to Speech Example"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textview" />
<EditText
android:ems="20"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editText" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text to Speech"
android:id="@+id/button" />
</LinearLayout>
MainActivity.java
package com.jamiapolytechnic.ttsexample;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import java.util.Locale;
import android.widget.Toast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed1 = (EditText) findViewById(R.id.editText);
b1 = (Button) findViewById(R.id.button);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String toSpeak = ed1.getText().toString();
Toast.makeText(getApplicationContext(), toSpeak,
Toast.LENGTH_SHORT).show();
t1.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null);
}
});
}
Sensors
Most Android-powered devices have built-in sensors that measure motion, orientation, and
various environmental conditions. These sensors are capable of providing raw data with high
precision and accuracy, and are useful if you want to monitor three-dimensional device
movement or positioning, or you want to monitor changes in the ambient environment near a
device.
The Android platform supports three broad categories of sensors:
Motion sensors
These sensors measure acceleration forces and rotational forces along three axes. This category
includes accelerometers, gravity sensors, gyroscopes, and rotational vector sensors.
Environmental sensors
These sensors measure various environmental parameters, such as ambient air temperature
and pressure, illumination, and humidity. This category includes barometers, photometers, and
thermometers.
Position sensors
These sensors measure the physical position of a device. This category includes orientation
sensors and magnetometers.
You can access sensors available on the device and acquire raw sensor data by using the
Android sensor framework. The sensor framework provides several classes and interfaces that
help you perform a wide variety of sensor-related tasks. For example, you can use the sensor
framework to do the following:
• Determine which sensors are available on a device.
• Determine an individual sensor's capabilities, such as its maximum range, manufacturer,
power requirements, and resolution.
• Acquire raw sensor data and define the minimum rate at which you acquire sensor data.
• Register and unregister sensor event listeners that monitor sensor changes.
The Android sensor framework lets you access many types of sensors. Some of these sensors
are hardware-based and some are software-based. Hardware-based sensors are physical
components built into a handset or tablet device. Software-based sensors are not physical
devices, although they mimic hardware-based sensors. Software-based sensors derive their
data from one or more of the hardware-based sensors and are sometimes called virtual sensors
or synthetic sensors.
Common
Sensor Type Description
Uses
Monitoring
dewpoint,
Measures the relative ambient humidity in
TYPE_RELATIVE_HUMIDITY Hardware absolute, and
percent (%).
relative
humidity.
Motion
Software Measures the orientation of a device by
detection and
TYPE_ROTATION_VECTOR or providing the three elements of the
rotation
Hardware device's rotation vector.
detection.
Sensor Framework
You can access these sensors and acquire raw sensor data by using the Android sensor
framework. The sensor framework is part of the android.hardware package and includes the
following classes and interfaces:
SensorManager
You can use this class to create an instance of the sensor service. This class provides various
methods for accessing and listing sensors, registering and unregistering sensor event listeners,
and acquiring orientation information. This class also provides several sensor constants that are
used to report sensor accuracy, set data acquisition rates, and calibrate sensors.
Sensor
You can use this class to create an instance of a specific sensor. This class provides various
Next, you can get a listing of every sensor on a device by calling the getSensorList() method and
using the TYPE_ALL constant. For example:
List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
You can also determine whether a specific type of sensor exists on a device by using the
getDefaultSensor() method and passing in the type constant for a specific sensor. If a device has
more than one sensor of a given type, one of the sensors must be designated as the default
sensor. If a default sensor does not exist for a given type of sensor, the method call returns null,
which means the device does not have that type of sensor. For example, the following code
checks whether there's a magnetometer on a device:
private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
MainActivity.java
package com.jamiapolytechnic.sensorlist;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.view.View;
import android.widget.TextView;
import java.util.List;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mgr = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
txtList = (TextView)findViewById(R.id.sensorslist);
List<Sensor> sensorList = mgr.getSensorList(Sensor.TYPE_ALL);
StringBuilder strBuilder = new StringBuilder();
for(Sensor s: sensorList){
strBuilder.append(s.getName()+"\n");
}
txtList.setVisibility(View.VISIBLE);
txtList.setText(strBuilder);
}
}
Async Task
In Android, AsyncTask (Asynchronous Task) allows us to run the instruction in the background
and then synchronize again with our main thread. This class will override at least one method i.e
doInBackground(Params) and most often will override second method onPostExecute(Result).
AsyncTask class is used to do background operations that will update the UI(user interface).
Mainly we use it for short operations that will not effect on our main thread.
AsyncTask class is firstly executed using execute() method. In the first step AsyncTask is called
onPreExecute() then onPreExecute() calls doInBackground() for background processes and then
doInBackground() calls onPostExecute() method to update the UI.
Rules of AsyncTask:
There are a few threading rules that must be followed for this class to work properly:
1. This class must be loaded on the UI thread. This is done automatically as from JELLY_BEAN.
2. The task instance must be created on the UI thread.
3. execute(Params…) method that executes it, must be invoked on the UI thread.
4. Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params…),
onProgressUpdate(Progress…) manually, just executes the class and then will call automatically
for good user experience.
Audio Capture:
Android has a built in microphone through which you can capture audio and store it , or play it in
your phone. There are many ways to do that but the most common way is through
MediaRecorder class.
Android provides MediaRecorder class to record audio or video. In order to use MediaRecorder
class ,you will first create an instance of MediaRecorder class. Its syntax is given below.
MediaRecorder myAudioRecorder = new MediaRecorder();
Now you will set the source , output and encoding format and output file. Their syntax is given
below.
myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myAudioRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myAudioRecorder.setOutputFile(outputFile);
After specifying the audio source and format and its output file, we can then call the two basic
methods prepare and start to start recording the audio.
myAudioRecorder.prepare();
myAudioRecorder.start();
Apart from these methods , there are other methods listed in the MediaRecorder class that
allows you more control over audio and video recording.
Sr.No. Method & description
1 setAudioSource()
Camera:
These are the following two ways, in which you can use camera in your application
Now you will use the function startActivityForResult() to launch this activity and wait for its
result. Its syntax is given below:
startActivityForResult(intent,0)
This method has been defined in the activity class. We are calling it from main activity. There
are methods defined in the activity class that does the same job , but used when you are not
calling from the activity but from somewhere else. They are listed below:
No matter which function you used to launch the activity , they all return the result. The result
can be obtained by overriding the function onActivityResult.
Bluetooth
Among many ways, Bluetooth is a way to send or receive data between two different devices.
Android platform includes support for the Bluetooth framework that allows a device to wirelessly
exchange data with other Bluetooth devices.
Android provides Bluetooth API to perform these different operations.
• Scan for other Bluetooth devices
• Get a list of paired devices
• Connect to other devices through service discovery
Android provides BluetoothAdapter class to communicate with Bluetooth. Create an object of
this calling by calling the static method getDefaultAdapter(). Its syntax is given below:
private BluetoothAdapter BA;
BA = BluetoothAdapter.getDefaultAdapter();
In order to enable the Bluetooth of your device, call the intent with the following Bluetooth
constant ACTION_REQUEST_ENABLE. Its syntax is:
Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOn, 0);
Apart from this constant, there are other constants provided the API , that supports different
tasks. They are listed below.
Once you enable the Bluetooth , you can get a list of paired devices by calling getBondedDevices()
method. It returns a set of bluetooth devices. Its syntax is:
private Set<BluetoothDevice>pairedDevices;
pairedDevices = BA.getBondedDevices();
Apart form the parried devices , there are other methods in the API that gives more control over
Blueetooth. They are listed below:
Sr.No. Method & description
1 enable()
This method enables the adapter if not enabled
2 isEnabled()
This method returns true if adapter is enabled
3 disable()
This method disables the adapter
4 getName()
This method returns the name of the Bluetooth adapter
5 setName(String name)
This method changes the Bluetooth name
6 getState()
This method returns the current state of the Bluetooth Adapter.
7 startDiscovery()
This method starts the discovery process of the Bluetooth for 120 seconds.
Create a new android application using android studio and give names as
BluetoothListPairedDevicesExample.
Once we create an application, open activity_main.xml file from \res\layout folder path and write
the code like as shown below:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnGet"
android:text="Get Paired Devices"
android:layout_marginLeft="130dp"
android:layout_marginTop="200dp" />
<ListView
android:id="@+id/deviceList"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Set;
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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Animation
“Animation is the process of creating motion and shape change”
Animation in android is possible from many ways. We will discuss one easy and widely used
way of making animation called tweened animation. We have four kinds tween animation:
Alpha (fade), Rotate, Translate, Scale (zoom).
Tween Animation
Tween Animation takes some parameters such as start value , end value, size , time duration ,
rotation angle etc. and perform the required animation on that object. It can be applied to any
type of object. So in order to use this , android has provided us a class called Animation.
In order to perform animation in android , we are going to call a static function loadAnimation()
of the class AnimationUtils. We are going to receive the result in an instance of Animation
Object. Its syntax is as follows −
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.myanimation);
Note the second parameter. It is the name of the our animation xml file. You have to create a
new folder called anim under res directory and make an xml file under anim folder.
This animation class has many useful functions which are listed below −
1 start()
This method starts the animation.
2 setDuration(long duration)
This method sets the duration of an animation.
3 getDuration()
This method gets the duration which is set by above method
4 end()
This method ends the animation.
5 cancel()
This method cancels the animation.
In order to apply this animation to an object , we will just call the startAnimation() method of
the object. Its syntax is −
ImageView image1 = (ImageView)findViewById(R.id.imageView1);
image.startAnimation(animation);
The following are some of the important animation attributes that will help us to change the
behavior of animation in our application.
Attributes Description
android:duration It is used to define the duration of the animation to complete.
android:startOffset It is used to define the waiting time before the animation starts.
android:interpolator It is used to define the rate of change in animation.
android:repeatMode It is useful when we want to repeat our animation.
android:repeatCount It is used to define the number of times the animation repeats. In case if
we set infinite, the animation will repeat infinite times.
android:fillAfter It is used to define whether to apply animation transformation after the
animation completes or not.
In android, we have different types of animations such as Fade In / Fade Out, Zoom In / Zoom
Out, Slide Up / Slide Down, Rotate in Clockwise or Anti-Clockwise, etc.
Now we will see how to create each animation with required properties in the android
application.
Android Fade In / Out Animation
To use Fade In or Fade Out animations in our android applications, we need to define a new
XML file with <alpha> tag like as shown below.
For Fade In animation, we need to increase the alpha value from 0 to 1 like as shown below.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator">
<alpha
android:duration="2000"
android:fromAlpha="0.1"
android:toAlpha="1.0">
</alpha>
</set>
For Fade Out animation, we need to decrease the alpha value from 1 to 0 like as shown below.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator">
<alpha
android:duration="2000"
android:fromAlpha="1.0"
android:toAlpha="0.1" >
</alpha>
</set>
android:duration="500"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="1.0"
android:toYScale="0.0" />
</set>
In android, Zoom Out animation is same as Zoom In animation but fromXScale, fromYScale
attribute values must be greater than toXScale, toYScale like as shown below.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="2500"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale=".2"
android:toYScale=".2" />
</set>
SQLite Database
SQLite is a opensource SQL database that stores data to a text file on a device. Android comes
in with built in SQLite database implementation.
SQLite supports all the relational database features. In order to access this database, you don't
need to establish any kind of connections for it like JDBC,ODBC etc.
Necessity of SQLite
Serverless: SQLite does not require a server process or system to run
Zero-configuration: SQLite does not require any setup or administration. SQLite uses no
configuration files,
Cross-platform: The SQLite file format is cross-platform. A database file written on one machine
can be copied to and used on a different machine with a different architecture. Big-endian or
little-endian, 32-bit or 64-bit does not matter.
Less-memory (Compact): When optimized for size, the whole SQLite library with everything
enabled is less than 500KiB in size. Unneeded features can be disabled at compile-time to
further reduce the size of the library to under 300KiB if desired.
Self-Contained: SQLite has no external dependencies.
Transactional: All transactions in SQLite are fully ACID-compliant. It means all queries and
changes are Atomic, Consistent, Isolated, and Durable.
In other words, all changes within a transaction take place completely or not at all even when
an unexpected situation like application crash, power failure, or operating system crash occurs.
Single Database File: An SQLite database is a single ordinary disk file that can be located
anywhere in the directory hierarchy. If SQLite can read the disk file then it can read anything in
the database. If the disk file and its directory are writable, then SQLite can change anything in
the database. Database files can easily be copied onto a USB memory stick or emailed for
sharing.
Database - Insertion
we can create table or insert data into table using execSQL method defined in SQLiteDatabase
class. Its syntax is given below
mydatabase.execSQL("CREATE TABLE IF NOT EXISTS USERS(Username
VARCHAR,Password VARCHAR);");
mydatabase.execSQL("INSERT INTO USERS VALUES('admin','admin');");
This will insert some values into our table in our database.
Another way to insert values is by using ContentValues class instance. Its put() method can be
used to hold values. Later insert() method of SQLiteDatabase class can be called to insert values
in the table.
The syntax of put() is as follows:
public void put (String key, String value)
where
key is String: the name of the value (table column name) to put
value is String: the data for the value (table column name) to put i.e. value for column
Note: Second parameter data type will be changed according to column values e.g.
Short, Long, Double, Integer, Float, Boolean, Byte
The syntax of insert is as follows:
public long insert (String table, String nullColumnHack, ContentValues values)
where
table is String: the table name into which row will be inserted
nullColumnHack is String: optional; may be null
values is an object of ContentValues
e.g.
Database - Fetching
We can retrieve anything from database using an object of the Cursor class. We will call a
method of this class called rawQuery and it will return a resultset with the cursor pointing to
the table. We can move the cursor forward and retrieve the data.
Cursor resultSet = mydatbase.rawQuery("Select * from USERS",null);
resultSet.moveToFirst();
String username = resultSet.getString(0);
String password = resultSet.getString(1);
There are other functions available in the Cursor class that allows us to effectively retrieve the
data. That includes
5 getCount()
This method returns the total number of rows in the cursor
6 getPosition()
This method returns the current position of the cursor in the table
7 isClosed()
This method returns true if the cursor is closed and return false otherwise
Android SQLiteOpenHelper
Android has features available to handle changing database schemas, which mostly depend on
using the SQLiteOpenHelper class.
SQLiteOpenHelper is designed to get rid of two very common problems.
1. When the application runs the first time – At this point, we do not yet have a database. So
we will have to create the tables, indexes, starter data, and so on.
2. When the application is upgraded to a newer schema – Our database will still be on the old
schema from the older edition of the app. We will have option to alter the database schema to
match the needs of the rest of the app.
SQLiteOpenHelper wraps up these logic to create and upgrade a database as per our
specifications. For that we’ll need to create a custom subclass of SQLiteOpenHelper
implementing at least the following three methods.
• Constructor
• onCreate(SQLiteDatabase db)
• onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
• Cursors should be closed when no longer used, and can be deactivated with a call to
Cursor.deactivate() statement when the application pauses or exits.
• On resume the Cursor.requery() statement is executed to re-enable the Cursor with
fresh data. These functions can be managed by the parent Activity by calling
startManagingCursor().
The getXxx(int columnIndex) methods can be used to get the value of requested column index.
e.g.
abstract float getFloat(int columnIndex)
Returns the value of the requested column as a float.
abstract int getInt(int columnIndex)
Returns the value of the requested column as an int.
abstract long getLong(int columnIndex)
and so on for each supported data type.
Transactions
When we want to execute a series of queries that either all complete or all fail, at that situation
we use transactions which is supported by SQLite.
When a SQLite transaction fails, an exception will be thrown.
There are three methods available in transaction for all part of the database object.
a. beginTransaction(): Start a transaction
b. setTransactionSuccessful(): Execute the queries and call we want to commit the transaction
c. endTransaction(): Complete the transaction
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
addButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Intent addIntent = new Intent(MainActivity.this,
AddStudentActivity.class);
startActivity(addIntent);
}
});
showButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Intent showIntent = new Intent(MainActivity.this,
ShowStudentActivity.class);
startActivity(showIntent);
}
});
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp" >
<Button
android:id="@+id/add_record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Add Record" />
<Button
android:id="@+id/show_record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Show Record" />
</LinearLayout>
AddStudentActivity.java
This activity displays two edit text views to accept two values from user, it has one button to
save data. Its layout file is add_layout.xml.
package com.jamiapolytechnic.databaseexample;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Add Record");
setContentView(R.layout.add_layout);
nameEditText = findViewById(R.id.name_edittext);
yearEditText = findViewById(R.id.year_edittext);
saveButton = findViewById(R.id.save_record);
}
dbManager.insert(sname, syear);
Toast.makeText(getApplicationContext(),"Record
Saved",Toast.LENGTH_SHORT).show();
nameEditText.setText("");
yearEditText.setText("");
}
});
}
@Override
protected void onStop(){
super.onStop();
dbManager.close();
}
add_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp" >
<EditText
android:id="@+id/name_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Enter Name" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/year_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Enter Year e.g. FYCO" >
</EditText>
<Button
android:id="@+id/save_record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Save" />
</LinearLayout>
ShowStudentActivity.java
This activity displays one text view to display the data from table. Its layout file is
show_layout.xml.
package com.jamiapolytechnic.databaseexample;
import androidx.appcompat.app.AppCompatActivity;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.TextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Show Record");
setContentView(R.layout.show_layout);
tv = (TextView) findViewById(R.id.empty);
show_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical">
<TextView
android:id="@+id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No Records" />
</ScrollView>
</LinearLayout>
DatabaseHelper.java
This is sub-class of SQLiteOpenHelper, used to create database and table.
package com.jamiapolytechnic.databaseexample;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
DBManager.java
This class is used to insert the record in database table and create a Cursor to retrieve data
from database table.
package com.jamiapolytechnic.databaseexample;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
public DBManager(Context c) {
context = c;
}
AndroidManifest.xml
In this file, add the details of two more activities created i.e. AddStudentActivity and
ShowStudentActivity.
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest>