SlideShare a Scribd company logo
1 of 37
Download to read offline
Pushing the Limits
Erik Hellman, Spotify
google.com/+ErikHellman
@ErikHellman
Android
Programming
2
wiley.com/go/ptl/androidprogramming
3
Improved memory management
Efficient multi-threading and -processing
Using Android components correctly
Improved memory management
4
Use a static factory method whenever possible
5
Effective Java (2nd ed.): Item 1!
“A second advantage of static factory methods is that,
unlike constructors, they are not required to create a
new object each time they’re invoked.”
Message.java
6
public	
  final	
  class	
  Message	
  implements	
  Parcelable	
  {	
  
	
  	
  	
  	
  /*package*/	
  Message	
  next;	
  
!
	
  	
  	
  	
  private	
  static	
  final	
  Object	
  sPoolSync	
  =	
  new	
  Object();	
  
	
  	
  	
  	
  private	
  static	
  Message	
  sPool;	
  
	
  	
  	
  	
  private	
  static	
  int	
  sPoolSize	
  =	
  0;	
  
!
	
  	
  	
  	
  private	
  static	
  final	
  int	
  MAX_POOL_SIZE	
  =	
  50;	
  
!
	
  	
  	
  	
  public	
  static	
  Message	
  obtain()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  synchronized	
  (sPoolSync)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (sPool	
  !=	
  null)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Message	
  m	
  =	
  sPool;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  sPool	
  =	
  m.next;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  m.next	
  =	
  null;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  sPoolSize-­‐-­‐;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  m;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  new	
  Message();	
  
	
  	
  	
  	
  }
	
  	
  	
  public	
  void	
  recycle()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  clearForRecycle();	
  
!
	
  	
  	
  	
  	
  	
  	
  	
  synchronized	
  (sPoolSync)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (sPoolSize	
  <	
  MAX_POOL_SIZE)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  next	
  =	
  sPool;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  sPool	
  =	
  this;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  sPoolSize++;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  }	
  
}	
  
How to get more memory - Part 1
7
<application	
  
	
  	
  	
  	
  android:allowBackup="true"	
  
	
  	
  	
  	
  android:icon="@drawable/ic_launcher"	
  
	
  	
  	
  	
  android:label="@string/app_name"	
  
	
  	
  	
  	
  android:name=".MyApplication"	
  
	
  	
  	
  	
  android:largeHeap="true"	
  
	
  	
  	
  	
  android:theme="@style/AppTheme"	
  >	
  
	
  	
  	
  	
  …	
  
</application>
How to get more memory - Part 2
8
<service	
  
	
  	
  	
  	
  android:name="se.hellsoft.apptl.app.MyService"	
  
	
  	
  	
  	
  android:enabled="true"	
  
	
  	
  	
  	
  android:exported="false"	
  
	
  	
  	
  	
  android:process="se.hellsoft.apptl.service">	
  
</service>
How to get more memory - Part 3
9
data	
  =	
  malloc(sizeof(data_struct));
10
Improved memory management
Efficient multi-threading and -processing
Using Android components correctly
11
Always use a Handler!*
* Except when you shouldn’t…
@Override	
  
protected	
  void	
  onCreate(Bundle	
  savedInstanceState)	
  {	
  
	
  	
  	
  	
  super.onCreate(savedInstanceState);	
  
	
  	
  	
  	
  HandlerThread	
  backgroundThread	
  =	
  new	
  HandlerThread("background");	
  
	
  	
  	
  	
  backgroundThread.start();	
  
	
  	
  	
  	
  mBackgroundHandler	
  =	
  new	
  Handler(backgroundThread.getLooper(),	
  this);	
  
	
  	
  	
  	
  mUiHandler	
  =	
  new	
  Handler(this);	
  
}	
  
!
@Override	
  
protected	
  void	
  onDestroy()	
  {	
  
	
  	
  	
  	
  super.onDestroy();	
  
	
  	
  	
  	
  mBackgroundHandler.removeCallbacksAndMessages(null);	
  
	
  	
  	
  	
  mBackgroundHandler.getLooper().quit();	
  
}
12
Always use a Handler!*
* Except when you shouldn’t…
public	
  void	
  onStartBackgroundJob(View	
  view)	
  {	
  
	
  	
  	
  	
  mBackgroundHandler.obtainMessage(BACKGROUND_JOB).sendToTarget();	
  
}	
  
!
@Override	
  
public	
  boolean	
  handleMessage(Message	
  msg)	
  {	
  
	
  	
  	
  	
  switch	
  (msg.what)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  case	
  BACKGROUND_JOB:	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Bitmap	
  result	
  =	
  null;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  Processing	
  goes	
  here...	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  mUiHandler.obtainMessage(UPDATE_UI,	
  result).sendToTarget();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  break;	
  
	
  	
  	
  	
  	
  	
  	
  	
  case	
  UPDATE_UI:	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ((ImageView)	
  findViewById(R.id.photo))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  .setImageBitmap((Bitmap)	
  msg.obj);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  break;	
  
	
  	
  	
  	
  }	
  
	
  	
  	
  	
  return	
  true;	
  
}	
  
Why Handler?
13
•Scheduling of messages

•Cancelling of messages

•Reduces GC calls
Using the process attribute
14
Why a separate process?
15
•Better isolation from crashes

•Binder transactions uses a thread pool

•Double the memory!
16
Improved memory management
Efficient multi-threading and -processing
Using Android components correctly
Application component
17
<application	
  
	
  	
  	
  	
  android:allowBackup="true"	
  
	
  	
  	
  	
  android:icon="@drawable/ic_launcher"	
  
	
  	
  	
  	
  android:label="@string/app_name"	
  
	
  	
  	
  	
  android:name=“.MyApplication"	
  
	
  	
  	
  	
  android:theme="@style/AppTheme"	
  >	
  
