Activities

advertisement
PROGRAMMING
IN ANDROID
IOANNIS (JOHN) PAPAVASILEIOU
MARCH 31 2014
1
papabasile@engr.uconn.edu
WHAT IS IT
• Software
platform
• Operating system
• Key apps
• Developers:
• Google
• Open Handset
Alliance
2
• Open Source
(http://source.an
droid.com/)
SOFTWARE STACK
DESIGN
• Android ≠ Linux!!!
• The kernel is based on Linux kernel
version 3.x (source Wikipedia)
• Written in C/C++
• Apps written in Java
3
• Use of Dalvik VM
• Runs .dex files (dalvic executables)
API CAPABILITIES
• Rich UI components
• Threads and Background processing
• Full network stack (Http, JSON)
• Database and file system access
• Access to hardware (Camera, Phone, GPS, sensors..)
4
• Plenty of libraries and services
Many of the APIs
provided map 1:1 to
the underlying HAL
crossing of process
boundaries & call of
system services
code
Includes window and
notification managers
Media services for
playing and
Interface that allows
recording media
the Android system
Kernel,
includes
to call device
drivers
device drivers and
memory
management
Source:
http://source.android.com/devices/im
ages/system-architecture.png
5
LOW LEVEL ARCHITECTURE
APPLICATION
COMPONENTS
Every app may have:
•
Activities
•
• A single screen with a UI. E.g. compose, read, list e-mails
Services
•
•
Run in the background to perform long-running operations. E.g. play
music, fetch data over the network
Content Providers
•
•
Manage a shared set of app data. Other apps can query or modify
the data. E.g. contacts
Broadcast Receivers
•
Respond to a system-wide broadcast announcement. E.g. screen
turned off, low-battery. May initiate services or notifications
Intents
•
Processes and threads
6
•
APP FUNDAMENTALS
Every app lives in its own security sandbox:
• Every app runs its own Linux process
• Each process has it’s own Java VM
• UI thread (managed by the system)
• Worker threads
Violates the rule: “do
not access the Android
UI toolkit from outside
the UI”
Will run on the UI thread
public
public void
void onClick(View
onClick(View v)
v) {{
new
Thread(new
Runnable()
new Thread(new Runnable() {{
public
public void
void run()
run() {{
final
Bitmap
bitmap = loadImageFromNetwork("http://example.com/image.png");
Bitmap b = loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new
Runnable() {
mImageView.setImageBitmap(b);
public void run() {
}
mImageView.setImageBitmap(bitmap);
}).start();
}
}
});
}
}).start();
}
http://developer.android.com/guide/components/fundame
ntals.html
7
Every process can have multiple threads:
ACTIVITIES
• The basis of android applications
• A viewable screen
• the actions, not the layout
• Can have multiple per application
• Each is a separate entity
• They have a structured life cycle
8
• Different events in their life happen either via the user
touching buttons or programmatically
ACTIVITY
LIFECYCLE
The system can
drop the activity
from memory by just
killing the process
9
It might not reach
this point!
ACTIVITY RESTART
• When there is a configuration change the app will be restarted
by the system
• Screen orientation
• keyboard availability
• Language
• Etc.
• To save the state of the Activity the developer has to use the
onSaveInstanceState() method.
• onPause() is guaranteed to be called in any case
10
• onCreate() or onRestoreInstancestate() will give you access to
the restored state
• We can prevent the restart of the activity by handling the
configuration change manually
SERVICES
• Started
• Can continue even if Activity that started it dies
• Something needs to be done while the user is not interacting
with application
• Otherwise, a thread is probably more applicable
• Bound
• Multiple activities can bind to it
• Allows multiple applications to communicate with it via a
common interface
• Client-server interface
• Needs to be declared in manifest file
11
• Like Activities, has a structured life cycle
SERVICES
LIFECYCLE
One component
calls stopService()
or service calls
To
stop it calls
stopSelf()
unbindService(),
Multiple clients can
bind to the same
service
12
One component
calls startService()
One component
calls bindService(),
It can communicate
with the Ibinder
interface
CONTENT PROVIDERS
• Encaptulate data  provide data security
• Share data between processes
• Android has providers for
Audio
Video
Images
Contact information
13
•
•
•
•
PROJECT
COMPONENTS
• src – your source code
• gen – auto-generated code (usually just R.java)
• Included libraries
• Resources
• Drawables (like .png images)
• Layouts (define the UI)
• Values (like strings)
14
• Manifest file
AndroidManifest.Xml
Configuration file for your application
•
Permissions required from the app:
•
E.g. access contacts, internet, vibration,
camera, phone history, DB access
Contains characteristics about your application
•
• Activities
• Services
• Content providers
• Broadcast receivers
Defines external libraries, like Google Maps API
15
•
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=http://schemas.android.com/apk/res/android
package="com.abimed.ecg“
android:versionCode="5“
android:versionName="1.2.2">
<uses-sdk android:minSdkVersion="8"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application android:label="@string/app_name“
android:icon="@drawable/logo“
android:debuggable="false">
<uses-library android:name="com.google.android.maps"/>
<activity
android:name="com.abimed.ecg.EcgActivity“ android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name="com.abimed.ecg.Preferences" android:label="@string/set_preferences"/>
<activity
android:name="com.abimed.ecg.About"
android:label="@string/aboutActivity"/>
<activity
android:name="com.abimed.ecg.Report"
android:label="@string/reportActivity"/>
<activity
android:name="com.abimed.ecg.GraphInfo" android:label="@string/graphInfoActivity"/>
<activity
android:name=".patients.Patients"
android:label="@string/patients"/>
<activity
android:name=".patients.ViewPatient"
android:label="@string/patient"/>
<activity
android:name=".patients.PatientInfo"
android:theme="@android:style/Theme.NoTitleBar"/>
<activity
android:name=".patients.PatientEdit"
android:theme="@android:style/Theme.NoTitleBar"/>
</application>
</manifest>
16
MANIFEST FILE
EXAMPLE
STRINGS.XML
Nice way to localize apps:
• res/values/strings.xml
• res/values-en/strings.xml
• res/values-fr/strings.xml
• res/values-ja/strings.xml
Application wide available strings
Promotes good software engineering
UI components made in the UI editor should have text
defined in strings.xml
17
Strings are just one kind of ‘Value’ there are many others
TOOLS TO DEVELOP
• Phone or a Virtual Device
• Android Studio
(http://developer.android.com/sdk/installing/studio.html)
Provides:
18
• Development environment (based on IntelliJ IDEA)
• SDK
• Virtual devices
http://developer.android.com/training/basics/firstapp/buildi
ng-ui.html
19
HELLO WORLD
LAYOUTS
• Declare UI elements in XML
• Separates presentation from actual code
• Visualize  easy to debug
• Almost Every Development Environment has nice Drag n
Drop editor
• Instantiate layout elements at runtime (through Java code)
• Fast and easy when the layout is simple:
Has a few View elements
Has only a surface vew like GLSurfaceView
20
•
•
R CLASS
• Auto-generated: you shouldn’t edit it
• Pairs Layout files with Activities
• Use findViewById and Resources object to get access to the
resources
21
• Ex. Button buttonInfo = (Button)findViewById(R.id.buttonInfo);
buttonInfo.setOnClickListener(buttonInfoClickListener);
• Ex. helloStr = getResources().getString(R.string.hello));
R CLASS
R.java
Layout.xml
22
Activity.java
HELLO WORLD
LAYOUT
23
<!-- mainLayout.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">
Only one root
<EditText android:id="@+id/edit_message"
android:layout_weight="1"
element
android:layout_width="0dp"
android:layout_height="wrap_content"
Additional elements
android:hint=“Enter a message" />
<Button
as children
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=“Send “
android:onClick="sendMessage" />
</LinearLayout>
MAIN ACTIVITY
public class MainActivity extends Activity {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainLayout);
// Make sure we're running on Honeycomb or higher to use ActionBar APIs
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// Show the Up button in the action bar.
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
24
}
DISPLAY MESSAGE
ACTIVITY
public class DisplayMessageActivity extends Activity {
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the message from the intent
Intent intent = getIntent();
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
// Create the text view
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(message);
// Set the text view as the activity layout
setContentView(textView);
}
25
}
INTENTS
• Start new activity
• Send user to another App:
Implicit intent:
•
•
Uri number = Uri.parse("tel:5551234");
Intent intent = new Intent(Intent.ACTION_DIAL, number);
Uri location =
Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountai
n+View,+California");
intent = new Intent(Intent.ACTION_VIEW, location);
•
• startActivity(intent);
Start a service
•
• Perform an operation in the background
Deliver a broadcast
•
Something happened that other apps need to know
http://developer.android.com/training/basics/intents/sendi
ng.html
26
•
When multiple
apps can handle
the intent
APP CHOOSER
Intent intent = new Intent(Intent.ACTION_SEND);
...
27
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create and start the chooser
Intent chooser = Intent.createChooser(intent, title);
startActivity(chooser);
28
STORAGE OPTIONS..
SHARED
PREFERENCES
•
•
Store key-value sets
Good for small sets
public class Calc extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";
@Override
protected void onCreate(Bundle state){
super.onCreate(state);
...
// Restore preferences
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
setSilent(silent);
}
@Override
protected void onStop(){
super.onStop();
// Commit the edits!
editor.commit();
}
}http://developer.android.com/guide/topics/data/datastorage.html
29
// We need an Editor object to make preference changes.
// All objects are from android.context.Context
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", mSilentMode);
FILE STORAGE
Internal
External
•
Always available
•
•
Files accesible only •
by the app
•
When the app is
uninstalled, files
are deleted
http://developer.android.com/guide/topics/data/datastorage.html
World-readable
When app is
uninstalled, files will
be deleted if the
directory is gotten
from
getExternalFilesDir()
30
•
Not always available
INTERNAL STORAGE
String FILENAME = “myfile.txt";
String string = "hello world!";
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
http://developer.android.com/guide/topics/data/datastorage.html
31
• When there is a need to cache some files use method:
File createTempFile (String prefix, String suffix)
EXTERNAL STORAGE
<manifest ... >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
...
</manifest>
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)
){
return true;
}
return false;
}
http://developer.android.com/guide/topics/data/datastorage.html
public File getAlbumStorageDir(Context context, String
albumName) {
// Get the directory for the app's private pictures
directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES),
albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
32
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
CREATE DATABASE
public class DictionaryOpenHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DICTIONARY_TABLE_NAME = "dictionary";
private static final String DICTIONARY_TABLE_CREATE =
"CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +
KEY_WORD + " TEXT, " +
KEY_DEFINITION + " TEXT);";
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DICTIONARY_TABLE_CREATE);
}
}
33
DictionaryOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
PUT INFO INTO THE
DATABASE
/ Gets the data repository in write mode
SQLiteDatabase db = mDbHelper.getWritableDatabase();
// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_CONTENT, content);
34
// Insert the new row, returning the primary key value of the new
row
long newRowId;
newRowId = db.insert(
FeedEntry.TABLE_NAME,
FeedEntry.COLUMN_NAME_NULLABLE,
values);
SENSORS
• Types:
• Motion sensors
• Environmental sensors
• Position sensors
• Sensor Framework:
Get available sensors
Get sensor capabilities
Acquire raw data for a given minimum rate
Register for sensor event listeners
http://developer.android.com/guide/topics/sensors/sensor
s_overview.html
35
•
•
•
•
MAGNETOMETER
AVAILABILITY CHECK
36
private SensorManager mSensorManager;
...
mSensorManager = (SensorManager)
getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
// Success! There's a magnetometer.
}
else {
// Failure! No magnetometer.
}
GET DATA EVENTS FROM
THE LIGHT SENSOR
public class SensorActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mLight;
@Override
public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
}
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
}
@Override
public final void onSensorChanged(SensorEvent event) {
// The light sensor returns a single value.
// Many sensors return 3 values, one for each axis.
float lux = event.values[0];
// Do something with this sensor value.
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
}
37
@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
}
CONNECTIVITY
Several APIs to let the app connect and interact with other
devices:
• Bluetooth
• NFC
• Wi-Fi P2P
• USB
http://developer.android.com/guide/topics/connectivity/ind
ex.html
38
• SIP
CHECK NETWORK
CONNECTIVITY
private void checkNetworkConnection() {
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
if (activeInfo != null && activeInfo.isConnected()) {
wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
mobileConnected=activeInfo.getType()==ConnectivityManager.TYPE_MOBILE;
if(wifiConnected) {
Log.i(TAG, "Wifi connection");
}
else if (mobileConnected){
Log.i(TAG, "Mobile connection");
}
} else {
Log.i(TAG, "Not connected");
}
39
}
USER LOCATION
<manifest ... >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
...
</manifest>
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager)
this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
locationListener);
http://developer.android.com/guide/topics/location/strategi
es.html
40
public void onProviderDisabled(String provider) {}
};
TOAST
Context context =
getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
http://developer.android.com/guide/topics/ui/notifiers/toast
s.html
41
Toast toast = Toast.makeText(context,
text, duration);
toast.show();
SEND SMS
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnSendSMS = (Button) findViewById(R.id.btnSendSMS);
txtPhoneNo = (EditText) findViewById(R.id.txtPhoneNo);
txtMessage = (EditText) findViewById(R.id.txtMessage);
btnSendSMS.setOnClickListener(new View.OnClickListener() {
public void Onclick(View v) {
String phoneNo = txtPhoneNo.getText().toString();
String message = txtMessage.getText().toString();
if (phoneNo.length()>0 && message.length()>0)
sendSMS(phoneNo, message);
else
Toast.makeText(getBaseContext(), "Please enter both phone number and
message.",Toast.LENGTH_SHORT).show();
}});
}
http://developer.android.com/reference/android/telephony/
SmsManager.html
42
<manifest ... >
<uses-permission android:name="android.permission.SEND_SMS"/>
...
</manifest>
SEND SMS
private void sendSMS(String phoneNumber, String message) {
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, null, null);
43
}
GOOGLE LOCATION
SERVICES
•
Fused location provider:
•
• Gives the bests location according to the needs
• “high accuracy”, “low power”, etc.
Geofencing APIs:
•
•
•
•
•
•
•
In a vehicle
On a bicycle
On foot
Still
Tilting
Unknown
http://developer.android.com/reference/android/telephony/
SmsManager.html
44
•
App will receive notifications when the user enters specific
geographic boundaries
Activity recognition:
45
MY APP
46
THANKS!
Download