+ All Categories
Home > Technology > Android Real-Life Architecture

Android Real-Life Architecture

Date post: 13-May-2015
Category:
Upload: open-knowledge-gmbh
View: 584 times
Download: 2 times
Share this document with a friend
Description:
Speaker: Lars Röwekamp MobileTechCon 2013 Berlin Die mittlerweile ausgereiften Android-APIs sowie das zugehörige Tooling machen es einem Mobile Developer denkbar einfach, Android-4.x-Anwendungen zu programmieren. Dank ActionBar, Fragments und Co. ist auch das Portieren für unterschiedlichste Device-Typen, wie z.B. Smartphones und Tablets, heute kein Rocket Science mehr. Aber wie kommt es dann, dass so viele Anwendungen den "Real-Life"-Check nicht bestehen und schlecht bewertet werden? Fakt ist, dass eine ergonomisch gute App deutlich mehr benötigt als nur schöne UIs - das Zauberwort heißt "Architektur".
114
Photo credit: SantiMB . / Foter.com / CC BY-NC-ND Real-Life Architecture @mobileLarson @_openKnowledge Lars Röwekamp | CIO New Technologies
Transcript
Page 1: Android Real-Life Architecture

Pho

to c

redi

t: S

antiM

B .

/ Fot

er.c

om /

CC

BY-

NC

-ND

Real-Life Architecture

@mobileLarson @_openKnowledge

Lars Röwekamp | CIO New Technologies

Page 2: Android Real-Life Architecture

Real-Life Architecture Android 4+

MTC2013

Eigentlich ist ja alles ganz einfach ...

Page 3: Android Real-Life Architecture

Real-Life Architecture Android 4+

MTC2013

Eigentlich ist ja alles ganz einfach ...

Page 4: Android Real-Life Architecture

Real-Life Architecture Android 4+

MTC2013

... auch wenn es kompliziert(er) wird.

Page 5: Android Real-Life Architecture

Real-Life Architecture Android 4+

MTC2013

... auch wenn es kompliziert(er) wird.

Page 6: Android Real-Life Architecture

Real-Life ArchitectureMTC2013

Splash Overview Share

Preferences

Map

Real-Life Architecture

Page 7: Android Real-Life Architecture
Page 8: Android Real-Life Architecture

Android 4+

Page 9: Android Real-Life Architecture

Real-Life Architecture Android 4+

MTC2013

Page 10: Android Real-Life Architecture

Real-Life Architecture Android 4+

MTC2013

Wo liegt das ...

Problem?

Page 11: Android Real-Life Architecture

Es war einmal eine App ...Real-Life Architecture

MTC2013

Splash Overview Share

Preferences

Map

Page 12: Android Real-Life Architecture

Es war einmal eine App ...Real-Life Architecture

MTC2013

Page 13: Android Real-Life Architecture

Es war einmal eine App ...Real-Life Architecture

MTC2013

Anforderungen easy Version

‣ klassische Android Anwendung‣ Kunden CI und White Label‣ Anbindung von (Web) Services‣ Vorlieben/Einstellungen merken‣ Time-to-Market

Page 14: Android Real-Life Architecture

Es war einmal eine App ...Real-Life Architecture

MTC2013

Anforderungen eXtended Edition

‣ Smartphone & Tablet Support‣ Android 2.3 & Android 4.x Support‣Multi-Language Support‣Multi-User Support‣ Localization Support

Page 15: Android Real-Life Architecture

Es war einmal eine App ...Real-Life Architecture

MTC2013

Anforderungen Directors Cut

‣ Daten immer aktuell‣ Daten auch offline ‣ Daten auch für Dritte‣ batterieschonend ‣ ... und natürlich „Top Security“‣ ... und natürlich „Top Usabillity“

Page 16: Android Real-Life Architecture

... und die hatte eine ArchitekturReal-Life Architecture

MTC2013

Page 17: Android Real-Life Architecture

... und die hatte eine ArchitekturReal-Life Architecture

MTC2013

