5. Tools
Tools directory
http://developer.android.com/tools/help/index.html
Support libraries and compatibility
In recent updates of Eclipse and the Android SDK
android-support-V4.jar is added by default in the libs folder when
new project is created
http://developer.android.com/tools/support-library/index.html
Adb commands
Process for communicating the device(real or emulated) with
hardware development
adb devices
adb install aplicación.apk –r[update]
adb uninstall aplicación.apk –k[dont clean application/cache data]
8. UI Design
http://developer.android.com/design/index.html
Ways to specify the size of an item:
dp/dip: Density independent pixel.
sp/sip: Scale independent pixel. Used in font sizes.
pt: Point.
px: Pixel. Not use
Ancho y alto
match_parent:takes all the space available.
wrap_content: uses the space needed
fill_parent:equivalent to match_parent
9. Android Asset Studio
Generate icons and graphic elements for each resolution
http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html
11. Resources /Screen support
External elements you want to include and reference in the application.
Declaratively include in /res ,accesing by @<type>/<nname>
Are programmatically accessible via the R class
(compiled with Android Asset Packaging Tool)
Android automatically selects the resource that adapts to the environment
Each resource type in a folder / res.
drawable: Images, Icons.
layout: Layout to organize views.
values:
string.xml: Text strings
colors.xml
dimens.xml: font sizes
anim: Animations
raw: Other resources like audio or video
menu: Menus and dialogs
xml: Other xml (preferences, app widget, …)
<supports-screens android:anyDensity="true"
android:xlargeScreens="true" android:largeScreens="true"
android:normalScreens="true" android:smallScreens="true" />
13. Google play services
Check if the service is available
import com.google.android.gms.common.GooglePlayServicesUtil;
int resultCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable
(getApplicationContext());
Can return the constants:
ConnectionResult.SUCCESS:
ConnectionResult.DEVELOPER_ERROR:
ConnectionResult.INTERNAL_ERROR:
ConnectionResult.INVALID_ACCOUNT:
ConnectionResult.NETWORK_ERROR:
ConnectionResult.RESOLUTION_REQUIRED:
ConnectionResult.SERVICE_DISABLED:
ConnectionResult.SERVICE_INVALID:
ConnectionResult.SERVICE_MISSING:
ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
ConnectionResult.SIGN_IN_REQUIRED:
14. OPENGL 2.0 SUPPORT
Google Maps Android API v2 only supports devices with
OpenGL ES 2.0 and above.
Check if the system supports OpenGL ES 2.0
final ActivityManager activityManager =
(ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo =
activityManager.getDeviceConfigurationInfo();
final boolean supportsEs2 = configurationInfo.reqGlEsVersion >=
0x20000;
15. GoogleMaps v2
The maps are integrated into Google services play
Obtain key
https://developers.google.com/maps/documentation/android/start#the_goo
gle_maps_api_key
Get signed certificate using the keytool command
Google APIS Console
https://code.google.com/apis/console/
Google CLOUD Console
https://cloud.google.com/console
keytool -list -v -keystore "%USERPROFILE%/.android/debug.keystore"
23. Action Bar
ActionBArSherlock.
It is an extension of functionality implemented in the support library
http://actionbarsherlock.com/
ActionBarCompat
Create a new project with API 18 and add the project in the folder
sdkextrasandroidsupportv7appcompat.
27. ACTION BAR
Icon to go back in Action Bar
ActionBar ab = getSupportActionBar();
ab.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE
|ActionBar.DISPLAY_SHOW_HOME|ActionBar.DISPLAY_HOME_AS_UP);
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
break;
}
return super.onOptionsItemSelected(item);
}
Action Bar in fragments
setHasOptionsMenu(true)
onCreateOptionsMenu: to inflate the menu provided by the fragment.
onOptionsItemSelected: to respond to the user touch in an item provided by
the fragment menu.
28. ACTION BAR PROGRESS
Progress bar in Action Bar
private Activity activity = this;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
ActionBar ab = getSupportActionBar();
………
}
activity.setProgressBarIndeterminateVisibility(true);
viewer.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
activity.setProgressBarIndeterminateVisibility(false);
}
Show the progress bar to start loading and hide when finished.
29. Notifications
To generate notifications in the status bar of the system we use a class included in
library compatibility android-support-v4.jar.
The class is NotificationCompat.Builder and we have to create a new object
passing by parameter application context and assign all the properties you want
through their set () methods.
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
NotificationCompat.Builder myNotification = new
NotificationCompat.Builder(context)
.setContentTitle(titulo)
.setContentText(texto)
.setTicker(aviso)
.setWhen(System.currentTimeMillis())
.setContentIntent(contentIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.favorito)
.setLargeIcon(largeIcon);
30. Notifications
Create and launch notification via object NotificationManager
TaskStackBuilder
stackBuilder=TaskStackBuilder.create(context);
stackBuilder.addParentStack(PrincipalActivity.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent
resultPendingIntent=stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
Associating action to notification
NotificationManager notificationManager;
notificationManager =(NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
/*Create notification with builder*/
Notification notification=myNotification.build();
notificationManager.notify((int)
System.currentTimeMillis(), notification);
41. Asynctask
This class will allow us to perform background tasks without using neither
directly nor Handlers Threads, trying these elements in a fully transparent way
to the programmer.
When we define a AsyncTask class must define the type of three elements, the
input parameters, its progress and outcome.
Override
onPreExecute(),doInBackground(),onPostExecute(),onProgressUpdate()
class RequestTask extends AsyncTask<String, String, String>{
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Integer... values) {
}
@Override
protected String doInBackground(String... uri) {
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
new
RequestTask().
execute(url);
42. Asynctask
onPreExecute, run before executing our task and we can use it to initialize
tasks as displaying a progress bar.
doInBackground(Params...), here we schedule our background task. Params
in the case discussed earlier will be an array of Strings that are passed when
calling the execute method. Being a process that can take an indefinite time to
complete, we can give feedback to the user thanks to percent complete in
publishProgress(Progress. ..) method.
publishProgress receives an integer parameter and make the execution of
onProgressUpdate method to indicate the user the task percentage.
onPostExecute(Result), runs to finish the process in the background.
The problem of doInBackground method is blocking the UI, so while this
method is running can not get anything in the ui, but if we have no
choice ,we can use this code for debug.
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Example for
Toast",Toast.LENGTH_SHORT).show();}
});
43. Singleton
Only one instance
Application class
<application
android:allowBackup="true"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/Theme.Styled"
android:name=
"com.proyecto.spaincomputing.singleton.MySingleton">
public class MySingleton extends Application
{
private static MySingleton instance;
public static Context context;
@Override public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
}
44. Navigation Pattern
import android.support.v4.app.NavUtils;
NavUtils.navigateUpTo(this,
new Intent(this, ListadoActivity.class));
http://developer.android.com/design/patterns/navigation.html
Intent intent = NavUtils.getParentActivityIntent(this);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_SINGLE_TOP);
NavUtils.navigateUpTo(this, intent);
NavUtils.navigateUpFromSameTask(this);
<activity android:name=".DetalleUniversidadActivity"
android:parentActivityName=".ListadoActivity"
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value=".ListadoActivity" />
</activity>
45. Adapter Pattern
Link between the source data and the view
It works with ListView or GridView
There are many types of adapter
You can perform a custom adaptar
The most used ArrayAdapter / CursorAdapter
The Adapter interacts with a collection of data objects for display in
View
ArrayList<UniversidadBean>
listado=newArrayList<UniversidadBean>();
private ListView lstListado;
lstListado=(ListView)getView().findViewById
(R.id.LstListado);
lstListado.setAdapter
(new UniversidadAdapter(this,listado));
46. View Holder/View Container Pattern
ViewContainer
static class ViewContainer{
public ImageView imagen;
public TextView nombre;
public TextView descripcion;
}
Improve the performance of listview
The viewholder is used to avoid calling findViewById whenever prompted a
new row to the adapter. Thus, instead of calling findViewById each time you
use the references to the fields you have stored in the viewholder.
This pattern will help us to limit the number of calls to findViewById method.
The idea would be to call it once, and then save the view daughter that refers
to the instance of ViewHolder to be associated with the object by the method
convertView View.setTag ()
Its recommend using a static class to store the items of each row in the view,
functioning as a kind of cache for our view.
47. View Holder/View Container Pattern
@Override
public View getView(int position, View convertView,ViewGroup parent) {
ViewContainer viewContainer;
//si es la primera vez que se imprime la fila
if(convertView==null){
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.row, null,true);
//crea una vista para el objeto contenedor
viewContainer=new ViewContainer()
//obtiene una referencia a todas las vistas de la fila
viewContainer.nombre=(TextView)convertView.findViewById(R.id.textView_superior);
viewContainer.descripcion=(TextView)convertView.findViewById(R.id.textView_inferior);
viewContainer.imagen=(ImageView)convertView.findViewById(R.id.imageView_imagen);
//asigna el contenedor de la vista a rowView
convertView.setTag(viewContainer);
}else{
viewContainer=(ViewContainer) convertView.getTag(); //recicling }
//personaliza el contenido de cada fila basándone en su posición
viewContainer.nombre.setText(listado.get(position).getNombre());
viewContainer.descripcion.setText(listado.get(position).getDescripcion());
viewContainer.imagen.setImageResource(listado.get(position).getIdImagen());
return(convertView);
}
49. Fragments
A fragment represents a certain behavior or a portion of a user interface
activity.
Multiple fragments can be combined.
A fragment must always be part of an activity.
They emerged to provide greater flexibility to build the user interface
Override methods
@Override
//called when finish onCreate method in activity
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public void onCreate(Bundle savedInstanceState) {//inicializar componentes
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle
savedInstanceState) {
}
http://developer.android.com/guide/components/fragments.html
50. Fragments
Add a fragment to view
by layout xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<fragment
class="com.proyecto.spaincomputing.fragment.UniversidadesFragment"
android:id="@+id/FrgListado"
android:layout_width="375dp"
android:layout_height="match_parent"/>
<fragment
class="com.proyecto.spaincomputing.fragment.FragmentDetalle"
android:id="@+id/FrgDetalle"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
51. Fragments
Add a fragment to view
By code
//Fragments array
Fragment[] fragments = new Fragment[]{new PortadaFragment(),
new UniversityListFragment(),new UniversidadesImagesFragment()};
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction()
.add(R.id.contentFrame, fragments[0])
.add(R.id.contentFrame, fragments[1])
.add(R.id.contentFrame, fragments[2])
.commit();
//show/hide
manager.beginTransaction().show(fragments[0]).commit();
manager.beginTransaction().hide(fragments[1]).commit();
manager.beginTransaction().hide(fragments[2]).commit();
56. Fragments/ Master-detail
Check orientation to display the detail page
UniversidadBean ub=listado.get(position);
if (getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE) {
FragmentManager manager =
getActivity().getSupportFragmentManager();
UniversidadInfoFragment fragment = (UniversidadInfoFragment)
manager.findFragmentById(R.id.fragmentUniversidadInfo);
fragment.loadWebViewContent(ub.getEnlace());
getActivity().invalidateOptionsMenu();
} else {
Intent intent = new Intent(getActivity().getApplicationContext(),
UniversityDetailActivity.class);
intent.putExtra(UniversityDetailActivity.URL, ub.getEnlace());
url=ub.getEnlace();
intent.putExtra(UniversityDetailActivity.UNIVERSIDAD,
ub.getNombre());
startActivity(intent);
}
57. Dialog Fragment
The DialogFragment class provides all the controls you need to create a dialogue and
change its appearance. It was introduced in Android 3.0 (API 11) and is available in the
support library, so that it can be used without problems with older versions.
Use the class you DialogFragment ensures proper management of events that may
occur, such as clicking the Back button or rotate the screen. Furthermore, using this class
we can reuse the interface dialogues as a larger component interface.
To create a dialogue create a class that inherits from the DialogFragment class and
create an AlertDialog object in the onCreateDialog() method
import android.support.v4.app.DialogFragment;
public class LinkDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(getText(R.string.title).toString());
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id) {
listener.onDialogNegativeClick(LinkDialogFragment.this);
}
});
return builder.create();
}}
58. Dialog Fragment
To display the dialog we just created we have to create an instance of the
class in our business and invoke the show () method so that the dialog
appears.
With getSupportFragmentManager() call method get access to
FragmentManager that is responsible for managing the fragments of the
application.
//LinkDialogFragment object
LinkDialogFragment linkDialogFragment=new LinkDialogFragment();
//fragment parameters
Bundle args = new Bundle();
args.putString("ENLACE", enlace);
linkDialogFragment.setArguments(args);
linkDialogFragment.show(getSupportFragmentManager(), "");
67. Action Share
Launch an intent of type "ACTION_SEND" to be received by the applications you have installed
public void mostrarShare(UniversidadBean ubBean){
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("text/html");
List<ResolveInfo> resInfo =
getActivity().getPackageManager().queryIntentActivities(shareIntent, 0);
if (!resInfo.isEmpty()){
for (ResolveInfo resolveInfo : resInfo) {
String packageName = resolveInfo.activityInfo.packageName;
Intent targetedShareIntent = new
Intent(android.content.Intent.ACTION_SEND);
targetedShareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
targetedShareIntent.setType("text/html");
targetedShareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
"Spain COmputing UNiversity");
targetedShareIntent.setPackage(packageName);
targetedShareIntents.add(targetedShareIntent);
}
Intent chooserIntent =
Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size()-1),
getText(R.string.compartir));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
targetedShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
}
}
69. Contacts
import android.provider.ContactsContract; //CONTACTS PROVIDER
Cursor mCursor;
// acceder al content provider de contactos
mCursor = getContentResolver().query(Data.CONTENT_URI,
new String[] { Data._ID, Data.DISPLAY_NAME, Email.DATA1,
Phone.TYPE },
Data.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE + "' AND "
+ Email.DATA1 + " IS NOT NULL", null,Data.DISPLAY_NAME + " ASC");
ListAdapter adapter = new SimpleCursorAdapter(this, // context
android.R.layout.simple_list_item_2, // Layout para las filas
mCursor, // cursor
new String[] { Data.DISPLAY_NAME, Phone.NUMBER }, //COLUMNS
new int[] { android.R.id.text1, android.R.id.text2 }, //views
);
setListAdapter(adapter);
<uses-permission android:name="android.permission.READ_CONTACTS" />
android.os.Build.VERSION.SDK_INT<11 //before honeycomb
70. Contacts
CursorLoader cursorLoader=new CursorLoader(this,
Data.CONTENT_URI,
new String[] { Data._ID, Data.DISPLAY_NAME,
Email.DATA1,Phone.TYPE },
Data.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE + "' AND "+
Email.DATA1 + " IS NOT NULL", null,Data.DISPLAY_NAME + " ASC");
mCursor=cursorLoader.loadInBackground();
ListAdapter adapter = new SimpleCursorAdapter(this, // context
android.R.layout.simple_list_item_2, // Layout para las filas
mCursor, // cursor
new String[] { Data.DISPLAY_NAME, Phone.NUMBER }, //COLUMNS
new int[] { android.R.id.text1, android.R.id.text2 }, //views
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); //flag
);
setListAdapter(adapter);
android.os.Build.VERSION.SDK_INT>=11 //after honeycomb
Using CursorLoader allows the query cursor executing on a separate thread
71. Loaders in contacts
public class ContactsListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(ContactsQuery.QUERY_ID, null, this);}}
Inicializar loader
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new
CursorLoader(getActivity(),contentUri,ContactsQuery.PROJECTION,
ContactsQuery.SELECTION,null,ContactsQuery.SORT_ORDER);}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// This swaps the new cursor into the adapter.
if (loader.getId() == ContactsQuery.QUERY_ID) {
mAdapter.swapCursor(data);
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {}
72. HTTP Request
org.apache.http
// Create HTTP Client
HttpParams httpParameters = new BasicHttpParams();
// 3s max for connection
HttpConnectionParams.setConnectionTimeout
(httpParameters,3000);
// 4s max to get data
HttpConnectionParams.setSoTimeout(httpParameters, 4000);
HttpClient httpclient = new DefaultHttpClient(httpParameters);
HttpResponse response;
String responseString = null;
try {response = httpclient.execute(new HttpGet(uri[0]));//Execute uri
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
} else{
//Closes the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}} catch (ClientProtocolException e) {//TODO Handle problems..
} catch (IOException e) {//TODO Handle problems..}
73. API INSTAGRAM
.Developer register
New client register
http://instagram.com/developer/clients/manage/
http://instagram.com/developer/
75. API INSTAGRAM
Endpoint tag media recent
http://instagram.com/developer/endpoints/tags/#get_tags_media_recent
76. VOLLEY
https://android.googlesource.com/platform/frameworks/volley
https://github.com/mcxiaoke/android-volley
Unzip and import from Eclipse as a new project with code available. Export
the project as Java Volley / jar checking only the "src" folder.
Volley is a library that facilitates and speeds up the creation of applications
that make use of networking in Android handling concurrency and network
requests.
The advantage is that volley is responsible for managing the request threads
transparently to the developer.
libsvolley.jar
Objects
RequestQueue
Request: Contains all the necessary details of API calls to Web. For example,
the method to use (GET or POST), application data, listeners, error listeners.
78. VOLLEY RESPONSE
//Callback that is executed once the request has completed
Response.Listener<JSONObject> successListener =
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
}
}
JSON Response by volley.Response object
More volley examples
https://github.com/PareshMayani/Android-Volley-Example
79. Geolocation
LocationManager / android.location package
ACCESS_COARSE_LOCATION/ACCESS_FINE_LOCATION
//Obtenemos el Location Manager del sistema
LocationManager locationManager = (LocationManager)this.getSystemService
(Context.LOCATION_SERVICE);
// Definimos el Listener que gestionará los eventos
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
if (location != null) {
Toast.makeText(getBaseContext(),
"Location changed : Lat: " + location.getLatitude() +
" Lng: " + location.getLongitude(),Toast.LENGTH_SHORT).show();
}
}
// Registramos el Listener en el Location Manager para recibir actualizaciones
locationManager.
requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
0, 0, locationListener);
82. Restore state in activity
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
Save the Activity state before being destroyed
Restore the Activity state after being created
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
}
84. SEND EMAIL
ACTION_SEND INTENT
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.putExtra(android.content.Intent.EXTRA_EMAIL, new
String[]{destino});
//colocamos la imagen adjunta en el stream
intent.putExtra(Intent.EXTRA_STREAM,
Uri.parse("android.resource://" + getPackageName() + "/"
+R.drawable.image));
startActivity(Intent.createChooser(intent, "Send email"));
libs
https://code.google.com/p/javamail-android/downloads/list
Java mail API / Gmail SMTP /GMAILSender
Gmail authentication
Configure SMTP SERVER
85. Shared Preferences
Key/value dictionary
res/xml/preferencias.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/pref_notificaciones">
<CheckBoxPreference
android:key="pref_notificaciones_favoritos"
android:title="@string/pref_notificaciones_favoritos"
android:summary="@string/pref_notificaciones_favoritos"
android:defaultValue="true" />
</PreferenceCategory>
</PreferenceScreen>
PreferenceScreen is the entire screen that will show us where the other elements are
displayed, and PreferenceCategory will allow us to create categories or groupings within our
screen.
The common element in different items is the key property. This will be the key that is
stored in SharedPreferences and later retrieve the stored values by this key.
93. Libraries
Indicator in ViewPager
http://viewpagerindicator.com/
https://github.com/chrisbanes/ActionBar-PullToRefresh
Pager Sliding Tabstrip
https://github.com/astuetz/PagerSlidingTabStrip
Show routes in map.
https://github.com/tyczj/MapNavigator
94. Sliding Menu
Library to implement a sliding flyout with similar behavior to
navigation drawer
https://github.com/jfeinstein10/SlidingMenu
MessageBar
Library to improve toast messages
http://simonvt.github.io/MessageBar/
95. Fading Action Bar
Used in Google play music
https://github.com/ManuelPeinado/FadingActionBar
+
http://www.androidviews.net/