470 likes | 676 Views
Programming in android. Ioannis (John) Papavasileiou March 31 2014 papabasile@engr.uconn.edu. What is it. Software platform Operating system Key apps Developers: Google Open Handset Alliance Open Source ( http ://source.android.com / ). Software stack design. Android ≠ Linux!!!
E N D
Programming in android Ioannis (John) Papavasileiou March 31 2014 papabasile@engr.uconn.edu
What is it • Software platform • Operating system • Key apps • Developers: • Google • Open Handset Alliance • Open Source (http://source.android.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 • Use of Dalvik VM • Runs .dex files (dalvicexecutables)
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..) • 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 recording media Interface that allows the Android system to call device drivers Kernel, includes device drivers and memory management low level architecture Source: http://source.android.com/devices/images/system-architecture.png
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
App fundamentals Will run on the UI thread Violates the rule: “do not access the Android UI toolkit from outside the UI” • Every app lives in its own security sandbox: • Every app runs its own Linux process • Each process has it’s own Java VM • Every process can have multiple threads: • UI thread (managed by the system) • Worker threads publicvoidonClick(View v){newThread(newRunnable(){publicvoid run(){finalBitmapbitmap=loadImageFromNetwork("http://example.com/image.png");mImageView.post(newRunnable(){publicvoid run(){mImageView.setImageBitmap(bitmap);}});}}).start();} publicvoidonClick(View v){newThread(newRunnable(){publicvoid run(){Bitmap b =loadImageFromNetwork("http://example.com/image.png");mImageView.setImageBitmap(b);}}).start();} http://developer.android.com/guide/components/fundamentals.html
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 • Different events in their life happen either via the user touching buttons or programmatically
Activitylifecycle The system can drop the activity from memory by just killing the process 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. • onCreate() oronRestoreInstancestate() will give you access to the restored state • We can prevent the restart of the activity by handling the configuration change manually • onPause() is guaranteed to be called in any case
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 • Like Activities, has a structured life cycle
Serviceslifecycle One component calls startService() One component calls stopService() or service calls stopSelf() One component calls bindService(), It can communicate with the Ibinderinterface To stop it calls unbindService(), Multiple clients can bind to the same service
Content providers • Encaptulate data provide data security • Share data between processes • Android has providers for • Audio • Video • Images • Contact information
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) 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
Manifest file example • <?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-sdkandroid: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>
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 • 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: • Development environment (based on IntelliJ IDEA) • SDK • Virtual devices
Hello world http://developer.android.com/training/basics/firstapp/building-ui.html
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 vewlike GLSurfaceView
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 • Ex. ButtonbuttonInfo = (Button)findViewById(R.id.buttonInfo); buttonInfo.setOnClickListener(buttonInfoClickListener); • Ex. helloStr = getResources().getString(R.string.hello));
Hello world layout Only one root element Additional elements as children • <!-- mainLayout.xml - -> • <?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns: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"><EditTextandroid:id="@+id/edit_message"android:layout_weight="1"android:layout_width="0dp"android:layout_height="wrap_content"android:hint=“Enter a message"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text=“Send “ • android:onClick="sendMessage"/></LinearLayout>
Main activity • publicclassMainActivityextendsActivity{publicfinalstaticString EXTRA_MESSAGE ="com.example.myfirstapp.MESSAGE"; • @Override protectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.mainLayout);// Make sure we're running on Honeycomb or higher to use ActionBar APIsif(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 */publicvoidsendMessage(View view){Intentintent=newIntent(this,DisplayMessageActivity.class);EditTexteditText=(EditText)findViewById(R.id.edit_message);Stringmessage =editText.getText().toString();intent.putExtra(EXTRA_MESSAGE, message);startActivity(intent);}}
Display message activity • publicclassDisplayMessageActivityextendsActivity{@SuppressLint("NewApi")@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);// Get the message from the intentIntentintent=getIntent();String message =intent.getStringExtra(MainActivity.EXTRA_MESSAGE);// Create the text viewTextViewtextView=newTextView(this);textView.setTextSize(40);textView.setText(message);// Set the text view as the activity layoutsetContentView(textView); • } • }
intents When multiple apps can handle the intent • Start new activity • Send user to another App: • Implicit intent: • Urinumber =Uri.parse("tel:5551234");Intentintent=newIntent(Intent.ACTION_DIAL, number); • Urilocation =Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");intent =newIntent(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/sending.html
App chooser • Intentintent=newIntent(Intent.ACTION_SEND);...// 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 chooserIntent chooser =Intent.createChooser(intent, title);startActivity(chooser);
Shared preferences • Store key-value sets • Good for small sets • publicclassCalcextendsActivity{publicstaticfinalString PREFS_NAME ="MyPrefsFile";@OverrideprotectedvoidonCreate(Bundle state){super.onCreate(state);...// Restore preferencesSharedPreferences settings =getSharedPreferences(PREFS_NAME,0);boolean silent =settings.getBoolean("silentMode",false);setSilent(silent);}@OverrideprotectedvoidonStop(){super.onStop();// We need an Editor object to make preference changes.// All objects are from android.context.ContextSharedPreferences settings =getSharedPreferences(PREFS_NAME,0);SharedPreferences.Editor editor =settings.edit();editor.putBoolean("silentMode",mSilentMode);// Commit the edits!editor.commit();}} http://developer.android.com/guide/topics/data/data-storage.html
File storage • Internal • Always available • Files accesible only by the app • When the app is uninstalled, files are deleted • External • Not always available • World-readable • When app is uninstalled, files will be deleted if the directory is gotten from getExternalFilesDir() http://developer.android.com/guide/topics/data/data-storage.html
Internal storage • StringFILENAME =“myfile.txt";Stringstring="hello world!";FileOutputStreamfos=openFileOutput(FILENAME,Context.MODE_PRIVATE);fos.write(string.getBytes());fos.close(); • When there is a need to cache some files use method: FilecreateTempFile(String prefix, String suffix) http://developer.android.com/guide/topics/data/data-storage.html
External storage • <manifest... ><uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/> • ...</manifest> publicFilegetAlbumStorageDir(Contextcontext,StringalbumName){// Get the directory for the app's private pictures directory. Filefile=newFile(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),albumName);if(!file.mkdirs()){Log.e(LOG_TAG,"Directory not created");}return file;} /* Checks if external storage is available for read and write */publicbooleanisExternalStorageWritable(){String state =Environment.getExternalStorageState();if(Environment.MEDIA_MOUNTED.equals(state)){returntrue;}returnfalse;}/* Checks if external storage is available to at least read */publicbooleanisExternalStorageReadable(){String state =Environment.getExternalStorageState();if(Environment.MEDIA_MOUNTED.equals(state)||Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){returntrue;}returnfalse;} http://developer.android.com/guide/topics/data/data-storage.html
Create database • publicclassDictionaryOpenHelperextendsSQLiteOpenHelper{privatestaticfinalint DATABASE_VERSION =2;privatestaticfinalString DICTIONARY_TABLE_NAME ="dictionary";privatestaticfinalString DICTIONARY_TABLE_CREATE ="CREATE TABLE "+ DICTIONARY_TABLE_NAME +" ("+ KEY_WORD +" TEXT, "+ KEY_DEFINITION +" TEXT);";DictionaryOpenHelper(Context context){super(context, DATABASE_NAME,null, DATABASE_VERSION);}@OverridepublicvoidonCreate(SQLiteDatabasedb){db.execSQL(DICTIONARY_TABLE_CREATE);}}
Put info into the database • / Gets the data repository in write modeSQLiteDatabasedb=mDbHelper.getWritableDatabase();// Create a new map of values, where column names are the keysContentValues values =newContentValues();values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);values.put(FeedEntry.COLUMN_NAME_TITLE, title);values.put(FeedEntry.COLUMN_NAME_CONTENT, content);// Insert the new row, returning the primary key value of the new rowlongnewRowId;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/sensors_overview.html
Magnetometer availability check • privateSensorManagermSensorManager;...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 • publicclassSensorActivityextendsActivityimplementsSensorEventListener{privateSensorManagermSensorManager;privateSensormLight;@OverridepublicfinalvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);mSensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);mLight=mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);}@OverridepublicfinalvoidonAccuracyChanged(Sensorsensor,int accuracy){// Do something here if sensor accuracy changes.}@OverridepublicfinalvoidonSensorChanged(SensorEventevent){// 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.}@OverrideprotectedvoidonResume(){super.onResume();mSensorManager.registerListener(this,mLight,SensorManager.SENSOR_DELAY_NORMAL);}@OverrideprotectedvoidonPause(){super.onPause();mSensorManager.unregisterListener(this);}}
connectivity • Several APIs to let the app connect and interact with other devices: • Bluetooth • NFC • Wi-Fi P2P • USB • SIP http://developer.android.com/guide/topics/connectivity/index.html
Check network connectivity • privatevoidcheckNetworkConnection(){ ConnectivityManagerconnMgr=(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfoactiveInfo=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"); } elseif(mobileConnected){ Log.i(TAG,"Mobile connection"); } }else{ Log.i(TAG,"Not connected"); } • }
User location • <manifest ... ><uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/> ...</manifest> • // Acquire a reference to the system Location ManagerLocationManagerlocationManager=(LocationManager)this.getSystemService(Context.LOCATION_SERVICE);// Define a listener that responds to location updatesLocationListenerlocationListener=newLocationListener(){publicvoidonLocationChanged(Location location){// Called when a new location is found by the network location provider.makeUseOfNewLocation(location);}publicvoidonStatusChanged(String provider,int status,Bundle extras){}publicvoidonProviderEnabled(String provider){}publicvoidonProviderDisabled(String provider){}};// Register the listener with the Location Manager to receive location updateslocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,0,locationListener); http://developer.android.com/guide/topics/location/strategies.html
toast • Contextcontext=getApplicationContext();CharSequence text ="Hello toast!";int duration =Toast.LENGTH_SHORT;Toasttoast=Toast.makeText(context, text, duration);toast.show(); http://developer.android.com/guide/topics/ui/notifiers/toasts.html
Send sms • <manifest ... ><uses-permissionandroid:name="android.permission.SEND_SMS"/> ...</manifest> • /** Called when the activity is first created. */ • @Override • public void onCreate(BundlesavedInstanceState){ • 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(newView.OnClickListener() { • public void Onclick(Viewv) { • 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
Send sms • privatevoidsendSMS(StringphoneNumber, String message) { • SmsManagersms = SmsManager.getDefault(); • sms.sendTextMessage(phoneNumber, null, message, null, null); • }
Google location services • Fused location provider: • Gives the bests location according to the needs • “high accuracy”, “low power”, etc. • Geofencing APIs: • App will receive notifications when the user enters specific geographic boundaries • Activity recognition: • In a vehicle • On a bicycle • On foot • Still • Tilting • Unknown http://developer.android.com/reference/android/telephony/SmsManager.html