!
	
  	
  	
  	
  	
  	
  	
  	
  ...	
  
</application>
Android Singletons using Context
18
public	
  class	
  MySingleton	
  {	
  
	
  	
  	
  	
  private	
  static	
  MySingleton	
  sInstance;	
  
	
  	
  	
  	
  private	
  Context	
  mContext;	
  
!
	
  	
  	
  	
  private	
  MySingleton(Context	
  context)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  mContext	
  =	
  context;	
  
	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  
	
  	
  	
  	
  public	
  MySingleton	
  getInstance(Context	
  context)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  if(sInstance	
  ==	
  null)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  sInstance	
  =	
  new	
  MySingleton(context.getApplicationContext());	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  sInstance;	
  
	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  
	
  	
  	
  	
  public	
  void	
  doStuffThatRequireContext()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  //	
  Do	
  stuff	
  here...	
  
	
  	
  	
  	
  }	
  
}	
  
Application Context limitations
19
•Inflating layout uses default theme

•Starting Activity creates a new task
20
Activity - saving state
Activity.onSaveInstanceState()
Activity.onPause()
or
21
onSaveInstanceState() is not called…
•…when user presses back

•…when you call Activity.finish()
22
Fragment
23
android.app.Fragment
android.support.v4.app.Fragment
or
Support library can be upgraded!
24
dependencies	
  {	
  
	
  	
  	
  	
  compile	
  'com.android.support:appcompat-­‐v7:+'	
  
	
  	
  	
  	
  compile	
  'com.android.support:support-­‐v4:19.1.+'	
  
	
  	
  	
  	
  compile	
  fileTree(dir:	
  'libs',	
  include:	
  ['*.jar'])	
  
}	
  
Typical Fragment crash
25
public	
  static	
  class	
  FirstFragment	
  extends	
  Fragment	
  {	
  
	
  	
  	
  	
  private	
  ImageView	
  mImageView;	
  
!
	
  	
  	
  	
  @Override	
  
	
  	
  	
  	
  public	
  View	
  onCreateView(LayoutInflater	
  inflater,	
  ViewGroup	
  container,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Bundle	
  savedInstanceState)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  View	
  rootView	
  =	
  inflater.inflate(R.layout.fragment_main,	
  container,	
  false);	
  
	
  	
  	
  	
  	
  	
  	
  	
  mImageView	
  =	
  (ImageView)	
  rootView.findViewById(R.id.photo);	
  
!
	
  	
  	
  	
  	
  	
  	
  	
  new	
  AsyncTask<Void,	
  Void,	
  Bitmap>()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  @Override	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  protected	
  Bitmap	
  doInBackground(Void...	
  params)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  SystemClock.sleep(10000);	
  //	
  Fake	
  long	
  processing...	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  BitmapFactory.decodeResource(getResources(),	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  R.drawable.happy_android);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
!
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  @Override	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  protected	
  void	
  onPostExecute(Bitmap	
  bitmap)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  mImageView.setImageBitmap(bitmap);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  }.execute();	
  
!
	
  	
  	
  	
  	
  	
  	
  	
  return	
  rootView;	
  
	
  	
  	
  	
  }	
  
}
Typical Fragment crash
26
E/AndroidRuntime(	
  1245):	
  FATAL	
  EXCEPTION:	
  AsyncTask	
  #1	
  
E/AndroidRuntime(	
  1245):	
  Process:	
  se.hellsoft.apptl.app,	
  PID:	
  1245	
  
E/AndroidRuntime(	
  1245):	
  java.lang.RuntimeException:	
  An	
  error	
  occured	
  while	
  executing	
  doInBackground()	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  android.os.AsyncTask$3.done(AsyncTask.java:300)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  java.util.concurrent.FutureTask.setException(FutureTask.java:222)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  java.util.concurrent.FutureTask.run(FutureTask.java:242)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  java.lang.Thread.run(Thread.java:841)	
  
E/AndroidRuntime(	
  1245):	
  Caused	
  by:	
  java.lang.IllegalStateException:	
  Fragment	
  FirstFragment{52836468}	
  not	
  attached	
  
to	
  Activity	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  android.support.v4.app.Fragment.getResources(Fragment.java:601)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  se.hellsoft.apptl.app.MainActivity$FirstFragment
$1.doInBackground(MainActivity.java:115)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  se.hellsoft.apptl.app.MainActivity$FirstFragment
$1.doInBackground(MainActivity.java:109)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  android.os.AsyncTask$2.call(AsyncTask.java:288)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  at	
  java.util.concurrent.FutureTask.run(FutureTask.java:237)	
  
E/AndroidRuntime(	
  1245):	
  	
  	
  	
  	
  ...	
  4	
  more
27
Use a Loader whenever possible and
cancel remaining requests in onPause()/onDetach()!
Binding to Services
28
@Override	
  
public	
  IBinder	
  onBind(Intent	
  intent)	
  {	
  
	
   return	
  null;	
  //	
  NEVER	
  do	
  this	
  
}
Binding to Services
29
@Override	
  