Page 18: Android Real-Life Architecture

Es war einmal eine App ...Real-Life Architecture

MTC2013

Let‘s go

‣ klein starten‣ schrittweise erweitern‣ stets lauffähig und sinnvoll

‣ Refactoring ist ein Zeichen von Stärke

Page 19: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 1: POI senden

Page 20: Android Real-Life Architecture

Schritt 1: POI sendenReal-Life Architecture

MTC2013

Page 21: Android Real-Life Architecture

MTC2013

POI senden Best Practices

‣ UI und Logik trennen‣ Kommunikation in eigene Lib auslagern‣ „Application not Responding“ vermeiden

Real-Life ArchitectureSchritt 1: POI senden

Page 22: Android Real-Life Architecture

MTC2013

Code Diving ...

Real-Life ArchitectureSchritt 1: POI senden

Page 23: Android Real-Life Architecture

MTC2013

POI senden Pitfalls

‣ Network on Main Thread‣ Strict Mode

Real-Life ArchitectureSchritt 1: POI senden

Page 24: Android Real-Life Architecture

MTC2013

POI senden Pitfalls

‣ Network on Main Thread‣ Strict Mode

Real-Life ArchitectureSchritt 1: POI senden

Page 25: Android Real-Life Architecture

MTC2013

Netzwerkzugriff seit 4.x nur via ...

Async

Real-Life ArchitectureSchritt 1: POI senden

Page 26: Android Real-Life Architecture

MTC2013class  PostToFriendFinder  extends  AsyncTask<Void,  Integer,  String>  {

       //  Invoked  on  the  background  thread  immediately  after  onPreExecute()        //  finishes  executing.  Performs  background  computation  that  can  take          //  a  long  time.  The  parameters  of  the  async  task  are  passed  to  this          //  step.              //  @Override        protected  String  doInBackground(Void...  params)  {            try  {            getFriendFinder().sharePointOfInterstVisit(poi,  note);            return  "Sending  point  of  interest  visitation  was  successfull.";            }  catch  (FriendFinderException  ex)  {        return  "Sending  point  of  interest  visitation  failed.";          }        }            @Override        protected  void  onProgressUpdate(Integer...  values)  {  ...  }

       @Override        protected  void  onPostExecute(String  result)  {  ...  }

}

Async

Real-Life ArchitectureSchritt 1: POI senden

Page 27: Android Real-Life Architecture

MTC2013class  PostToFriendFinder  extends  AsyncTask<Void,  Integer,  String>  {

       //  Invoked  on  the  background  thread  immediately  after  onPreExecute()        //  finishes  executing.  Performs  background  computation  that  can  take          //  a  long  time.  The  parameters  of  the  async  task  are  passed  to  this          //  step.              //  @Override        protected  String  doInBackground(Void...  params)  {            try  {            getFriendFinder().sharePointOfInterstVisit(poi,  note);            return  "Sending  point  of  interest  visitation  was  successfull.";            }  catch  (FriendFinderException  ex)  {        return  "Sending  point  of  interest  visitation  failed.";          }        }            @Override        protected  void  onProgressUpdate(Integer...  values)  {  ...  }

       @Override        protected  void  onPostExecute(String  result)  {  ...  }

}

Async

Real-Life ArchitectureSchritt 1: POI senden

POI & Note?

Page 28: Android Real-Life Architecture

MTC2013class  PostToFriendFinder  extends  AsyncTask<Void,  Integer,  String>  {

       private  PointOfInterest  poi;          private  String  note;              public  PostToFriendFinder(PointOfInterest  poi,  String  note)  {  ...  }            //  @Override        protected  String  doInBackground(Void...  params)  {            try  {            getFriendFinder().sharePointOfInterstVisit(poi,  note);            return  "Sending  point  of  interest  visitation  was  successfull.";            }  catch  (FriendFinderException  ex)  {        return  "Sending  point  of  interest  visitation  failed.";          }        }            @Override        protected  void  onProgressUpdate(Integer...  values)  {  ...  }

       @Override        protected  void  onPostExecute(String  result)  {  ...  }

}

