$30 off During Our Annual Pro Sale. View Details »

Android in Practice

Android in Practice

Android in Practice

jmortegac

April 26, 2015
Tweet

More Decks by jmortegac

Other Decks in Programming

Transcript

  1. Android in Practice José Manuel Ortega Techfest uc3m February 2014

  2. Index  DEVELOPMENT ENVIRONMENT / SDK / TOOLS / ADB

     UI DESIGN /ANDROID ASSET STUDIO  GOOGLE PLAY SERVICES / GOOGLE MAPS V2 / MAP FRAGMENTS  ACTION BAR / SEARCH VIEW / NOTIFICATIONS / ACCESSIBILITY / CONTEXTUAL MENU  WEBVIEW / NETWORK CONNECTIONS / ASYNCTASK  SINGLETON / ADAPTER PATTERN / VIEW HOLDER PATTERN  FRAGMENTS / MASTER-DETAIL / DIALOG FRAGMENTS  NAVIGATION DRAWER / ACTION BAR DRAWER TOOGLE /TABS  ACTION SHARE / CONTACTS / LOADERS  HTTP REQUEST /VOLLEY / INSTAGRAM API  GEOLOCATION / SHARED PREFERENCES / SQLITE DATABASE  LIBRARIES
  3. Development environment  JAVA JDK+ANDROID SDK  http://www.oracle.com/technetwork/es/java/javasebusiness/downlo ads/index.html 

    http://developer.android.com/sdk/index.html  https://developer.android.com/intl/es/reference/android/app/packag e-summary.html Android SDK Starter Package
  4. Development process

  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]
  6. Project

  7. Spain Computing University

  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
  10. Android manifest.xml  Define the components and application permissions <uses-sdk

    android:minSdkVersion="8" android:targetSdkVersion="17" /> <!-- Permisos --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <application android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/Theme.Styled" android:configChanges="locale|keyboard|keyboardHidden|orientation" android:name="com.proyecto.spaincomputing.singleton.MySingleton" android:hardwareAccelerated="true" > <activity android:name="com.proyecto.spaincomputing.SplashScreenActivity« android:label="@string/app_name" android:theme="@style/TransparentTheme" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ListadoActivity" android:configChanges="locale|keyboard|keyboardHidden|orientation" android:hardwareAccelerated="true"/> </application> http://developer.android.com/reference/android/Manifest.permission.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" />
  12. Google play services

  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"
  16. GoogleMaps v2  Windowpreferencesandroidbuild

  17. GoogleMaps v2

  18. Permissions /Features Google Mapsv2 <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <!-- Localizacion --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-feature android:glEsVersion="0x00020000" android:required="true"/> <permission android:name="com.proyecto.spaincomputing.permission.MAPS_RECEIVE" android:protectionLevel="signature"/> <uses-permission android:name="com.proyecto.spaincomputing.permission.MAPS_RECEIVE"/> <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="YOUR_API_KEY"/> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
  19. Map fragments  layout/fragment_mapa.xml <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.SupportMapFragment"/> 

    MapaActivity. FragmentActivity from android.support.v4 import android.support.v4.app.FragmentActivity; public class MapaActivity extends FragmentActivity{ private GoogleMap mapa=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_mapa); mapa = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) .getMap(); }}
  20. Markers/InfoWindow public class MapaActivity extends FragmentActivity implements OnMapLongClickListener, InfoWindowAdapter{ @Override

    public void onMapLongClick(LatLng location) { MarkerOptions options = new MarkerOptions() .position(location) //location mandatory .title(title) .snippet(snippet); Marker marker = mapa.addMarker(options); } @Override public View getInfoContents(Marker marker) { View window = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE). inflate(R.layout.info_window, null); txt_title.setText(marker.getTitle()); txt_snippet.setText(marker.getSnippet()); return window; } }
  21. Markers/InfoWindow

  22. OPENGL / DISTANCE POLYGON

  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 sdk\extras\android\support\v7\appcompat.
  24. Action Bar search view

  25. Action Bar search view  Implement interface OnQueryTextListener  Override

    methods onQueryTextSubmit, onQueryTextChange @Override public boolean onQueryTextSubmit(String query) { UniversityListFragment fragmentList = (UniversityListFragment)getSupportFragmentManager().findFragmentBy Tag("list_fragment"); fragmentList.searchData(query); return true; } @Override public boolean onQueryTextChange(String query) { return true; }
  26. Action Bar search view @Override public boolean onCreateOptionsMenu(Menu menu) {

    mSearchView = (SearchView) searchItem.getActionView(); mSearchView.setQueryHint("Search..."); mSearchView.setOnQueryTextListener(this); return true; } <item android:id="@+id/action_search" android:showAsAction="always" android:title="@string/search" android:icon="@android:drawable/ic_menu_search" android:actionViewClass= "android.support.v7.widget.SearchView" /> private SearchView mSearchView;
  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);
  31. Accessibility http://developer.android.com/training/accessibility/index.html <Button android:id="@+id/pause_button" android:src="@drawable/pause" android:contentDescription="@string/pause"/>  Through layout 

    Through code String contentDescription = "Select " + strValues[position]; label.setContentDescription(contentDescription);
  32. Contextual menu

  33. Contextual menu  Add menu items by code @Override public

    void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) { if(listado.size()>0){ menu.setHeaderTitle(R.string.accion); if(!favoritos){ menu.add(0, Constants.MENU_FAVORITO, 3, getResources().getText(R.string.anyadir_favorito)); }else{ menu.add(0, Constants.MENU_FAVORITO, 3, getResources().getText(R.string.eliminar_favorito)); } }} lstListado.setAdapter(new UniversidadAdapter(this)); registerForContextMenu(lstListado); //view register  Floating list at long press on a View row
  34. Contextual menu  Add options menu with xml (recommended option)

    <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/mapa" android:title="@string/mapa" android:showAsAction="ifRoom|withText" android:icon="@drawable/location" /> <item android:id="@+id/rutaGoogle" android:title="@string/ruta_google" android:showAsAction="ifRoom|withText" android:icon="@drawable/google_map" /> </menu> @Override public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater=getActivity().getMenuInflater(); if(listado.size()>0){ inflater.inflate(R.menu.menu_mostrar, menu); }}
  35. Contextual menu //Manage touch in contextual menu @Override public boolean

    onContextItemSelected(android.view.MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); //selected row UniversidadBean ub = (UniversidadBean) getUniversidad((int) info.id); switch (item.getItemId()) { case Constants.MENU_ENLACE: if(ub.getEnlace()!=null){ listener.onUniversidadLink(ub.getEnlace()); } return true; default: return super.onContextItemSelected(item); } }
  36. WebView

  37. WebView <WebView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/visorWebView"> </WebView> import android.webkit.WebView; import android.webkit.WebViewClient;

    WebView viewer; viewer = (WebView) findViewById(R.id.visorWebView); viewer.setWebViewClient(new myWebClient()); viewer.getSettings().setJavaScriptEnabled(true); viewer.getSettings().setBuiltInZoomControls(true); viewer.loadUrl(content);
  38. WebView public class myWebClient extends WebViewClient{ @Override public void onPageStarted(WebView

    view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } }
  39. Network connection import android.net.ConnectivityManager; import android.net.NetworkInfo; ConnectivityManager connectivityManager; connectivityManager =

    (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); Boolean connected = networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected(); <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  40. Network connection  Enable Wifi / Check connection type NetworkInfo

    wifiInfo=connectivityManager.getNetworkInfo (ConnectivityManager.TYPE_WIFI); NetworkInfo mobileInfo=connectivityManager.getNetworkInfo (ConnectivityManager.TYPE_MOBILE); if(wifiInfo.isConnected()){ Toast.makeText(context, "Wifi is connected", Toast.LENGTH_LONG).show(); } if(mobileInfo.isConnected()){ Toast.makeText(context, "3G/4G is connected", Toast.LENGTH_LONG).show(); } WifiManager wifiManager=(WifiManager) context.getSystemService(Context.WIFI_SERVICE); wifiManager.setWifiEnabled(true); <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
  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); }
  48. View Holder/View Container Pattern  Debug

  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();
  52. Fragments/ Master-detail PORTRAIT LANDSCAPE

  53. Fragments/ Master-detail PORTRAIT LANDSCAPE

  54. Fragments/ Master-detail  2 layout  layout\fragment_universidades_list.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" > <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout>
  55. Fragments/ Master-detail  2 layout  layout-land\fragment_universidades_list.xml <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:baselineAligned="false" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="horizontal" tools:context=".TabsActivity" > <ListView android:id="@+id/listView" android:layout_width="0px" android:layout_height="wrap_content" android:layout_weight="1.5"> </ListView> <fragment android:id="@+id/fragmentUniversidadInfo" android:name="com.proyecto.spaincomputing.fragment.UniversidadInfoFragment" android:layout_width="0px" android:layout_height="wrap_content" android:layout_weight="4" tools:layout="@layout/fragment_universidad_info" /> </LinearLayout>
  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(), "");
  59. Navigation Drawer <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/drawerLayout">

    <!-- The main content view --> <FrameLayout android:id="@+id/contentFrame" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- The navigation drawer --> <ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" android:background="#111"/> </android.support.v4.widget.DrawerLayout>  http://developer.android.com/training/implementing-navigation/nav- drawer.html
  60. Navigation Drawer private ListView drawerList; private String[] drawerOptions; private DrawerLayout

    drawerLayout; drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout); drawerList = (ListView) findViewById(R.id.left_drawer); drawerOptions = getResources().getStringArray(R.array.drawer_options); // Set the adapter for the list view drawerList.setAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.drawer_list_item,drawerOptions)); // Set the list's click listener drawerList.setOnItemClickListener(new DrawerItemClickListener()); private class DrawerItemClickListener implements ListView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position,long id) { setContent(position); } }
  61. Navigation Drawer/ ActionBarDrawerToogle private ActionBarDrawerToggle drawerToggle; drawerToggle = new ActionBarDrawerToggle(

    this, drawerLayout, R.drawable.ic_drawer, R.string.drawer_open, //accesibility text string R.string.drawer_close ) { public void onDrawerClosed(View view) { ActivityCompat.invalidateOptionsMenu(PrincipalActivity.this); } public void onDrawerOpened(View drawerView) { ActivityCompat.invalidateOptionsMenu(PrincipalActivity.this); } } //listener drawerLayout.setDrawerListener(drawerToggle); drawerToggle.setDrawerIndicatorEnabled(true);  Open/close sidebar by Icon ActionBar  Through ActionBarDrawerToogle object in support library
  62. Navigation Drawer/ ActionBarDrawerToogle getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeButtonEnabled(true); @Override public void onConfigurationChanged(Configuration newConfig)

    { super.onConfigurationChanged(newConfig); drawerToggle.onConfigurationChanged(newConfig); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); drawerToggle.syncState(); //sincronize drawer toogle state } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { if (drawerLayout.isDrawerOpen(drawerList)) { drawerLayout.closeDrawer(drawerList); } else { drawerLayout.openDrawer(drawerList); } return true; } }  We allow the use of the icon in Action Bar
  63. Tabs

  64. Tabs  Implement interface TabListener  Override methods in TabListener

    @Override public void onTabUnselected(Tab arg0, FragmentTransaction arg1) { } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { setContent(tab.getPosition()); } import com.actionbarsherlock.app.ActionBar.Tab; import com.actionbarsherlock.app.ActionBar.TabListener; public class TabsActivity extends SherlockFragmentActivity implements TabListener { }
  65. Tabs  Reference obtain ActionBar final ActionBar actionBar = getSupportActionBar();

    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_T ABS);  Add tabs actionBar.addTab( actionBar.newTab() .setText(getResources().getString(R.string.listado)) .setTabListener(this)); actionBar.addTab( actionBar.newTab() .setText(getResources().getString(R.string.imagenes)) .setTabListener(this));
  66. Action Share / Share Action Provider

  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); } }
  68. Share Action Provider <item android:id="@+id/action_share" android:title="@string/compartir" spaincomputing:showAsAction="ifRoom" spaincomputing:actionProviderClass= "android.support.v7.widget.ShareActionProvider"/> private

    Intent createShareIntent() { Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("text/html"); shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Spain COmputing UNiversity"); UniversidadBean ub=new UniversidadBean(id, idImagen, nombre, descripcion, enlace, tipo, grado, latitud, longitud); shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, Html.fromHtml(ub.getNombre()+"\n"+ub.getDescripcion()+"\n"+ub.getGrado()+" \n\n"+ub.getEnlace()+"\n\n"+ub.getLatitud()+"\n"+ub.getLongitud())); return shareIntent; } private ShareActionProvider mShareActionProvider; MenuItem shareItem = menu.findItem(R.id.action_share); mShareActionProvider = (ShareActionProvider)MenuItemCompat.getActionProvider(shareItem); mShareActionProvider.setShareIntent(createShareIntent());
  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/
  74. API INSTAGRAM

  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.  libs\volley.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.
  77. VOLLEY REQUEST import com.android.volley.*; public static RequestQueue requestQueue; @Override protected

    void onCreate(Bundle savedInstanceState) { requestQueue = Volley.newRequestQueue(this); }  JSON Request with volley.Request object JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, successListener,null); requestQueue.add(jsObjRequest);  Instagram Activity
  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);
  80. Geolocation  Implement interface ConnectionCallbacks import com.google.android.gms.common.GooglePlayServicesClient. ConnectionCallbacks;  Override

    onConnected / User location @Override public void onConnected(Bundle arg0) { updateLocation(locationClient.getLastLocation()); locationClient.requestLocationUpdates(locationRequest, this); } import com.google.android.gms.location.LocationClient; import com.google.android.gms.location.LocationRequest; locationClient = new LocationClient(this, this, this); locationRequest = LocationRequest.create();
  81. Reverse Geolocation Geocoder geoCoder = new Geocoder(context, Locale.getDefault()); List<Address> addresses

    = null; try { addresses = geoCoder.getFromLocation(gp.latitude , gp.longitude , 1); if (addresses!=null && addresses.size() > 0) { Address address = addresses.get(0); if(address.getMaxAddressLineIndex() > 0 ){ addressText =address.getAddressLine(0); } if(address.getLocality()!=null){ addressText = addressText+" / "+address.getLocality(); } if(address.getCountryName()!=null){ addressText = addressText+" / "+address.getCountryName(); } } } catch (IOException e) { }  Obtain place address from latidude and longitude
  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); }
  83. SEND EMAIL

  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.
  86. Shared Preferences

  87. Shared Preferences  Preferences Activity @Override public void onCreate(Bundle savedInstanceState)

    { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { onCreatePreferenceActivity(); } else { onCreatePreferenceFragment(); } } private void onCreatePreferenceActivity() { PreferenceManager prefManager=getPreferenceManager(); prefManager.setSharedPreferencesName("appPreferences"); addPreferencesFromResource(R.xml.preferencias); } private void onCreatePreferenceFragment() { getFragmentManager().beginTransaction() .replace(android.R.id.content, new MyPreferenceFragment ()) .commit(); }
  88. Shared Preferences  PreferenciasActivity public static class MyPreferenceFragment extends PreferenceFragment

    { @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); PreferenceManager prefManager=getPreferenceManager(); prefManager.setSharedPreferencesName("appPreferences"); addPreferencesFromResource(R.xml.preferencias); } }  Get Preferences values SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("appPreferences", MODE_PRIVATE); //Launch favorites notification depending preferences value if(sharedPreferences.getBoolean("pref_notificaciones_favoritos",true)){ com.proyecto.spaincomputing.utils.StatusBarNotify.getInstance( getApplicationContext()).statusBarNotify("eliminado_favorito", nombre,descripcion); }
  89. SQLITE DATABASE

  90. SQLITE DATABASE  import android.database.sqlite.*;  Create class that extends

    SQLiteOpenHelper and override onCreate() method to create database public class DBHelper extends SQLiteOpenHelper { //constructor public DBAdapter (Context context){ dbHelper = new DBHelper(context, DATABASE_NAME, null, DATABASE_VERSION); } private final static String DATABASE_CREATE = "CREATE TABLE ..“; @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_CREATE); } }  Emulator /root  /data/data/<package>/databases
  91. SQLITE DATABASE  INSERT,UPDATE,DELETE SQLiteDatabase db = dbHelper.getWritableDatabase();  QUERY

    SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor= myDatabase.query(DATABASE_TABLE, null, where,null, null, null, order); // Create a new row of values to insert. ContentValues newValues = new ContentValues(); // Assign values for each row. newValues.put(COLUMN_NAME, newValue); [ ... Repeat for each column ... ] // Insert myDatabase.insert(DATABASE_TABLE, null, newValues); // Update myDatabase.update(DATABASE_TABLE, updatedValues, where, null); // Delete myDatabase.delete(DATABASE_TABLE, null, null);
  92. Developer libraries in google play

  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/
  96. About me https://github.com/jmortega/apps https://github.com/jmortega/android https://www.linkedin.com/in/jmortega1 jmoc25@gmail.com https://play.google.com/store/apps/developer?id=Jos%C3%A9+Manuel+Ortega+Candel

  97. Google play