public	
  IBinder	
  onBind(Intent	
  intent)	
  {	
  
	
   String	
  action	
  =	
  intent.getAction();	
  
	
   if(ACTION_FIRST_BINDER.equals(action))	
  {	
  
	
   	
   return	
  mFirstBinder;	
  
	
   }	
  else	
  if(ACTION_SECOND_BINDER.equals(action))	
  {	
  
	
   	
   return	
  mSecondBinder;	
  
	
   }	
  else	
  {	
  
	
   	
   throw	
  new	
  RuntimeException("Unexpected	
  error!");	
  
	
   }	
  
}	
  
Binding to Services
30
@Override	
  
public	
  IBinder	
  onBind(Intent	
  intent)	
  {	
  
	
   Uri	
  data	
  =	
  intent.getData();	
  
	
   String	
  param	
  =	
  data.getQueryParameter("param");	
  
	
   if(FIRST_BINDER.equals(param))	
  {	
  
	
   	
   return	
  mFirstBinder;	
  
	
   }	
  else	
  if(SECOND_BINDER.equals(param))	
  {	
  
	
   	
   return	
  mSecondBinder;	
  
	
   }	
  else	
  {	
  
	
   	
   throw	
  new	
  RuntimeException("Unexpected	
  error!:");	
  
	
   }	
  
}	
  
Service considerations
31
•A binder Intent is identified by the action string and data Uri!
!
•onBind() and onUnbind() only called once per unique
Intent

•START_STICKY will give a null	
  Intent when Service is
restarted by the system

•Binder calls run on local thread for process-local service
Most common ContentProvider mistake :)
32
@Override	
  
public	
  Cursor	
  query(Uri	
  uri,	
  String[]	
  projection,	
  String	
  selection,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  String[]	
  selectionArgs,	
  String	
  sortOrder)	
  {	
  
	
  	
  	
  	
  SQLiteDatabase	
  db	
  =	
  mDatabaseHelper.getReadableDatabase();	
  
	
  	
  	
  	
  int	
  match	
  =	
  sUriMatcher.match(uri);	
  
	
  	
  	
  	
  Cursor	
  cursor	
  =	
  null;	
  
	
  	
  	
  	
  switch	
  (match)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  case	
  ALL_ROWS:	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cursor	
  =	
  db.query(Contract.TABLE_NAME,	
  projection,	
  selection,	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  selectionArgs,	
  "",	
  "",	
  sortOrder);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  break;	
  
	
  	
  	
  	
  	
  	
  	
  	
  case	
  SINGLE_ROW:	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  String	
  id	
  =	
  uri.getLastPathSegment();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cursor	
  =	
  	
  db.query(Contract.TABLE_NAME,	
  projection,	
  "_id	
  =	
  ?",	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  new	
  String[]{id},	
  "",	
  "",	
  sortOrder);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  break;	
  
	
  	
  	
  	
  }	
  
	
  	
  	
  	
  if(cursor	
  !=	
  null)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  cursor.setNotificationUri(getContext().getContentResolver(),	
  uri);	
  
	
  	
  	
  	
  }	
  
	
  	
  	
  	
  return	
  cursor;	
  
}
Most common ContentProvider mistake :)
33
@Override	
  
public	
  Uri	
  insert(Uri	
  uri,	
  ContentValues	
  values)	
  {	
  
	
  	
  	
  SQLiteDatabase	
  db	
  =	
  mDatabaseHelper.getWritableDatabase();	
  
	
  	
  	
  	
  int	
  match	
  =	
  sUriMatcher.match(uri);	
  
	
  	
  	
  	
  switch	
  (match)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  case	
  ALL_ROWS:	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  long	
  newId	
  =	
  db.insert(Contract.TABLE_NAME,	
  "",	
  values);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if(newId	
  !=	
  -­‐1)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  getContext().getContentResolver().notifyChange(uri,	
  null);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  Uri.withAppendedPath(uri,	
  String.valueOf(newId));	
  
	
  	
  	
  	
  	
  	
  	
  	
  default:	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  null;	
  
	
  	
  	
  	
  }	
  
}
Don’t forget bulkInsert() !!!
34
@Override	
  
public	
  int	
  bulkInsert(Uri	
  uri,	
  ContentValues[]	
  values)	
  {	
  
	
  	
  	
  	
  SQLiteDatabase	
  db	
  =	
  mDatabaseHelper.getWritableDatabase();	
  
	
  	
  	
  	
  int	
  match	
  =	
  sUriMatcher.match(uri);	
  
	
  	
  	
  	
  int	
  inserted	
  =	
  0;	
  
	
  	
  	
  	
  switch	
  (match)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  case	
  TASKS_CODE:	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  try	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  db.beginTransaction();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  for	
  (ContentValues	
  value	
  :	
  values)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  long	
  id	
  =	
  db.insert(Contract.TABLE_NAME,	
  "",	
  value);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (id	
  <=	
  0)	
  throw	
  new	
  SQLException("Failed	
  with	
  inserting.");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  inserted++;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  db.setTransactionSuccessful();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  getContext().getContentResolver().notifyChange(uri,	
  null);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  finally	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  db.endTransaction();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  }	
  
	
  	
  	
  	
  return	
  inserted;	
  
}	
  
Useful Broadcasts - Auto-starting
35
<receiver	
  android:name="se.hellsoft.myapp.AutoStartReceiver"	
  >	
  
	
  	
  	
  	
  <intent-­‐filter>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <action	
  android:name="android.intent.action.BOOT_COMPLETED"	
  />	
  
	
  	
  	
  </intent-­‐filter>	
  
</receiver>	
  
<receiver	
  android:name=“se.hellsoft.myapp.AutoStartReceiver"	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  android:process=“:autostarter”>	
  
	
  	
  	
  	
  <intent-­‐filter>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <action	
  android:name="android.intent.action.USER_PRESENT"	
  />	
  
	
  	
  	
  </intent-­‐filter>	
  
</receiver>	
  
Useful Broadcasts - Monitoring the network
36
<receiver	
  android:name=“se.hellsoft.myapp.NetworkMonitor">	
  
	
  	
  	
  	
  <intent-­‐filter>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <action	
  android:name="android.net.conn.CONNECTIVITY_CHANGE"	
  />	
  
	
  	
  	
  	
  	
  	
  	
  	
  <action	
  android:name="android.net.wifi.supplicant.CONNECTION_CHANGE"	
  />	
  
	
  	
  	
  	
  	
  	
  	
  	
  <action	
  android:name="android.net.wifi.WIFI_AP_STATE_CHANGED"	
  />	
  
	
  	
  	
  </intent-­‐filter>	
  