Async

Real-Life ArchitectureSchritt 1: POI senden

Page 29: Android Real-Life Architecture

MTC2013//  onClick  handler  to  collect  input  data,  create  a  new  Point  of  Interest//  and  share  it  async  via  related  service  public  void  onClick(View  view)  {     float  latitude  =  ...;   float  longitude  =  ...;   String  note  =  ...;  

  //  create  new  point  of  interest   PointOfInterest  poi  =  new  PointOfInterest(longitude,  latitude,  0.00F);  

  //  create  async  tasks  to  communicate  with  the  cloud  service   new  PostToFriendFinder(poi,  note).execute();    

}

Real-Life ArchitectureSchritt 1: POI senden

Page 30: Android Real-Life Architecture

MTC2013//  onClick  handler  to  collect  input  data,  create  a  new  Point  of  Interest//  and  share  it  async  via  related  service  public  void  onClick(View  view)  {     float  latitude  =  ...;   float  longitude  =  ...;   String  note  =  ...;  

  //  create  new  point  of  interest   PointOfInterest  poi  =  new  PointOfInterest(longitude,  latitude,  0.00F);  

  //  create  async  tasks  to  communicate  with  the  cloud  service   new  PostToFriendFinder(poi,  note).execute();    

}

Real-Life ArchitectureSchritt 1: POI senden

Page 31: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 2: Einstellungen merken

Page 32: Android Real-Life Architecture

Real-Life ArchitectureMTC2013

Schritt 2: Einstellungen merken

Page 33: Android Real-Life Architecture

Schritt 2: Einstellungen merkenMTC2013

Einstellungen merken Best Practices

‣ Einstellungen zentral verwalten‣ Einstellungen gruppieren ‣ UI zur Bearbeitung bereit stellen‣ Settings Design Guide beachten

Real-Life Architecture

Page 34: Android Real-Life Architecture

Schritt 2: Einstellungen merkenMTC2013

Einstellungen merken Best Practices

‣ Einstellungen zentral verwalten‣ Einstellungen gruppieren ‣ UI zur Bearbeitung bereit stellen‣ Settings Design Guide beachten

Real-Life Architecture

Page 35: Android Real-Life Architecture

MTC2013

Einstellungen merken Pitfalls

‣ Hierarchie von Einstellungen‣ Einstellungen können sich ändern‣ Zugriff auf Einstellungen an mehreren Stellen

‣ Android 2.x vs. Android 4.x

Real-Life ArchitectureSchritt 2: Einstellungen merken

Page 36: Android Real-Life Architecture

MTC2013

Einstellungen via ...

Preferences

Real-Life ArchitectureSchritt 2: Einstellungen merken

Page 37: Android Real-Life Architecture

MTC2013<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <!-- opens a subscreen of settings --> <PreferenceScreen android:key="button_voicemail_category_key" android:title="@string/voicemail" android:persistent="false"> <ListPreference android:key="button_voicemail_provider_key" android:title="@string/voicemail_provider" ... /> <!-- opens another nested subscreen --> <PreferenceScreen android:key="button_voicemail_setting_key" android:title="@string/voicemail_settings" android:persistent="false"> ... </PreferenceScreen> <RingtonePreference android:key="button_voicemail_ringtone_key" android:title="@string/voicemail_ringtone_title" android:ringtoneType="notification" ... /> ... </PreferenceScreen> ...</PreferenceScreen>

Real-Life ArchitectureSchritt 2: Einstellungen merken

Page 38: Android Real-Life Architecture

MTC2013<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <!-- opens a subscreen of settings --> <PreferenceScreen android:key="button_voicemail_category_key" android:title="@string/voicemail" android:persistent="false"> <ListPreference android:key="button_voicemail_provider_key" android:title="@string/voicemail_provider" ... /> <!-- opens another nested subscreen --> <PreferenceScreen android:key="button_voicemail_setting_key" android:title="@string/voicemail_settings" android:persistent="false"> ... </PreferenceScreen> <RingtonePreference android:key="button_voicemail_ringtone_key" android:title="@string/voicemail_ringtone_title" android:ringtoneType="notification" ... /> ... </PreferenceScreen> ...</PreferenceScreen>