</receiver>	
  
37
“Many problems with Android apps can be fixed with 

a proper use of the Handler class.”
- Erik Hellman
Get my book at wiley.com/go/ptl/androidprogramming

More Related Content

What's hot

Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.x
Tatsuya Maki
 
Google Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification GoogleGoogle Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification Google
Mathias Seguy
 

What's hot (20)

Using hilt in a modularized project
Using hilt in a modularized projectUsing hilt in a modularized project
Using hilt in a modularized project
 
Advanced Dagger talk from 360andev
Advanced Dagger talk from 360andevAdvanced Dagger talk from 360andev
Advanced Dagger talk from 360andev
 
Android dev toolbox
Android dev toolboxAndroid dev toolbox
Android dev toolbox
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
 
Maintainable JavaScript 2011
Maintainable JavaScript 2011Maintainable JavaScript 2011
Maintainable JavaScript 2011
 
Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016
 
Testing Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJavaTesting Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJava
 
Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.x
 
Managing parallelism using coroutines
Managing parallelism using coroutinesManaging parallelism using coroutines
Managing parallelism using coroutines
 
Google Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification GoogleGoogle Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification Google
 
Reactive, component 그리고 angular2
Reactive, component 그리고  angular2Reactive, component 그리고  angular2
Reactive, component 그리고 angular2
 
Code to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern ApplicationsCode to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern Applications
 
Performance #1: Memory
Performance #1: MemoryPerformance #1: Memory
Performance #1: Memory
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-Programming
 
Java Quiz - Meetup
Java Quiz - MeetupJava Quiz - Meetup
Java Quiz - Meetup
 
Sane Async Patterns
Sane Async PatternsSane Async Patterns
Sane Async Patterns
 
Alexey Buzdin "Maslow's Pyramid of Android Testing"
Alexey Buzdin "Maslow's Pyramid of Android Testing"Alexey Buzdin "Maslow's Pyramid of Android Testing"
Alexey Buzdin "Maslow's Pyramid of Android Testing"
 
Arquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com JetpackArquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com Jetpack
 
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, howTomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and Performance
 

Viewers also liked

Froyo to kit kat two years developing & maintaining deliradio
Froyo to kit kat   two years developing & maintaining deliradioFroyo to kit kat   two years developing & maintaining deliradio
Froyo to kit kat two years developing & maintaining deliradio
Droidcon Berlin
 
20140508 quantified self droidcon
20140508 quantified self droidcon20140508 quantified self droidcon
20140508 quantified self droidcon
Droidcon Berlin
 
Android System Design And Power Management
Android System Design And Power ManagementAndroid System Design And Power Management
Android System Design And Power Management
Nilay Mishra
 
How to Lower Android Power Consumption Without Affecting Performance
How to Lower Android Power Consumption Without Affecting PerformanceHow to Lower Android Power Consumption Without Affecting Performance
How to Lower Android Power Consumption Without Affecting Performance
rickschwar
 
Android power management
Android power managementAndroid power management
Android power management
Jerrin George
 

Viewers also liked (20)

crashing in style
crashing in stylecrashing in style
crashing in style
 
Froyo to kit kat two years developing & maintaining deliradio
Froyo to kit kat   two years developing & maintaining deliradioFroyo to kit kat   two years developing & maintaining deliradio
Froyo to kit kat two years developing & maintaining deliradio
 
20140508 quantified self droidcon
20140508 quantified self droidcon20140508 quantified self droidcon
20140508 quantified self droidcon
 
Android 电源管理 power_management_(英文版)
Android 电源管理 power_management_(英文版)Android 电源管理 power_management_(英文版)
Android 电源管理 power_management_(英文版)
 
An Introduction To Android
An Introduction To AndroidAn Introduction To Android
An Introduction To Android
 
Android System Design And Power Management
Android System Design And Power ManagementAndroid System Design And Power Management
Android System Design And Power Management
 
Power management android
Power management androidPower management android
Power management android
 
Android power management, current and future trends
Android power management, current and future trendsAndroid power management, current and future trends
Android power management, current and future trends
 
How to Lower Android Power Consumption Without Affecting Performance
How to Lower Android Power Consumption Without Affecting PerformanceHow to Lower Android Power Consumption Without Affecting Performance
How to Lower Android Power Consumption Without Affecting Performance
 
Android Platform Overview - Azercell Barama
Android Platform Overview - Azercell BaramaAndroid Platform Overview - Azercell Barama
Android Platform Overview - Azercell Barama
 
Android power management
Android power managementAndroid power management
Android power management
 
Android internals 09 - Sensors, Power Management, Input subsystem, Data stora...
Android internals 09 - Sensors, Power Management, Input subsystem, Data stora...Android internals 09 - Sensors, Power Management, Input subsystem, Data stora...
Android internals 09 - Sensors, Power Management, Input subsystem, Data stora...
 
Android
AndroidAndroid
Android
 
Android Accessibility - The missing manual
Android Accessibility - The missing manualAndroid Accessibility - The missing manual
Android Accessibility - The missing manual
 
Seminar android presentation
Seminar android presentationSeminar android presentation
Seminar android presentation
 
Android seminar report
Android seminar reportAndroid seminar report
Android seminar report
 
Android Platform Architecture
Android Platform ArchitectureAndroid Platform Architecture
Android Platform Architecture
 
Mobile operating systems
Mobile operating systemsMobile operating systems
Mobile operating systems
 
Android IPC Mechanism
Android IPC MechanismAndroid IPC Mechanism
Android IPC Mechanism
 
Scheduling in Android
Scheduling in AndroidScheduling in Android
Scheduling in Android
 

Similar to Android programming -_pushing_the_limits

Mobile Software Engineering Crash Course - C04 Android Cont.
Mobile Software Engineering Crash Course - C04 Android Cont.Mobile Software Engineering Crash Course - C04 Android Cont.
Mobile Software Engineering Crash Course - C04 Android Cont.
Mohammad Shaker
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
Yekmer Simsek
 
BlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorksBlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorks
mwbrooks
 

Similar to Android programming -_pushing_the_limits (20)

Android workshop
Android workshopAndroid workshop
Android workshop
 
Android Froyo
Android FroyoAndroid Froyo
Android Froyo
 
Mobile Software Engineering Crash Course - C04 Android Cont.
Mobile Software Engineering Crash Course - C04 Android Cont.Mobile Software Engineering Crash Course - C04 Android Cont.
Mobile Software Engineering Crash Course - C04 Android Cont.
 
Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 
Android session-5-sajib
Android session-5-sajibAndroid session-5-sajib
Android session-5-sajib
 
Android - Api & Debugging in Android
Android - Api & Debugging in AndroidAndroid - Api & Debugging in Android
Android - Api & Debugging in Android
 
Titanium appcelerator best practices
Titanium appcelerator best practicesTitanium appcelerator best practices
Titanium appcelerator best practices
 
performance optimization: Memory
performance optimization: Memoryperformance optimization: Memory
performance optimization: Memory
 
BlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorksBlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorks
 
Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in Heaven
 
Modern Android app library stack
Modern Android app library stackModern Android app library stack
Modern Android app library stack
 
Android Apps the Right Way
Android Apps the Right WayAndroid Apps the Right Way
Android Apps the Right Way
 
Naive application development
Naive application developmentNaive application development
Naive application development
 
Pro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptPro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScript
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
 
Session 9 Android Web Services - Part 2.pdf
Session 9 Android Web Services - Part 2.pdfSession 9 Android Web Services - Part 2.pdf
Session 9 Android Web Services - Part 2.pdf
 
Best practices android_2010
Best practices android_2010Best practices android_2010
Best practices android_2010
 
Lightning Talk - Xamarin
Lightning Talk - Xamarin Lightning Talk - Xamarin
Lightning Talk - Xamarin
 
Android: the Single Activity, Multiple Fragments pattern | One Activity to ru...
Android: the Single Activity, Multiple Fragments pattern | One Activity to ru...Android: the Single Activity, Multiple Fragments pattern | One Activity to ru...
Android: the Single Activity, Multiple Fragments pattern | One Activity to ru...
 

More from Droidcon Berlin

Droidcon de 2014 google cast
Droidcon de 2014   google castDroidcon de 2014   google cast
Droidcon de 2014 google cast
Droidcon Berlin
 
Android industrial mobility
Android industrial mobility Android industrial mobility
Android industrial mobility
Droidcon Berlin
 
From sensor data_to_android_and_back
From sensor data_to_android_and_backFrom sensor data_to_android_and_back
From sensor data_to_android_and_back
Droidcon Berlin
 
new_age_graphics_android_x86
new_age_graphics_android_x86new_age_graphics_android_x86
new_age_graphics_android_x86
Droidcon Berlin
 
Testing and Building Android
Testing and Building AndroidTesting and Building Android
Testing and Building Android
Droidcon Berlin
 
Matchinguu droidcon presentation
Matchinguu droidcon presentationMatchinguu droidcon presentation
Matchinguu droidcon presentation
Droidcon Berlin
 
Cgm life sdk_droidcon_2014_v3
Cgm life sdk_droidcon_2014_v3Cgm life sdk_droidcon_2014_v3
Cgm life sdk_droidcon_2014_v3
Droidcon Berlin
 
The artofcalabash peterkrauss
The artofcalabash peterkraussThe artofcalabash peterkrauss
The artofcalabash peterkrauss
Droidcon Berlin
 
Raesch, gries droidcon 2014
Raesch, gries   droidcon 2014Raesch, gries   droidcon 2014
Raesch, gries droidcon 2014
Droidcon Berlin
 
Android open gl2_droidcon_2014
Android open gl2_droidcon_2014Android open gl2_droidcon_2014
Android open gl2_droidcon_2014
Droidcon Berlin
 
Tuning android for low ram devices
Tuning android for low ram devicesTuning android for low ram devices
Tuning android for low ram devices
Droidcon Berlin
 
Droidcon2013 security genes_trendmicro
Droidcon2013 security genes_trendmicroDroidcon2013 security genes_trendmicro
Droidcon2013 security genes_trendmicro
Droidcon Berlin
 
Droidcon2013 commercialsuccess rannenberg
Droidcon2013 commercialsuccess rannenbergDroidcon2013 commercialsuccess rannenberg
Droidcon2013 commercialsuccess rannenberg
Droidcon Berlin
 
Droidcon2013 bootstrap luedeke
Droidcon2013 bootstrap luedekeDroidcon2013 bootstrap luedeke
Droidcon2013 bootstrap luedeke
Droidcon Berlin
 
Droidcon2013 app analytics_huber_1und1
Droidcon2013  app analytics_huber_1und1Droidcon2013  app analytics_huber_1und1
Droidcon2013 app analytics_huber_1und1
Droidcon Berlin
 
Droidcon2013 facebook stewart
Droidcon2013 facebook stewartDroidcon2013 facebook stewart
Droidcon2013 facebook stewart
Droidcon Berlin
 
Droidcon 2013 ui smartphones tam hanna
Droidcon 2013 ui smartphones tam hannaDroidcon 2013 ui smartphones tam hanna
Droidcon 2013 ui smartphones tam hanna
Droidcon Berlin
 