Real-Life ArchitectureSchritt 2: Einstellungen merken

Page 39: Android Real-Life Architecture

MTC2013public static class SettingsFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

// Load the preferences from an XML resource addPreferencesFromResource(R.xml.preferences); } ...}

public class SettingsActivity extends Activity {

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

// Display the fragment as the main content. getFragmentManager().beginTransaction() .replace(android.R.id.content, new SettingsFragment()) .commit(); }}

Real-Life ArchitectureSchritt 2: Einstellungen merken

Page 40: Android Real-Life Architecture

MTC2013public class FriendFinderApplication extends Application implements OnSharedPreferenceChangeListener {

SharedPreferences preferences; ...

@Override public void onCreate() { super.onCreate(); this.preferences = PreferenceManager.getDefaultSharedPreferences(this);

// recommanded in onResume (register) / onPause (unregister) this.preferences.registerOnSharedPreferenceChangeListener(this); // use preferences to initialize app data ... } ...

@Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // force reload of preferences and reinitialization of global data ... }}

Real-Life ArchitectureSchritt 2: Einstellungen merken

Page 41: Android Real-Life Architecture

Ok, aber wofür brauche ich dann

noch die PreferenceActivity?

Page 42: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 2: Einstellungen merken

Page 43: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 2: Einstellungen merken

Page 44: Android Real-Life Architecture

MTC2013

Code Diving ...

Real-Life ArchitectureSchritt 2: Einstellungen merken

Page 45: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 3: POIs abgleichen

Page 46: Android Real-Life Architecture

Real-Life ArchitectureMTC2013

Schritt 3: POIs abgleichen

Page 47: Android Real-Life Architecture

Schritt 3: POIs abgleichenReal-Life Architecture

MTC2013

Page 48: Android Real-Life Architecture

MTC2013

POIs abgleichen Best Practices

‣ POIs regelmäßig abgleichen‣ POIs so aktuell wie möglich halten‣ POIs im Hintergrund laden

Real-Life ArchitectureSchritt 3: POIs abgleichen

Page 49: Android Real-Life Architecture

MTC2013

POIs abgleichen Pitfalls

‣ regelmäßig‣ aktuell‣ im Hintergrund

Real-Life ArchitectureSchritt 3: POIs abgleichen

Page 50: Android Real-Life Architecture

MTC2013

Hintergrundaufgaben via ...

Service

Real-Life ArchitectureSchritt 3: POIs abgleichen

Page 51: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 3: POIs abgleichen

Page 52: Android Real-Life Architecture

MTC2013public class UpdaterService extends Service {

private Updater updater; ... public IBinder onBind(Intent intent) { ... } public void onCreate() { ... } public int onStartCommand(Intent intent, int flags, int startId) { .. } public void onDestroy() { ... }

private class Updater extends Thread {

public Updater() { ... }

public void run() { UpdaterService updaterService = UpdaterService.this; while (updaterService.running) { try { ... // do some work Thread.sleep(DELAY); } catch (InterruptedException ex) { updaterService.running = false; } }

} }}

Real-Life ArchitectureSchritt 3: POIs abgleichen

Page 53: Android Real-Life Architecture

MTC2013public class UpdaterService extends Service {

private Updater updater; ... public IBinder onBind(Intent intent) { ... } public void onCreate() { ... } public int onStartCommand(Intent intent, int flags, int startId) { .. } public void onDestroy() { ... }

private class Updater extends Thread {

public Updater() { ... }

public void run() { UpdaterService updaterService = UpdaterService.this; while (updaterService.running) { try { ... // do some work Thread.sleep(DELAY); } catch (InterruptedException ex) { updaterService.running = false; } }

} }}

Real-Life Architecture Starten & Stoppen?

Online vs. Offline?

Schritt 3: POIs abgleichen

Page 54: Android Real-Life Architecture

MTC2013

Code Diving ...

Real-Life ArchitectureSchritt 3: POIs abgleichen

Page 55: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 4: Offline-Modus

Page 56: Android Real-Life Architecture

Real-Life ArchitectureMTC2013

Schritt 4: Offline-Modus

Page 57: Android Real-Life Architecture

Schritt 4: Offline-ModusReal-Life Architecture

MTC2013

Page 58: Android Real-Life Architecture

MTC2013

Offline Modus Best Practices

‣ POIs via Online-Modus abgleichen‣ POIs für Offline-Modus speichern‣ POI UI aktuell halten

‣ Datenzugriff kapseln ‣ Datenzugriff optimieren

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 59: Android Real-Life Architecture

MTC2013

Offline-Modus Pitfalls

‣ Online vs. Offline ‣ Read vs. Write ‣ UI aktuell halten

‣ Testen

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 60: Android Real-Life Architecture

MTC2013

Daten verfügbar machen via ...

SQL & Adapter

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 61: Android Real-Life Architecture

MTC2013 Real-Life Architecture

?

Schritt 4: Offline-Modus

Page 62: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 4: Offline-Modus

Page 63: Android Real-Life Architecture

MTC2013 Real-Life Architecture

PoiVisitations

username, name,

...

AdapterFROM TO

username tx_username

... ...

<Row-Layout />

<ListView>

</ListView>

<Row-Layout />

<Row-Layout />

<LinearLayout>

</Linearlayout>

t_timestamp

tx_name

tx_note

res/layout/row.xmlres/layout/mylist.xml

src/MyAdapter.java src/MyDbHelper.java

Schritt 4: Offline-Modus

Page 64: Android Real-Life Architecture

MTC2013 Real-Life Architecture

public class PositionOverviewActivity extends Activity {

Cursor cursor; ListView listView; PositionOverviewAdapter adapter; FriendFinderData friendFinderData;

static final String[] FROM = { ... }; static final int[] TO = { ... };

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_position_overview); // lookup list view listView = (ListView) findViewById(R.id.list_position_overview);

// lookup data friendFinderData = ((FriendFinderApplication) getApplication()) .getFriendFinderData(); } ...}

Schritt 4: Offline-Modus

Page 65: Android Real-Life Architecture

MTC2013 Real-Life Architecture

public class PositionOverviewActivity extends Activity {

Cursor cursor; ListView listView; PositionOverviewAdapter adapter; FriendFinderData friendFinderData;

...

public void onResume() { super.onResume(); cursor = friendFinderData.getPoiVisitations(); // start managing the cursor startManagingCursor(cursor); // created special adapter adapter = new PositionOverviewAdapter(this, cursor); listView.setAdapter(adapter); } ...}

Schritt 4: Offline-Modus

Page 66: Android Real-Life Architecture

MTC2013 Real-Life Architecture

public class PositionOverviewActivity extends Activity {

Cursor cursor; ListView listView; PositionOverviewAdapter adapter; FriendFinderData friendFinderData;

...

public void onResume() { super.onResume(); cursor = friendFinderData.getPoiVisitations(); // deprecated in Android 4.x startManagingCursor(cursor); // created special adapter adapter = new PositionOverviewAdapter(this, cursor); listView.setAdapter(adapter); } ...}

Schritt 4: Offline-Modus

Page 67: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 4: Offline-Modus

Page 68: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 4: Offline-Modus

Page 69: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 4: Offline-Modus

Page 70: Android Real-Life Architecture

MTC2013

Das kleine Loader 1x1

‣ asynchrones Laden von Daten‣ verfügbar in Activities und Fragments‣ Content-Change-Monitoring der Datensource‣ Reconnection zu vorheriger Position

‣ CursorLoader (für ContentProvider)‣ Loader oder AsyncTaskLoader

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 71: Android Real-Life Architecture

MTC2013// Activity implementing Loader Callbackspublic class MyActivity extends Activity implements LoaderManager.LoaderCallback<Cursor> {

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... adapter = new SimpleCursorAdapter(...) setListAdapter(adapter) getLoaderManager().initLoader(0, null, this); } ...

}

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 72: Android Real-Life Architecture

MTC2013// Activity implementing Loader Callbackspublic class MyActivity extends Activity implements LoaderManager.LoaderCallback<Cursor> {

... // loader was created and is ready to work public Loader<Cursor> onCreateLoader(int id, Bundle args){ // set content provider query URI etc. ... // access content provider return new CursorLoader(this, cpQueryUri, projection, where, whereArgs, sortOrder); } ...}

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 73: Android Real-Life Architecture

MTC2013// Activity implementing Loader Callbackspublic class MyActivity extends Activity implements LoaderManager.LoaderCallback<Cursor> {

... // loader finished loading - data is available public void onLoadFinished(Loader<Cursor> l, Cursor c){ adapter.swapCursor(c); }

// loader was reseted - its data is unavailable public void onLoaderReset(Loader<Cursor> l){ adapter.swapCursor(null); }}

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 74: Android Real-Life Architecture

MTC2013

Loader und ...

‣ Content Provider für Lau‣ SQLite via eigenem AsyncTaskLoader<Cursor>

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 75: Android Real-Life Architecture

MTC2013

Und wie kann ich die DB Daten sehen ...

‣ DB liegt unter /data/data/[mypackage]/databases/[myapp].db

‣ DB Copy auf den Rechner ‣ SQLiteManager PlugIn für Eclipse

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 76: Android Real-Life Architecture

MTC2013

Code Diving ...

Real-Life ArchitectureSchritt 4: Offline-Modus

Page 77: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 5: Mobile Intelligenz

Page 78: Android Real-Life Architecture

Real-Life ArchitectureMTC2013

Schritt 5: Mobile Intelligenz

Page 79: Android Real-Life Architecture

Schritt 5: Mobile IntelligenzReal-Life Architecture

MTC2013

Page 80: Android Real-Life Architecture

MTC2013

Mobile Intelligenz Best Practices

‣ POIs nur senden/abfragen, wenn Internet‣ POIs nur senden/abfragen, wenn Strom‣ UI aktualisieren, wenn neue Daten‣ ...

Real-Life ArchitectureSchritt 5: Mobile Intelligenz

Page 81: Android Real-Life Architecture

MTC2013

Mobile Intelligenz Pitfalls

‣ POIs im günstigsten Moment abfragen‣ Umgebungsänderungen feststellen‣ Zugriffe ausreichend absichern

Real-Life ArchitectureSchritt 5: Mobile Intelligenz

Page 82: Android Real-Life Architecture

MTC2013

Mobile Intelligenz via ...

BroadcastReceiver

Real-Life ArchitectureSchritt 5: Mobile Intelligenz

Page 83: Android Real-Life Architecture

MTC2013

Was sind Broadcast Receiver?

‣ Publisher-Subscriber-Pattern‣ Observer-Pattern

‣ App / System sendet Nachricht‣ Broadcast Receiver hört auf Nachricht

Real-Life ArchitectureSchritt 5: Mobile Intelligenz

Page 84: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 5: Mobile Intelligenz

Page 85: Android Real-Life Architecture

MTC2013

Was helfen uns die Broadcast Receiver?

‣ Service starten sobald Device gebootet ist

‣ auf Internet-Verfügbarkeit reagieren ‣ auf Batteriestatus reagieren

‣ auf neue POIs reagieren

Real-Life ArchitectureSchritt 5: Mobile Intelligenz

Page 86: Android Real-Life Architecture

MTC2013 Real-Life Architecture

public class BootReceiver extends BroadcastReceiver { private static final String TAG = BootReceiver.class.getSimpleName();

// start update service after system start automatically @Override public void onReceive(Context context, Intent intent) { context.startService(new Intent(context, UpdaterService.class)); Log.d(TAG, "onReceived"); }}

‣ Service starten sobald Devices gebootet ist

Schritt 5: Mobile Intelligenz

Page 87: Android Real-Life Architecture

MTC2013 Real-Life Architecture

<!-- AndroidManifest.xml -->

...

<receiver android:name=".BootReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter></receiver>

<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

...

Schritt 5: Mobile Intelligenz

Page 88: Android Real-Life Architecture

MTC2013 Real-Life Architecture

public class NetworkReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { // check if network is available boolean isNetworkDown = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); if (isNetworkDown) { context.stopService(new Intent(context, UpdaterService.class)); } else { context.startService(new Intent(context, UpdaterService.class)); } }}

‣ auf Internet-Verfügbarkeit reagieren

Schritt 5: Mobile Intelligenz

Page 89: Android Real-Life Architecture

MTC2013 Real-Life Architecture

<!-- AndroidManifest.xml -->

...

<receiver android:name=".NetworkReceiver" > <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter></receiver>

<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

...

Schritt 5: Mobile Intelligenz

Page 90: Android Real-Life Architecture

MTC2013 Real-Life Architecture

public class PositionOverviewActivity extends BaseActivity { static final String SEND_LOCATION_UPDATE_NOTIFICATION = "de.openknowledge.mtc.ff.SEND_LOCATION_UPDATE_NOTIFICATION"; ...

class PositionOverviewReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { LoaderManager lm = getLoaderManager(); lm.restartLoader(0, null, PositionOverviewActivity.this); } }}

‣ auf neue POIs reagieren

Schritt 5: Mobile Intelligenz

Page 91: Android Real-Life Architecture

MTC2013 Real-Life Architecture

<!-- AndroidManifest.xml -->

...

<permission android:name="de.openknowledge.mtc.ff.SEND_LOCATION_UPDATE_NOTIFICATION" android:description="@string/send_location_update_notification_permission_description" android:label="@string/send_location_update_notification_permission_label" android:permissionGroup="android.permission-group.PERSONAL_INFO" android:protectionLevel="normal" />

<permission android:name="de.openknowledge.mtc.ff.RECEIVE_LOCATION_UPDATE_NOTIFICATION" android:description="@string/receive_location_update_notification_permission_description" android:label="@string/receive_location_update_notification_permission_label" android:permissionGroup="android.permission-group.PERSONAL_INFO" android:protectionLevel="normal" />

<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<uses-permission android:name="de.openknowledge.mtc.ff.SEND_LOCATION_UPDATE_NOTIFICATION" /> <uses-permission android:name="de.openknowledge.mtc.ff.RECEIVE_LOCATION_UPDATE_NOTIFICATION" />

...

Schritt 5: Mobile Intelligenz

Page 92: Android Real-Life Architecture

MTC2013

Code Diving ...

Real-Life ArchitectureSchritt 5: Mobile Intelligenz

Page 93: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 6: Externer Datenzugriff

Page 94: Android Real-Life Architecture

Real-Life ArchitectureMTC2013

Schritt 6: Externer Datenzugriff

Page 95: Android Real-Life Architecture

Schritt 6: Externer DatenzugriffReal-Life Architecture

MTC2013

Page 96: Android Real-Life Architecture

MTC2013

Externer Datenzugriff Best Practices

‣ Content Provider zur Datenbereitstellung‣Widget / App zur Datennutzung

Real-Life ArchitectureSchritt 6: Externer Datenzugriff

Page 97: Android Real-Life Architecture

MTC2013

Externer Datenzugriff Pitfalls

‣ Lesen vs. Schreiben‣ Security Defaults‣ Android 2.x vs. Android 4.x

Real-Life ArchitectureSchritt 6: Externer Datenzugriff

Page 98: Android Real-Life Architecture

MTC2013

Daten verfügbar machen via ...

ContentProvider

Real-Life ArchitectureSchritt 6: Externer Datenzugriff

Page 99: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 6: Externer Datenzugriff

Page 100: Android Real-Life Architecture

MTC2013 Real-Life Architecture

<!-- AndroidManifest.xml -->

...

<provider android:name =".PositionProvider" android:authorities ="de.openknowledge.mtc.ff.poi" />

...

Schritt 6: Externer Datenzugriff

Page 101: Android Real-Life Architecture

MTC2013 Real-Life Architecture

<!-- AndroidManifest.xml -->

...

<provider android:name =".PositionProvider" android:authorities ="de.openknowledge.mtc.ff.poi" />

...

Öffentlich?

Lesen vs. Schreiben?

Schritt 6: Externer Datenzugriff

Page 102: Android Real-Life Architecture

MTC2013 Real-Life Architecture

<!-- AndroidManifest.xml -->

...

<provider android:name =".PositionProvider" android:authorities ="de.openknowledge.mtc.ff.poi" android:exported ="true" android:readPermission ="de.openknowledge.mtc.ff.poi.READ_DATA" /> ...

Schritt 6: Externer Datenzugriff

Page 103: Android Real-Life Architecture

MTC2013

Code Diving ...

Real-Life ArchitectureSchritt 6: Externer Datenzugriff

Page 104: Android Real-Life Architecture

MTC2013 Real-Life Architecture

Schritt 7: Standorte anzeigen

Page 105: Android Real-Life Architecture

Real-Life ArchitectureMTC2013

Schritt 7: Standorte anzeigen

Page 106: Android Real-Life Architecture

MTC2013

Standorte anzeigen Best Practices

‣ Interaktive Karte‣ eigenen Standort hervorheben‣ Detailinfos beim „Anklicken“‣ User Controlls

Real-Life ArchitectureSchritt 7: Standorte anzeigen

Page 107: Android Real-Life Architecture

MTC2013

Standorte anzeigen Pitfalls

‣ Google Maps v2‣ Google Play Service‣ Emulator

Real-Life ArchitectureSchritt 7: Standorte anzeigen

Page 108: Android Real-Life Architecture

MTC2013

Standorte anzeigen via ...

GoogleMaps API v2

Real-Life ArchitectureSchritt 7: Standorte anzeigen

Page 109: Android Real-Life Architecture

Real-Life ArchitectureMTC2013

Schritt 7: Google Maps API v2

Page 110: Android Real-Life Architecture

MTC2013

Google Maps v2 Pitfalls

‣ API laden via Google Play Service‣ Google Maps API Key generieren‣Manifest.xml anpassen ‣Map Fragment „bauen“‣Map Activity implementieren

Schritt 7: Google Maps API v2Real-Life Architecture

Page 111: Android Real-Life Architecture

MTC2013

Google Maps v2 Pitfalls

‣ API laden via Google Play Service‣ Google Maps API Key generieren‣Manifest.xml anpassen ‣Map Fragment „bauen“‣Map Activity implementieren‣ ... sie sehen, sie sehen nix (im Emulator)

Schritt 7: Google Maps API v2Real-Life Architecture

Page 112: Android Real-Life Architecture

MTC2013

Google Maps v2 Pitfalls

‣ API laden via Google Play Service‣ Google Maps API Key generieren‣Manifest.xml anpassen ‣Map Fragment „bauen“‣Map Activity implementieren‣ ... sie sehen, sie sehen nix (im Emulator)

Schritt 7: Google Maps API v2Real-Life Architecture

adb -e install com.google.android.gms.apk

adb -e install com.android.vending.apk

Page 113: Android Real-Life Architecture

MTC2013

Code Diving ...

Schritt 7: Google Maps API v2Real-Life Architecture

Page 114: Android Real-Life Architecture

Pho

to c

redi

t: S

antiM

B .

/ Fot

er.c

om /

CC

BY-

NC

-ND

Real-Life Architecture

@mobileLarson @_openKnowledge

Lars Röwekamp | CIO New Technologies


Recommended