More from Droidcon Berlin (20)

Droidcon de 2014 google cast
Droidcon de 2014   google castDroidcon de 2014   google cast
Droidcon de 2014 google cast
 
Raspberry Pi
Raspberry PiRaspberry Pi
Raspberry Pi
 
Android industrial mobility
Android industrial mobility Android industrial mobility
Android industrial mobility
 
Details matter in ux
Details matter in uxDetails matter in ux
Details matter in ux
 
From sensor data_to_android_and_back
From sensor data_to_android_and_backFrom sensor data_to_android_and_back
From sensor data_to_android_and_back
 
new_age_graphics_android_x86
new_age_graphics_android_x86new_age_graphics_android_x86
new_age_graphics_android_x86
 
5 tips of monetization
5 tips of monetization5 tips of monetization
5 tips of monetization
 
Testing and Building Android
Testing and Building AndroidTesting and Building Android
Testing and Building Android
 
Matchinguu droidcon presentation
Matchinguu droidcon presentationMatchinguu droidcon presentation
Matchinguu droidcon presentation
 
Cgm life sdk_droidcon_2014_v3
Cgm life sdk_droidcon_2014_v3Cgm life sdk_droidcon_2014_v3
Cgm life sdk_droidcon_2014_v3
 
The artofcalabash peterkrauss
The artofcalabash peterkraussThe artofcalabash peterkrauss
The artofcalabash peterkrauss
 
Raesch, gries droidcon 2014
Raesch, gries   droidcon 2014Raesch, gries   droidcon 2014
Raesch, gries droidcon 2014
 
Android open gl2_droidcon_2014
Android open gl2_droidcon_2014Android open gl2_droidcon_2014
Android open gl2_droidcon_2014
 
Tuning android for low ram devices
Tuning android for low ram devicesTuning android for low ram devices
Tuning android for low ram devices
 
Droidcon2013 security genes_trendmicro
Droidcon2013 security genes_trendmicroDroidcon2013 security genes_trendmicro
Droidcon2013 security genes_trendmicro
 
Droidcon2013 commercialsuccess rannenberg
Droidcon2013 commercialsuccess rannenbergDroidcon2013 commercialsuccess rannenberg
Droidcon2013 commercialsuccess rannenberg
 
Droidcon2013 bootstrap luedeke
Droidcon2013 bootstrap luedekeDroidcon2013 bootstrap luedeke
Droidcon2013 bootstrap luedeke
 
Droidcon2013 app analytics_huber_1und1
Droidcon2013  app analytics_huber_1und1Droidcon2013  app analytics_huber_1und1
Droidcon2013 app analytics_huber_1und1
 
Droidcon2013 facebook stewart
Droidcon2013 facebook stewartDroidcon2013 facebook stewart
Droidcon2013 facebook stewart
 
Droidcon 2013 ui smartphones tam hanna
Droidcon 2013 ui smartphones tam hannaDroidcon 2013 ui smartphones tam hanna
Droidcon 2013 ui smartphones tam hanna
 

Recently uploaded

Breaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdfBreaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
UK Journal
 

Recently uploaded (20)

Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
 
WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM Performance
 
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
 
Event-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream ProcessingEvent-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream Processing
 
Working together SRE & Platform Engineering
Working together SRE & Platform EngineeringWorking together SRE & Platform Engineering
Working together SRE & Platform Engineering
 
Oauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoftOauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoft
 
Using IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & IrelandUsing IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & Ireland
 
Introduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptxIntroduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptx
 
Overview of Hyperledger Foundation
Overview of Hyperledger FoundationOverview of Hyperledger Foundation
Overview of Hyperledger Foundation
 
AI mind or machine power point presentation
AI mind or machine power point presentationAI mind or machine power point presentation
AI mind or machine power point presentation
 
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
 
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdfLinux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
 
Intro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераIntro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджера
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptx
 
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdfBreaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
 
Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...
Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...
Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...
 
Microsoft CSP Briefing Pre-Engagement - Questionnaire
Microsoft CSP Briefing Pre-Engagement - QuestionnaireMicrosoft CSP Briefing Pre-Engagement - Questionnaire
Microsoft CSP Briefing Pre-Engagement - Questionnaire
 
2024 May Patch Tuesday
2024 May Patch Tuesday2024 May Patch Tuesday
2024 May Patch Tuesday
 
ERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage Intacct
 

Android programming -_pushing_the_limits

  • 1. Pushing the Limits Erik Hellman, Spotify google.com/+ErikHellman @ErikHellman Android Programming
  • 3. 3 Improved memory management Efficient multi-threading and -processing Using Android components correctly
  • 5. Use a static factory method whenever possible 5 Effective Java (2nd ed.): Item 1! “A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked.”
  • 6. Message.java 6 public  final  class  Message  implements  Parcelable  {          /*package*/  Message  next;   !        private  static  final  Object  sPoolSync  =  new  Object();          private  static  Message  sPool;          private  static  int  sPoolSize  =  0;   !        private  static  final  int  MAX_POOL_SIZE  =  50;   !        public  static  Message  obtain()  {                  synchronized  (sPoolSync)  {                          if  (sPool  !=  null)  {                                  Message  m  =  sPool;                                  sPool  =  m.next;                                  m.next  =  null;                                  sPoolSize-­‐-­‐;                                  return  m;                          }                  }                  return  new  Message();          }      public  void  recycle()  {                  clearForRecycle();   !                synchronized  (sPoolSync)  {                          if  (sPoolSize  <  MAX_POOL_SIZE)  {                                  next  =  sPool;                                  sPool  =  this;                                  sPoolSize++;                          }                  }          }   }  
  • 7. How to get more memory - Part 1 7 <application          android:allowBackup="true"          android:icon="@drawable/ic_launcher"          android:label="@string/app_name"          android:name=".MyApplication"          android:largeHeap="true"          android:theme="@style/AppTheme"  >          …   </application>
  • 8. How to get more memory - Part 2 8 <service          android:name="se.hellsoft.apptl.app.MyService"          android:enabled="true"          android:exported="false"          android:process="se.hellsoft.apptl.service">   </service>
  • 9. How to get more memory - Part 3 9 data  =  malloc(sizeof(data_struct));
  • 10. 10 Improved memory management Efficient multi-threading and -processing Using Android components correctly
  • 11. 11 Always use a Handler!* * Except when you shouldn’t… @Override   protected  void  onCreate(Bundle  savedInstanceState)  {          super.onCreate(savedInstanceState);          HandlerThread  backgroundThread  =  new  HandlerThread("background");          backgroundThread.start();          mBackgroundHandler  =  new  Handler(backgroundThread.getLooper(),  this);          mUiHandler  =  new  Handler(this);   }   ! @Override   protected  void  onDestroy()  {          super.onDestroy();          mBackgroundHandler.removeCallbacksAndMessages(null);          mBackgroundHandler.getLooper().quit();   }
  • 12. 12 Always use a Handler!* * Except when you shouldn’t… public  void  onStartBackgroundJob(View  view)  {          mBackgroundHandler.obtainMessage(BACKGROUND_JOB).sendToTarget();   }   ! @Override   public  boolean  handleMessage(Message  msg)  {          switch  (msg.what)  {                  case  BACKGROUND_JOB:                          Bitmap  result  =  null;                          //  Processing  goes  here...                            mUiHandler.obtainMessage(UPDATE_UI,  result).sendToTarget();                          break;                  case  UPDATE_UI:                          ((ImageView)  findViewById(R.id.photo))                                                                              .setImageBitmap((Bitmap)  msg.obj);                          break;          }          return  true;   }  
  • 13. Why Handler? 13 •Scheduling of messages
 •Cancelling of messages
 •Reduces GC calls
  • 14. Using the process attribute 14
  • 15. Why a separate process? 15 •Better isolation from crashes
 •Binder transactions uses a thread pool
 •Double the memory!
  • 16. 16 Improved memory management Efficient multi-threading and -processing Using Android components correctly
  • 17. Application component 17 <application          android:allowBackup="true"          android:icon="@drawable/ic_launcher"          android:label="@string/app_name"          android:name=“.MyApplication"          android:theme="@style/AppTheme"  >   !                ...   </application>
  • 18. Android Singletons using Context 18 public  class  MySingleton  {          private  static  MySingleton  sInstance;          private  Context  mContext;   !        private  MySingleton(Context  context)  {                  mContext  =  context;          }                    public  MySingleton  getInstance(Context  context)  {                  if(sInstance  ==  null)  {                          sInstance  =  new  MySingleton(context.getApplicationContext());                  }                  return  sInstance;          }                    public  void  doStuffThatRequireContext()  {                  //  Do  stuff  here...          }   }  
  • 19. Application Context limitations 19 •Inflating layout uses default theme
 •Starting Activity creates a new task
  • 20. 20 Activity - saving state Activity.onSaveInstanceState() Activity.onPause() or
  • 21. 21 onSaveInstanceState() is not called… •…when user presses back
 •…when you call Activity.finish()
  • 22. 22
  • 24. Support library can be upgraded! 24 dependencies  {          compile  'com.android.support:appcompat-­‐v7:+'          compile  'com.android.support:support-­‐v4:19.1.+'          compile  fileTree(dir:  'libs',  include:  ['*.jar'])   }  
  • 25. Typical Fragment crash 25 public  static  class  FirstFragment  extends  Fragment  {          private  ImageView  mImageView;   !        @Override          public  View  onCreateView(LayoutInflater  inflater,  ViewGroup  container,                                                            Bundle  savedInstanceState)  {                  View  rootView  =  inflater.inflate(R.layout.fragment_main,  container,  false);                  mImageView  =  (ImageView)  rootView.findViewById(R.id.photo);   !                new  AsyncTask<Void,  Void,  Bitmap>()  {                          @Override                          protected  Bitmap  doInBackground(Void...  params)  {                                  SystemClock.sleep(10000);  //  Fake  long  processing...                                  return  BitmapFactory.decodeResource(getResources(),                                                                                                                                  R.drawable.happy_android);                          }   !                        @Override                          protected  void  onPostExecute(Bitmap  bitmap)  {                                  mImageView.setImageBitmap(bitmap);                          }                  }.execute();   !                return  rootView;          }   }
  • 26. Typical Fragment crash 26 E/AndroidRuntime(  1245):  FATAL  EXCEPTION:  AsyncTask  #1   E/AndroidRuntime(  1245):  Process:  se.hellsoft.apptl.app,  PID:  1245   E/AndroidRuntime(  1245):  java.lang.RuntimeException:  An  error  occured  while  executing  doInBackground()   E/AndroidRuntime(  1245):          at  android.os.AsyncTask$3.done(AsyncTask.java:300)   E/AndroidRuntime(  1245):          at  java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)   E/AndroidRuntime(  1245):          at  java.util.concurrent.FutureTask.setException(FutureTask.java:222)   E/AndroidRuntime(  1245):          at  java.util.concurrent.FutureTask.run(FutureTask.java:242)   E/AndroidRuntime(  1245):          at  android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)   E/AndroidRuntime(  1245):          at  java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)   E/AndroidRuntime(  1245):          at  java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)   E/AndroidRuntime(  1245):          at  java.lang.Thread.run(Thread.java:841)   E/AndroidRuntime(  1245):  Caused  by:  java.lang.IllegalStateException:  Fragment  FirstFragment{52836468}  not  attached   to  Activity   E/AndroidRuntime(  1245):          at  android.support.v4.app.Fragment.getResources(Fragment.java:601)   E/AndroidRuntime(  1245):          at  se.hellsoft.apptl.app.MainActivity$FirstFragment $1.doInBackground(MainActivity.java:115)   E/AndroidRuntime(  1245):          at  se.hellsoft.apptl.app.MainActivity$FirstFragment $1.doInBackground(MainActivity.java:109)   E/AndroidRuntime(  1245):          at  android.os.AsyncTask$2.call(AsyncTask.java:288)   E/AndroidRuntime(  1245):          at  java.util.concurrent.FutureTask.run(FutureTask.java:237)   E/AndroidRuntime(  1245):          ...  4  more
  • 27. 27 Use a Loader whenever possible and cancel remaining requests in onPause()/onDetach()!
  • 28. Binding to Services 28 @Override   public  IBinder  onBind(Intent  intent)  {     return  null;  //  NEVER  do  this   }
  • 29. Binding to Services 29 @Override   public  IBinder  onBind(Intent  intent)  {     String  action  =  intent.getAction();     if(ACTION_FIRST_BINDER.equals(action))  {       return  mFirstBinder;     }  else  if(ACTION_SECOND_BINDER.equals(action))  {       return  mSecondBinder;     }  else  {       throw  new  RuntimeException("Unexpected  error!");     }   }  
  • 30. Binding to Services 30 @Override   public  IBinder  onBind(Intent  intent)  {     Uri  data  =  intent.getData();     String  param  =  data.getQueryParameter("param");     if(FIRST_BINDER.equals(param))  {       return  mFirstBinder;     }  else  if(SECOND_BINDER.equals(param))  {       return  mSecondBinder;     }  else  {       throw  new  RuntimeException("Unexpected  error!:");     }   }  
  • 31. Service considerations 31 •A binder Intent is identified by the action string and data Uri! ! •onBind() and onUnbind() only called once per unique Intent
 •START_STICKY will give a null  Intent when Service is restarted by the system
 •Binder calls run on local thread for process-local service
  • 32. Most common ContentProvider mistake :) 32 @Override   public  Cursor  query(Uri  uri,  String[]  projection,  String  selection,                                          String[]  selectionArgs,  String  sortOrder)  {          SQLiteDatabase  db  =  mDatabaseHelper.getReadableDatabase();          int  match  =  sUriMatcher.match(uri);          Cursor  cursor  =  null;          switch  (match)  {                  case  ALL_ROWS:                          cursor  =  db.query(Contract.TABLE_NAME,  projection,  selection,                                            selectionArgs,  "",  "",  sortOrder);                          break;                  case  SINGLE_ROW:                          String  id  =  uri.getLastPathSegment();                          cursor  =    db.query(Contract.TABLE_NAME,  projection,  "_id  =  ?",                                            new  String[]{id},  "",  "",  sortOrder);                          break;          }          if(cursor  !=  null)  {                  cursor.setNotificationUri(getContext().getContentResolver(),  uri);          }          return  cursor;   }
  • 33. Most common ContentProvider mistake :) 33 @Override   public  Uri  insert(Uri  uri,  ContentValues  values)  {        SQLiteDatabase  db  =  mDatabaseHelper.getWritableDatabase();          int  match  =  sUriMatcher.match(uri);          switch  (match)  {                  case  ALL_ROWS:                          long  newId  =  db.insert(Contract.TABLE_NAME,  "",  values);                          if(newId  !=  -­‐1)  {                                  getContext().getContentResolver().notifyChange(uri,  null);                          }                          return  Uri.withAppendedPath(uri,  String.valueOf(newId));                  default:                          return  null;          }   }
  • 34. Don’t forget bulkInsert() !!! 34 @Override   public  int  bulkInsert(Uri  uri,  ContentValues[]  values)  {          SQLiteDatabase  db  =  mDatabaseHelper.getWritableDatabase();          int  match  =  sUriMatcher.match(uri);          int  inserted  =  0;          switch  (match)  {                  case  TASKS_CODE:                          try  {                                  db.beginTransaction();                                  for  (ContentValues  value  :  values)  {                                          long  id  =  db.insert(Contract.TABLE_NAME,  "",  value);                                          if  (id  <=  0)  throw  new  SQLException("Failed  with  inserting.");                                          inserted++;                                  }                                  db.setTransactionSuccessful();                                  getContext().getContentResolver().notifyChange(uri,  null);                          }  finally  {                                  db.endTransaction();                          }          }          return  inserted;   }  
  • 35. Useful Broadcasts - Auto-starting 35 <receiver  android:name="se.hellsoft.myapp.AutoStartReceiver"  >          <intent-­‐filter>                  <action  android:name="android.intent.action.BOOT_COMPLETED"  />        </intent-­‐filter>   </receiver>   <receiver  android:name=“se.hellsoft.myapp.AutoStartReceiver"                      android:process=“:autostarter”>          <intent-­‐filter>                  <action  android:name="android.intent.action.USER_PRESENT"  />        </intent-­‐filter>   </receiver>  
  • 36. Useful Broadcasts - Monitoring the network 36 <receiver  android:name=“se.hellsoft.myapp.NetworkMonitor">          <intent-­‐filter>                  <action  android:name="android.net.conn.CONNECTIVITY_CHANGE"  />                  <action  android:name="android.net.wifi.supplicant.CONNECTION_CHANGE"  />                  <action  android:name="android.net.wifi.WIFI_AP_STATE_CHANGED"  />        </intent-­‐filter>   </receiver>  
  • 37. 37 “Many problems with Android apps can be fixed with 
 a proper use of the Handler class.” - Erik Hellman Get my book at wiley.com/go/ptl/androidprogramming