SlideShare une entreprise Scribd logo
1  sur  40
Android Code
Puzzles
droidcon.nl
● Danny Preussler:
● Lead Engineer Android
ebay Kleinanzeigen, Germany
● Path to the green side:
C++ -> Java SE -> JME -> BlackBerry -> Android
● My current Droids:
Galaxy Nexus, Nexus 7, Logitech Revue, I'm watch
● My 1st Droid was a:
Motorola Droid/Milestone
● Johannes Orgis:
● Software Development Manager
Cortado Mobile Clients
Cortado AG, Germany
● Path to the green side:
Java EE -> Java SE -> BlackBerry -> Android
● My current Droids:
Galaxy Nexus, Nexus 7
● My 1st Droid was a:
HTC Magic
● We show code snippets that does something or maybe not
● Look out for hidden pitfalls
● All Puzzles are run with Android 4.1 Jelly Beans
There should be no platform depended puzzles
● Test yourself!
● Raise your hands when we ask you!
● Guess if you're unsure!
● Learn something if you were wrong!
● Have fun! :D
public class DroidConPuzzle extends Activity {
@Override
protected void onCreate(Bundle saved) {
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.add(android.R.id.content, new Fragment() {
@Override
public View onCreateView(LayoutInflater inf,
ViewGroup view, Bundle saved)
{
View v = inf.inflate(R.layout.fragment_default, null);
return null;
}
});
trans.commit();
super.onCreate(saved);
}
}
For your eyes only...
a) NullPointerException in Inflater.inflate()
b) NullPointerException after onCreateView()
c) llegalStateException in super.onCreate()
d) llegalStateException in Transaction.commit()
e) shows an empty screen
public class DroidConPuzzle extends Activity {
@Override
protected void onCreate(Bundle saved) {
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.add(android.R.id.content, new Fragment() {
@Override
public View onCreateView(LayoutInflater inf,
ViewGroup view, Bundle saved)
{
View v = inf.inflate(R.layout.fragment_default, null);
return null;
}
});
trans.commit();
super.onCreate(saved);
}
}
For your eyes only...
a) NullPointerException in Inflater.inflate()
b) NullPointerException after onCreateView()
c) llegalStateException in super.onCreate()
d) llegalStateException in Transaction.commit()
e) shows an empty screen
public class DroidConPuzzle extends Activity {
@Override
protected void onCreate(Bundle saved) {
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.add(android.R.id.content, new Fragment() {
@Override
public View onCreateView(LayoutInflater inf,
ViewGroup view, Bundle saved)
{
View v = inf.inflate(R.layout.fragment_default, null);
return null;
}
});
trans.commit();
super.onCreate(saved);
}
}
For your eyes only...
e) shows an empty screen BUT after rotation it will crash:
● Fragments need to be public:
not possible as inner or anonymous class
● Fragments must have a public empty
constructor
● RTFW: read the fucking warnings:
●
<Button ... android:onClick="clicked" />
public class OnClickToastFragment extends Fragment {...
public void clicked(View v)
{
Toast.makeText(getActivity(),getClass().getName(),Toast.LENGTH_SHORT).show();
}
}
public class OnClickToastFragmentActivity extends FragmentActivity{
public void clicked(View v)
{
Toast.makeText(this,getClass().getName(),Toast.LENGTH_SHORT).show();
}
}
public class MyMainActivity extends Activity{
public void clicked(View v)
{
Toast.makeText(this,getClass().getName(),Toast.LENGTH_SHORT).show();
}
}
Licence to click
What happens when I click the Button?
a) Toast : MyMainActivity
b) Toast : OnClickToastFragmentActivity
c) Toast : OnClickToastFragment
d) Nothing
e) IllegalStateException - Could not find a method ...
<Button ... android:onClick="clicked" />
public class OnClickToastFragment extends Fragment {...
public void clicked(View v)
{
Toast.makeText(getActivity(),getClass().getName(),Toast.LENGTH_SHORT).show();
}
}
public class OnClickToastFragmentActivity extends FragmentActivity{
public void clicked(View v)
{
Toast.makeText(this,getClass().getName(),Toast.LENGTH_SHORT).show();
}
}
public class MyMainActivity extends Activity{
public void clicked(View v)
{
Toast.makeText(this,getClass().getName(),Toast.LENGTH_SHORT).show();
}
}
Licence to click
What happens when I click the Button?
a) Toast : MyMainActivity
b) Toast : OnClickToastFragmentActivity
c) Toast : OnClickToastFragment
d) Nothing
e) IllegalStateException - Could not find a method ...
android:onClick is an easy way to trigger "click" events in xml
but remember: the calling Activity MUST implement the xxx(Viev v) method otherwise a
IllegalStateException will be thrown at runtime
be careful if you are using Fragments in multiple Activities
Every 2.2. Device has the "unique" ANDROID_ID
9774d56d682e549c ?
Be aware of platform dependent puzzles....
or did you know that?
public class GetViewFragment extends Fragment {
public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {
super.onCreateView(inf, view, saved);
return inf.inflate(R.layout.fragment_get_view, view);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getView().setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(getActivity(),
"My name is droid, android",
Toast.LENGTH_SHORT);}});
}
}
A View to (a) Kill
a) shows a Toast "my name is droid, android"
b) does nothing but showing a view
c) Exception in Inflater.inflate()
d) Exception in GetViewFragment.onCreate()
e) Exception in Fragment.onCreateView()
public class GetViewFragment extends Fragment {
public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {
super.onCreateView(inf, view, saved);
return inf.inflate(R.layout.fragment_get_view, view);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getView().setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(getActivity(),
"My name is droid, android",
Toast.LENGTH_SHORT);}});
}
}
A View to (a) Kill
a) shows a Toast "my name is droid, android"
b) does nothing but showing a view
c) Exception in Inflater.inflate()
d) Exception in GetViewFragment.onCreate()
e) Exception in Fragment.onCreateView()
public class GetViewFragment extends Fragment {
public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {
super.onCreateView(inf, view, saved);
return inf.inflate(R.layout.fragment_get_view, view);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getView().setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(getActivity(),
"My name is droid, android",
Toast.LENGTH_SHORT);}});
}
}
A View to (a) Kill
a) shows a Toast "my name is droid, android"
b) does nothing but showing a view
c) Exception in Inflater.inflate() (2nd winner)
d) Exception in GetViewFragment.onCreateView()
e) Exception in Fragment.onCreateView()
● Know about the life cycle of Activities,
Fragments, Services!
● Example: methods as
getView() or getActivity() can return null in
certain points of their life cycle!
public class ToastFragment extends Fragment {
...
public void onDestroy() {
super.onDestroy();
new ToastingAsyncTask().execute(null,null,null);
}
class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{
protected void onPostExecute(Long result) {
if (getActivity() == null){
System.out.println(getString(R.string.no_activity));
}else{
System.out.println(getString(R.string.activity_leak));
}
}
protected Long doInBackground(String... params) {
try {Thread.sleep(500);} catch (InterruptedException e) {}
return null;}
...
Live and let die ...
what happens when I change the orientation of my Galaxy Nexus?
a) Sysout: no_activity
b) Sysout: activity_leak
c) Sysout: null
d) Exception in getActivity
e) Exception in getString
public class ToastFragment extends Fragment {
...
public void onDestroy() {
super.onDestroy();
new ToastingAsyncTask().execute(null,null,null);
}
class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{
protected void onPostExecute(Long result) {
if (getActivity() == null){
System.out.println(getString(R.string.no_activity));
}else{
System.out.println(getString(R.string.activity_leak));
}
}
protected Long doInBackground(String... params) {
try {Thread.sleep(500);} catch (InterruptedException e) {}
return null;}
...
Live and let die ...
what happens when I change the orientation of my Galaxy Nexus?
a) Sysout: no_activity
b) Sysout: activity_leak
c) Sysout: null
d) Exception in getActivity
e) Exception in getString
LogCat shows:
java.lang.IllegalStateException: Fragment ToastFragment not attached to Activity
A Context holds your Resources!
Know about the life cycle of Activities, Fragments,
Services!!
Until Android 4 (possible 3.x) android.app.DownloadManager only supports http
connections:
if (scheme == null || !scheme.equals("http")) {
throw new IllegalArgumentException("Can only download HTTP URIs: " + uri);
}
Because of that the stock browser (and Chrome)
could not handle https downloads.
Be aware of platform dependent puzzles....
or did you know that?
public class MyListActivity extends ListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFromServer(getApplicationContext());
}
void getFromServer(Context context) {
final ProgressDialog dlg = new ProgressDialog(context);
dlg.show();
new AsyncTask<Context, Void, ArrayAdapter>() {
protected ArrayAdapter doInBackground(Context... params) {
return new ArrayAdapter<String>(params[0],
android.R.layout.simple_list_item_1,
Arrays.asList(new String[] { "0", "0", "7" }));
}
protected void onPostExecute(ArrayAdapter result) {
setListAdapter(result);
dlg.dismiss();
}
}.execute(context);
}...
a) shows list with entries 0,0,7
b) shows list with entries 0,7
c) Exception in getFromServer
d) Exception in doInBackground
e) Exception in onPostExecute
Tomorrow never dies...
public class MyListActivity extends ListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFromServer(getApplicationContext());
}
void getFromServer(Context context) {
final ProgressDialog dlg = new ProgressDialog(context);
dlg.show();
new AsyncTask<Context, Void, ArrayAdapter>() {
protected ArrayAdapter doInBackground(Context... params) {
return new ArrayAdapter<String>(params[0],
android.R.layout.simple_list_item_1,
Arrays.asList(new String[] { "0", "0", "7" }));
}
protected void onPostExecute(ArrayAdapter result) {
setListAdapter(result);
dlg.dismiss();
}
}.execute(context);
}...
a) shows list with entries 0,0,7
b) shows list with entries 0,7
c) Exception in getFromServer
d) Exception in doInBackground
e) Exception in onPostExecute
Tomorrow never dies...
● Know your Context!
● Never use Application Context for UI!
Prefer Application Context for Non-UI!
● Be aware of Context Leaks!
public class ActionbarFragment extends Fragment {
...
public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {
setHasOptionsMenu(true);
return inf.inflate(R.layout.fragment_get_view, null);
}
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(getActivity(), "from Fragment", Toast.LENGTH_SHORT).show();
return true;
}
}
public class ActionbarActivity extends Activity {
...
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(this, "from Activity", Toast.LENGTH_SHORT).show();
return true;
}
}
From Fragment with Love...
When clicking an item from actionbar:
a) shows toast: "from Activity"
b) shows toast: "from Fragment"
c) shows both toasts
d) shows toast depending on who the creator of the menu item
public class ActionbarFragment extends Fragment {
...
public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {
setHasOptionsMenu(true);
return inf.inflate(R.layout.fragment_get_view, null);
}
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(getActivity(), "from Fragment", Toast.LENGTH_SHORT).show();
return true;
}
}
public class ActionbarActivity extends Activity {
...
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(this, "from Activity", Toast.LENGTH_SHORT).show();
return true;
}
}
From Fragment with Love...
When clicking an item from actionbar:
a) shows toast: "from Activity"
b) shows toast: "from Fragment"
c) shows both toasts
d) shows toast depending on who the creator of the menu item
"If you added the menu item from a fragment, then the
respective onOptionsItemSelected() method is called for that
fragment.
However the activity gets a chance to handle it first, so the
system calls onOptionsItemSelected() on the activity before
calling the fragment."
● RTFJD: read the fucking java doc:
On pre 2.3.6 Android's HttpUrlConnection is broken
as soon as the server supports more than Basic authentication ?
You'll get IndexOutOfBoundsException
Be aware of platform dependent puzzles....
or did you know that?
int realm = challenge.indexOf("realm="") + 7;
WWW-Authenticate: Basic realm="RealmName"
WWW-Authenticate: NTLM
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] longList = new String[1000000];
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra("droidcon", longList);
startActivityForResult(intent, 100);
}
protected void onActivityResult(int request, int result, Intent data) {
super.onActivityResult(request, result, data);
Log.e("droidcon", "result" + request + " " + result);
}
a) OutOfMemoryException in onCreate()
b) IllegalArgumentException in onCreate()
c) Nothing happens, direct invocation of onActivityResult (with cancel code)
d) Nothing happens, no invocation of onActivityResult
e) System-Intent-Picker for "sent" action will be shown normally
The world is not enough ...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] longList = new String[1000000];
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra("droidcon", longList);
startActivityForResult(intent, 100);
}
protected void onActivityResult(int request, int result, Intent data) {
super.onActivityResult(request, result, data);
Log.e("droidcon", "result" + request + " " + result);
}
a) OutOfMemoryException in onCreate()
b) IllegalArgumentException in onCreate()
c) Nothing happens, direct invocation of onActivityResult (with cancel code)
d) Nothing happens, no invocation of onActivityResult
e) System-Intent-Picker for "sent" action will be shown normally
The world is not enough ...
Logcat shows:
11-12 16:25:53.391: E/JavaBinder(6247): !!! FAILED BINDER TRANSACTION !!!
Some devices show TransactionTooLargeException:
The Binder transaction failed because it was too large.
During a remote procedure call, the arguments and the return value of the call are transferred as
Parcel objects stored in the Binder transaction buffer. If the arguments or the return value are too
large to fit in the transaction buffer, then the call will fail and TransactionTooLargeException will be
thrown.
The Binder transaction buffer has a limited fixed size, currently 1Mb, which is shared by all
transactions in progress for the process. Consequently this exception can be thrown when there are
many transactions in progress even when most of the individual transactions are of moderate size.
Be aware of platform dependent puzzles....
or did you know that?
Starting with 2.3 HTTPUrlConnection handles and sets gzip as Content-Encoding.
This leads to errors if you get a response where there is no content but a Content-
Length (=0) or a Content-Encoding(=gzip).
getResponceCode leads to EOFException
public class AsyncTaskActivity extends Activity{
...
protected void onResume() {
super.onResume();
TextView testV = (TextView) findViewById(R.id.async_text_1);
new WritingAsyncTask(testV,2000).execute(" Bob");
new WritingAsyncTask(testV,100).execute("Alice");
new WritingAsyncTask(testV,500).execute("loves");
}
...
public class WritingAsyncTask extends AsyncTask<String, Void, String>{...
private final TextView view;//set in Constructor
private final int timeout;//set in Constructor
protected String doInBackground(String... params) {
try {Thread.sleep(timeout);} catch (InterruptedException e) {}
return params[0];
}
protected void onPostExecute(String result) {
view.setText(view.getText()+" "+result);}
Casino Royal
What is shown in the TextView when I start the Activity on my Galaxy Nexus:
a) Alice loves Bob
b) Bob Alice loves
c) Bob loves Alice
d) There is not enough information to decide
public class AsyncTaskActivity extends Activity{
...
protected void onResume() {
super.onResume();
TextView testV = (TextView) findViewById(R.id.async_text_1);
new WritingAsyncTask(testV,2000).execute(" Bob");
new WritingAsyncTask(testV,100).execute("Alice");
new WritingAsyncTask(testV,500).execute("loves");
}
...
public class WritingAsyncTask extends AsyncTask<String, Void, String>{...
private final TextView view;//set in Constructor
private final int timeout;//set in Constructor
protected String doInBackground(String... params) {
try {Thread.sleep(timeout);} catch (InterruptedException e) {}
return params[0];
}
protected void onPostExecute(String result) {
view.setText(view.getText()+" "+result);}
Casino Royal
What is shown in the TextView when I start the Activity on my Galaxy Nexus:
a) Alice loves Bob
b) Bob Alice loves
c) Bob loves Alice
d) There is not enough information to decide
public class AsyncTaskActivity extends Activity{
...
protected void onResume() {
super.onResume();
TextView testV = (TextView) findViewById(R.id.async_text_1);
new WritingAsyncTask(testV,2000).execute(" Bob");
new WritingAsyncTask(testV,100).execute("Alice");
new WritingAsyncTask(testV,500).execute("loves");
}
...
public class WritingAsyncTask extends AsyncTask<String, Void, String>{...
private final TextView view;//set in Constructor
private final int timeout;//set in Constructor
protected String doInBackground(String... params) {
try {Thread.sleep(timeout);} catch (InterruptedException e) {}
return params[0];
}
protected void onPostExecute(String result) {
view.setText(view.getText()+" "+result);}
Casino Royal
What is shown in the TextView when I start the Activity on my Galaxy Nexus:
a) Alice loves Bob
b) Bob Alice loves .... usually
c) Bob loves Alice
d) There is not enough information to decide
public class AsyncTaskActivity extends Activity{
...
protected void onResume() {
super.onResume();
TextView testV = (TextView) findViewById(R.id.async_text_1);
new WritingAsyncTask(testV,2000).execute(" Bob");
new WritingAsyncTask(testV,100).execute("Alice");
new WritingAsyncTask(testV,500).execute("loves");
}
...
public class WritingAsyncTask extends AsyncTask<String, Void, String>{...
private final TextView view;//set in Constructor
private final int timeout;//set in Constructor
protected String doInBackground(String... params) {
try {Thread.sleep(timeout);} catch (InterruptedException e) {}
return params[0];
}
protected void onPostExecute(String result) {
view.setText(view.getText()+" "+result);}
Casino Royal
What is shown in the TextView when I start the Activity on my Galaxy Nexus:
a) Alice loves Bob
b) Bob Alice loves
c) Bob loves Alice
d) There is not enough information to decide
You need to know the android:targetSdkVersion (and the Device Version of the Target Device)
android:targetSdkVersion < 13:
AsyncTask is executed parallel
android:targetSdkVersion >= 13 && Device OS >= 14:
AsyncTask is executed serial
from AsyncTask.Java:
...
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
...
You can enforce parallel execution in SDK >= 11
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,...);
public class ManyAsyncTasksActivity extends Activity{
...
protected void onResume() {
super.onResume();
TextView testV = (TextView) findViewById(R.id.async_text_1);
for (int i = 0; i < 200; i++) {
new WritingAsyncTask(testV,100).execute(i+",");
}
}
...
public class WritingAsyncTask extends AsyncTask<String, Void, String>{...
private final TextView view;//set in Constructor
private final int timeout;//set in Constructor
protected String doInBackground(String... params) {
try {Thread.sleep(timeout);} catch (InterruptedException e) {}
return params[0];
}
protected void onPostExecute(String result) {
view.setText(view.getText()+" "+result);}
Moonraker
What is shown when I start the Activity on my G. Nexus (target SDK is 11, A: 4.1.2) :
a) Numbers from 0 to 199 in random order
b) Application Error (App has stopped)
c) Numbers from 0 to 199 in serial order
d) Numbers from 0 to 127 in random order
e) Numbers from 0 to 137 in random order
public class ManyAsyncTasksActivity extends Activity{
...
protected void onResume() {
super.onResume();
TextView testV = (TextView) findViewById(R.id.async_text_1);
for (int i = 0; i < 200; i++) {
new WritingAsyncTask(testV,100).execute(i+",");
}
}
...
public class WritingAsyncTask extends AsyncTask<String, Void, String>{...
private final TextView view;//set in Constructor
private final int timeout;//set in Constructor
protected String doInBackground(String... params) {
try {Thread.sleep(timeout);} catch (InterruptedException e) {}
return params[0];
}
protected void onPostExecute(String result) {
view.setText(view.getText()+" "+result);}
Moonraker
What is shown when I start the Activity on my G. Nexus (target SDK is 11, A: 4.1.2) :
a) Numbers from 0 to 199 in random order
b) Application Error (App has stopped)
c) Numbers from 0 to 199 in serial order
d) Numbers from 0 to 127 in random order
e) Numbers from 0 to 137 in random order
LogCat shows:
java.lang.RuntimeException: Unable to resume activity {...}: java.util.concurrent.
RejectedExecutionException: Task android.os.AsyncTask ... rejected from java.util.concurrent.
ThreadPoolExecutor ... [Running, pool size = 128, active threads = 128, queued tasks = 10,
completed tasks = 0]
ThreadPoolExecutor currently only accepts a given number of Tasks, default value is a pool size of
128.
private static final int MAXIMUM_POOL_SIZE = 128;
...
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);
Thank you!
dpreussler@ebay.com
johannes.orgis@team.cortado.com

Contenu connexe

Tendances

ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013
Mathias Seguy
 
The event-driven nature of javascript – IPC2012
The event-driven nature of javascript – IPC2012The event-driven nature of javascript – IPC2012
The event-driven nature of javascript – IPC2012
Martin Schuhfuß
 

Tendances (8)

ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013
 
Javascript, the GNOME way (JSConf EU 2011)
Javascript, the GNOME way (JSConf EU 2011)Javascript, the GNOME way (JSConf EU 2011)
Javascript, the GNOME way (JSConf EU 2011)
 
Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516
 
Cracking JWT tokens: a tale of magic, Node.js and parallel computing - WebReb...
Cracking JWT tokens: a tale of magic, Node.js and parallel computing - WebReb...Cracking JWT tokens: a tale of magic, Node.js and parallel computing - WebReb...
Cracking JWT tokens: a tale of magic, Node.js and parallel computing - WebReb...
 
Modern Code Reviews in Open-Source Projects: Which Problems Do They Fix?
Modern Code Reviews in Open-Source Projects: Which Problems Do They Fix?Modern Code Reviews in Open-Source Projects: Which Problems Do They Fix?
Modern Code Reviews in Open-Source Projects: Which Problems Do They Fix?
 
The event-driven nature of javascript – IPC2012
The event-driven nature of javascript – IPC2012The event-driven nature of javascript – IPC2012
The event-driven nature of javascript – IPC2012
 
The Ring programming language version 1.10 book - Part 83 of 212
The Ring programming language version 1.10 book - Part 83 of 212The Ring programming language version 1.10 book - Part 83 of 212
The Ring programming language version 1.10 book - Part 83 of 212
 
A More Flash Like Web?
A More Flash Like Web?A More Flash Like Web?
A More Flash Like Web?
 

Similaire à Android Code Puzzles (DroidCon Amsterdam 2012)

Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
Yekmer Simsek
 
Thomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-finalThomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-final
Droidcon Berlin
 
Quick Intro to Android Development
Quick Intro to Android DevelopmentQuick Intro to Android Development
Quick Intro to Android Development
Jussi Pohjolainen
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahoda
Droidcon Berlin
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
Alexey Buzdin
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
C.T.Co
 

Similaire à Android Code Puzzles (DroidCon Amsterdam 2012) (20)

Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 
Fragments anyone
Fragments anyone Fragments anyone
Fragments anyone
 
Minicurso Android
Minicurso AndroidMinicurso Android
Minicurso Android
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Thomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-finalThomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-final
 
Quick Intro to Android Development
Quick Intro to Android DevelopmentQuick Intro to Android Development
Quick Intro to Android Development
 
RxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниRxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камни
 
Data binding в массы!
Data binding в массы!Data binding в массы!
Data binding в массы!
 
Android Loaders : Reloaded
Android Loaders : ReloadedAndroid Loaders : Reloaded
Android Loaders : Reloaded
 
深入淺出談Fragment
深入淺出談Fragment深入淺出談Fragment
深入淺出談Fragment
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developers
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahoda
 
Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
02 hello world - Android
02   hello world - Android02   hello world - Android
02 hello world - Android
 
Di and Dagger
Di and DaggerDi and Dagger
Di and Dagger
 
Mattbrenner
MattbrennerMattbrenner
Mattbrenner
 
Griffon @ Svwjug
Griffon @ SvwjugGriffon @ Svwjug
Griffon @ Svwjug
 
Mini curso Android
Mini curso AndroidMini curso Android
Mini curso Android
 

Plus de Danny Preussler

Plus de Danny Preussler (17)

We aint got no time - Droidcon Nairobi
We aint got no time - Droidcon NairobiWe aint got no time - Droidcon Nairobi
We aint got no time - Droidcon Nairobi
 
Test Driven Development on Android (Kotlin Kenya)
Test Driven Development on Android (Kotlin Kenya)Test Driven Development on Android (Kotlin Kenya)
Test Driven Development on Android (Kotlin Kenya)
 
TDD on android. Why and How? (Coding Serbia 2019)
TDD on android. Why and How? (Coding Serbia 2019)TDD on android. Why and How? (Coding Serbia 2019)
TDD on android. Why and How? (Coding Serbia 2019)
 
TDD on Android (Øredev 2018)
TDD on Android (Øredev 2018)TDD on Android (Øredev 2018)
TDD on Android (Øredev 2018)
 
Junit5: the next gen of testing, don't stay behind
Junit5: the next gen of testing, don't stay behindJunit5: the next gen of testing, don't stay behind
Junit5: the next gen of testing, don't stay behind
 
Demystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and ToothpickDemystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and Toothpick
 
Unit Testing on Android: why and how? DevFest Romania, Bucharest 2016
Unit Testing on Android: why and how? DevFest Romania, Bucharest 2016Unit Testing on Android: why and how? DevFest Romania, Bucharest 2016
Unit Testing on Android: why and how? DevFest Romania, Bucharest 2016
 
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
 
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
 
All around the world, localization and internationalization on Android (Droid...
All around the world, localization and internationalization on Android (Droid...All around the world, localization and internationalization on Android (Droid...
All around the world, localization and internationalization on Android (Droid...
 
(Android) Developer Survival in Multiscreen World, MobCon Sofia 2016
(Android) Developer Survival in Multiscreen World, MobCon Sofia 2016(Android) Developer Survival in Multiscreen World, MobCon Sofia 2016
(Android) Developer Survival in Multiscreen World, MobCon Sofia 2016
 
Unit testing on Android (Droidcon Dubai 2015)
Unit testing on Android (Droidcon Dubai 2015)Unit testing on Android (Droidcon Dubai 2015)
Unit testing on Android (Droidcon Dubai 2015)
 
Clean code on Android (Droidcon Dubai 2015)
Clean code on Android (Droidcon Dubai 2015)Clean code on Android (Droidcon Dubai 2015)
Clean code on Android (Droidcon Dubai 2015)
 
Bye Bye Charles, Welcome Odo, Android Meetup Berlin May 2014
Bye Bye Charles, Welcome Odo, Android Meetup Berlin May 2014Bye Bye Charles, Welcome Odo, Android Meetup Berlin May 2014
Bye Bye Charles, Welcome Odo, Android Meetup Berlin May 2014
 
Abgeschottete Realität - Testen im Emulator, Mobile Testing Days 2014, Berlin
Abgeschottete Realität - Testen im Emulator, Mobile Testing Days 2014, BerlinAbgeschottete Realität - Testen im Emulator, Mobile Testing Days 2014, Berlin
Abgeschottete Realität - Testen im Emulator, Mobile Testing Days 2014, Berlin
 
Rockstar Android Testing (Mobile TechCon Munich 2014)
Rockstar Android Testing (Mobile TechCon Munich 2014)Rockstar Android Testing (Mobile TechCon Munich 2014)
Rockstar Android Testing (Mobile TechCon Munich 2014)
 
Android Unit Testing With Robolectric
Android Unit Testing With RobolectricAndroid Unit Testing With Robolectric
Android Unit Testing With Robolectric
 

Dernier

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Dernier (20)

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 

Android Code Puzzles (DroidCon Amsterdam 2012)

  • 2.
  • 3. ● Danny Preussler: ● Lead Engineer Android ebay Kleinanzeigen, Germany ● Path to the green side: C++ -> Java SE -> JME -> BlackBerry -> Android ● My current Droids: Galaxy Nexus, Nexus 7, Logitech Revue, I'm watch ● My 1st Droid was a: Motorola Droid/Milestone ● Johannes Orgis: ● Software Development Manager Cortado Mobile Clients Cortado AG, Germany ● Path to the green side: Java EE -> Java SE -> BlackBerry -> Android ● My current Droids: Galaxy Nexus, Nexus 7 ● My 1st Droid was a: HTC Magic
  • 4. ● We show code snippets that does something or maybe not ● Look out for hidden pitfalls ● All Puzzles are run with Android 4.1 Jelly Beans There should be no platform depended puzzles ● Test yourself! ● Raise your hands when we ask you! ● Guess if you're unsure! ● Learn something if you were wrong! ● Have fun! :D
  • 5. public class DroidConPuzzle extends Activity { @Override protected void onCreate(Bundle saved) { FragmentTransaction trans = getFragmentManager().beginTransaction(); trans.add(android.R.id.content, new Fragment() { @Override public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) { View v = inf.inflate(R.layout.fragment_default, null); return null; } }); trans.commit(); super.onCreate(saved); } } For your eyes only... a) NullPointerException in Inflater.inflate() b) NullPointerException after onCreateView() c) llegalStateException in super.onCreate() d) llegalStateException in Transaction.commit() e) shows an empty screen
  • 6. public class DroidConPuzzle extends Activity { @Override protected void onCreate(Bundle saved) { FragmentTransaction trans = getFragmentManager().beginTransaction(); trans.add(android.R.id.content, new Fragment() { @Override public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) { View v = inf.inflate(R.layout.fragment_default, null); return null; } }); trans.commit(); super.onCreate(saved); } } For your eyes only... a) NullPointerException in Inflater.inflate() b) NullPointerException after onCreateView() c) llegalStateException in super.onCreate() d) llegalStateException in Transaction.commit() e) shows an empty screen
  • 7. public class DroidConPuzzle extends Activity { @Override protected void onCreate(Bundle saved) { FragmentTransaction trans = getFragmentManager().beginTransaction(); trans.add(android.R.id.content, new Fragment() { @Override public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) { View v = inf.inflate(R.layout.fragment_default, null); return null; } }); trans.commit(); super.onCreate(saved); } } For your eyes only... e) shows an empty screen BUT after rotation it will crash:
  • 8. ● Fragments need to be public: not possible as inner or anonymous class ● Fragments must have a public empty constructor ● RTFW: read the fucking warnings: ●
  • 9. <Button ... android:onClick="clicked" /> public class OnClickToastFragment extends Fragment {... public void clicked(View v) { Toast.makeText(getActivity(),getClass().getName(),Toast.LENGTH_SHORT).show(); } } public class OnClickToastFragmentActivity extends FragmentActivity{ public void clicked(View v) { Toast.makeText(this,getClass().getName(),Toast.LENGTH_SHORT).show(); } } public class MyMainActivity extends Activity{ public void clicked(View v) { Toast.makeText(this,getClass().getName(),Toast.LENGTH_SHORT).show(); } } Licence to click What happens when I click the Button? a) Toast : MyMainActivity b) Toast : OnClickToastFragmentActivity c) Toast : OnClickToastFragment d) Nothing e) IllegalStateException - Could not find a method ...
  • 10. <Button ... android:onClick="clicked" /> public class OnClickToastFragment extends Fragment {... public void clicked(View v) { Toast.makeText(getActivity(),getClass().getName(),Toast.LENGTH_SHORT).show(); } } public class OnClickToastFragmentActivity extends FragmentActivity{ public void clicked(View v) { Toast.makeText(this,getClass().getName(),Toast.LENGTH_SHORT).show(); } } public class MyMainActivity extends Activity{ public void clicked(View v) { Toast.makeText(this,getClass().getName(),Toast.LENGTH_SHORT).show(); } } Licence to click What happens when I click the Button? a) Toast : MyMainActivity b) Toast : OnClickToastFragmentActivity c) Toast : OnClickToastFragment d) Nothing e) IllegalStateException - Could not find a method ...
  • 11. android:onClick is an easy way to trigger "click" events in xml but remember: the calling Activity MUST implement the xxx(Viev v) method otherwise a IllegalStateException will be thrown at runtime be careful if you are using Fragments in multiple Activities
  • 12. Every 2.2. Device has the "unique" ANDROID_ID 9774d56d682e549c ? Be aware of platform dependent puzzles.... or did you know that?
  • 13. public class GetViewFragment extends Fragment { public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) { super.onCreateView(inf, view, saved); return inf.inflate(R.layout.fragment_get_view, view); } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getView().setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Toast.makeText(getActivity(), "My name is droid, android", Toast.LENGTH_SHORT);}}); } } A View to (a) Kill a) shows a Toast "my name is droid, android" b) does nothing but showing a view c) Exception in Inflater.inflate() d) Exception in GetViewFragment.onCreate() e) Exception in Fragment.onCreateView()
  • 14. public class GetViewFragment extends Fragment { public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) { super.onCreateView(inf, view, saved); return inf.inflate(R.layout.fragment_get_view, view); } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getView().setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Toast.makeText(getActivity(), "My name is droid, android", Toast.LENGTH_SHORT);}}); } } A View to (a) Kill a) shows a Toast "my name is droid, android" b) does nothing but showing a view c) Exception in Inflater.inflate() d) Exception in GetViewFragment.onCreate() e) Exception in Fragment.onCreateView()
  • 15. public class GetViewFragment extends Fragment { public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) { super.onCreateView(inf, view, saved); return inf.inflate(R.layout.fragment_get_view, view); } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getView().setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Toast.makeText(getActivity(), "My name is droid, android", Toast.LENGTH_SHORT);}}); } } A View to (a) Kill a) shows a Toast "my name is droid, android" b) does nothing but showing a view c) Exception in Inflater.inflate() (2nd winner) d) Exception in GetViewFragment.onCreateView() e) Exception in Fragment.onCreateView()
  • 16. ● Know about the life cycle of Activities, Fragments, Services! ● Example: methods as getView() or getActivity() can return null in certain points of their life cycle!
  • 17. public class ToastFragment extends Fragment { ... public void onDestroy() { super.onDestroy(); new ToastingAsyncTask().execute(null,null,null); } class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{ protected void onPostExecute(Long result) { if (getActivity() == null){ System.out.println(getString(R.string.no_activity)); }else{ System.out.println(getString(R.string.activity_leak)); } } protected Long doInBackground(String... params) { try {Thread.sleep(500);} catch (InterruptedException e) {} return null;} ... Live and let die ... what happens when I change the orientation of my Galaxy Nexus? a) Sysout: no_activity b) Sysout: activity_leak c) Sysout: null d) Exception in getActivity e) Exception in getString
  • 18. public class ToastFragment extends Fragment { ... public void onDestroy() { super.onDestroy(); new ToastingAsyncTask().execute(null,null,null); } class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{ protected void onPostExecute(Long result) { if (getActivity() == null){ System.out.println(getString(R.string.no_activity)); }else{ System.out.println(getString(R.string.activity_leak)); } } protected Long doInBackground(String... params) { try {Thread.sleep(500);} catch (InterruptedException e) {} return null;} ... Live and let die ... what happens when I change the orientation of my Galaxy Nexus? a) Sysout: no_activity b) Sysout: activity_leak c) Sysout: null d) Exception in getActivity e) Exception in getString
  • 19. LogCat shows: java.lang.IllegalStateException: Fragment ToastFragment not attached to Activity A Context holds your Resources! Know about the life cycle of Activities, Fragments, Services!!
  • 20. Until Android 4 (possible 3.x) android.app.DownloadManager only supports http connections: if (scheme == null || !scheme.equals("http")) { throw new IllegalArgumentException("Can only download HTTP URIs: " + uri); } Because of that the stock browser (and Chrome) could not handle https downloads. Be aware of platform dependent puzzles.... or did you know that?
  • 21. public class MyListActivity extends ListActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getFromServer(getApplicationContext()); } void getFromServer(Context context) { final ProgressDialog dlg = new ProgressDialog(context); dlg.show(); new AsyncTask<Context, Void, ArrayAdapter>() { protected ArrayAdapter doInBackground(Context... params) { return new ArrayAdapter<String>(params[0], android.R.layout.simple_list_item_1, Arrays.asList(new String[] { "0", "0", "7" })); } protected void onPostExecute(ArrayAdapter result) { setListAdapter(result); dlg.dismiss(); } }.execute(context); }... a) shows list with entries 0,0,7 b) shows list with entries 0,7 c) Exception in getFromServer d) Exception in doInBackground e) Exception in onPostExecute Tomorrow never dies...
  • 22. public class MyListActivity extends ListActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getFromServer(getApplicationContext()); } void getFromServer(Context context) { final ProgressDialog dlg = new ProgressDialog(context); dlg.show(); new AsyncTask<Context, Void, ArrayAdapter>() { protected ArrayAdapter doInBackground(Context... params) { return new ArrayAdapter<String>(params[0], android.R.layout.simple_list_item_1, Arrays.asList(new String[] { "0", "0", "7" })); } protected void onPostExecute(ArrayAdapter result) { setListAdapter(result); dlg.dismiss(); } }.execute(context); }... a) shows list with entries 0,0,7 b) shows list with entries 0,7 c) Exception in getFromServer d) Exception in doInBackground e) Exception in onPostExecute Tomorrow never dies...
  • 23. ● Know your Context! ● Never use Application Context for UI! Prefer Application Context for Non-UI! ● Be aware of Context Leaks!
  • 24. public class ActionbarFragment extends Fragment { ... public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) { setHasOptionsMenu(true); return inf.inflate(R.layout.fragment_get_view, null); } public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(getActivity(), "from Fragment", Toast.LENGTH_SHORT).show(); return true; } } public class ActionbarActivity extends Activity { ... public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(this, "from Activity", Toast.LENGTH_SHORT).show(); return true; } } From Fragment with Love... When clicking an item from actionbar: a) shows toast: "from Activity" b) shows toast: "from Fragment" c) shows both toasts d) shows toast depending on who the creator of the menu item
  • 25. public class ActionbarFragment extends Fragment { ... public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) { setHasOptionsMenu(true); return inf.inflate(R.layout.fragment_get_view, null); } public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(getActivity(), "from Fragment", Toast.LENGTH_SHORT).show(); return true; } } public class ActionbarActivity extends Activity { ... public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(this, "from Activity", Toast.LENGTH_SHORT).show(); return true; } } From Fragment with Love... When clicking an item from actionbar: a) shows toast: "from Activity" b) shows toast: "from Fragment" c) shows both toasts d) shows toast depending on who the creator of the menu item
  • 26. "If you added the menu item from a fragment, then the respective onOptionsItemSelected() method is called for that fragment. However the activity gets a chance to handle it first, so the system calls onOptionsItemSelected() on the activity before calling the fragment." ● RTFJD: read the fucking java doc:
  • 27. On pre 2.3.6 Android's HttpUrlConnection is broken as soon as the server supports more than Basic authentication ? You'll get IndexOutOfBoundsException Be aware of platform dependent puzzles.... or did you know that? int realm = challenge.indexOf("realm="") + 7; WWW-Authenticate: Basic realm="RealmName" WWW-Authenticate: NTLM
  • 28. protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] longList = new String[1000000]; Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra("droidcon", longList); startActivityForResult(intent, 100); } protected void onActivityResult(int request, int result, Intent data) { super.onActivityResult(request, result, data); Log.e("droidcon", "result" + request + " " + result); } a) OutOfMemoryException in onCreate() b) IllegalArgumentException in onCreate() c) Nothing happens, direct invocation of onActivityResult (with cancel code) d) Nothing happens, no invocation of onActivityResult e) System-Intent-Picker for "sent" action will be shown normally The world is not enough ...
  • 29. protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] longList = new String[1000000]; Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra("droidcon", longList); startActivityForResult(intent, 100); } protected void onActivityResult(int request, int result, Intent data) { super.onActivityResult(request, result, data); Log.e("droidcon", "result" + request + " " + result); } a) OutOfMemoryException in onCreate() b) IllegalArgumentException in onCreate() c) Nothing happens, direct invocation of onActivityResult (with cancel code) d) Nothing happens, no invocation of onActivityResult e) System-Intent-Picker for "sent" action will be shown normally The world is not enough ...
  • 30. Logcat shows: 11-12 16:25:53.391: E/JavaBinder(6247): !!! FAILED BINDER TRANSACTION !!! Some devices show TransactionTooLargeException: The Binder transaction failed because it was too large. During a remote procedure call, the arguments and the return value of the call are transferred as Parcel objects stored in the Binder transaction buffer. If the arguments or the return value are too large to fit in the transaction buffer, then the call will fail and TransactionTooLargeException will be thrown. The Binder transaction buffer has a limited fixed size, currently 1Mb, which is shared by all transactions in progress for the process. Consequently this exception can be thrown when there are many transactions in progress even when most of the individual transactions are of moderate size.
  • 31. Be aware of platform dependent puzzles.... or did you know that? Starting with 2.3 HTTPUrlConnection handles and sets gzip as Content-Encoding. This leads to errors if you get a response where there is no content but a Content- Length (=0) or a Content-Encoding(=gzip). getResponceCode leads to EOFException
  • 32. public class AsyncTaskActivity extends Activity{ ... protected void onResume() { super.onResume(); TextView testV = (TextView) findViewById(R.id.async_text_1); new WritingAsyncTask(testV,2000).execute(" Bob"); new WritingAsyncTask(testV,100).execute("Alice"); new WritingAsyncTask(testV,500).execute("loves"); } ... public class WritingAsyncTask extends AsyncTask<String, Void, String>{... private final TextView view;//set in Constructor private final int timeout;//set in Constructor protected String doInBackground(String... params) { try {Thread.sleep(timeout);} catch (InterruptedException e) {} return params[0]; } protected void onPostExecute(String result) { view.setText(view.getText()+" "+result);} Casino Royal What is shown in the TextView when I start the Activity on my Galaxy Nexus: a) Alice loves Bob b) Bob Alice loves c) Bob loves Alice d) There is not enough information to decide
  • 33. public class AsyncTaskActivity extends Activity{ ... protected void onResume() { super.onResume(); TextView testV = (TextView) findViewById(R.id.async_text_1); new WritingAsyncTask(testV,2000).execute(" Bob"); new WritingAsyncTask(testV,100).execute("Alice"); new WritingAsyncTask(testV,500).execute("loves"); } ... public class WritingAsyncTask extends AsyncTask<String, Void, String>{... private final TextView view;//set in Constructor private final int timeout;//set in Constructor protected String doInBackground(String... params) { try {Thread.sleep(timeout);} catch (InterruptedException e) {} return params[0]; } protected void onPostExecute(String result) { view.setText(view.getText()+" "+result);} Casino Royal What is shown in the TextView when I start the Activity on my Galaxy Nexus: a) Alice loves Bob b) Bob Alice loves c) Bob loves Alice d) There is not enough information to decide
  • 34. public class AsyncTaskActivity extends Activity{ ... protected void onResume() { super.onResume(); TextView testV = (TextView) findViewById(R.id.async_text_1); new WritingAsyncTask(testV,2000).execute(" Bob"); new WritingAsyncTask(testV,100).execute("Alice"); new WritingAsyncTask(testV,500).execute("loves"); } ... public class WritingAsyncTask extends AsyncTask<String, Void, String>{... private final TextView view;//set in Constructor private final int timeout;//set in Constructor protected String doInBackground(String... params) { try {Thread.sleep(timeout);} catch (InterruptedException e) {} return params[0]; } protected void onPostExecute(String result) { view.setText(view.getText()+" "+result);} Casino Royal What is shown in the TextView when I start the Activity on my Galaxy Nexus: a) Alice loves Bob b) Bob Alice loves .... usually c) Bob loves Alice d) There is not enough information to decide
  • 35. public class AsyncTaskActivity extends Activity{ ... protected void onResume() { super.onResume(); TextView testV = (TextView) findViewById(R.id.async_text_1); new WritingAsyncTask(testV,2000).execute(" Bob"); new WritingAsyncTask(testV,100).execute("Alice"); new WritingAsyncTask(testV,500).execute("loves"); } ... public class WritingAsyncTask extends AsyncTask<String, Void, String>{... private final TextView view;//set in Constructor private final int timeout;//set in Constructor protected String doInBackground(String... params) { try {Thread.sleep(timeout);} catch (InterruptedException e) {} return params[0]; } protected void onPostExecute(String result) { view.setText(view.getText()+" "+result);} Casino Royal What is shown in the TextView when I start the Activity on my Galaxy Nexus: a) Alice loves Bob b) Bob Alice loves c) Bob loves Alice d) There is not enough information to decide
  • 36. You need to know the android:targetSdkVersion (and the Device Version of the Target Device) android:targetSdkVersion < 13: AsyncTask is executed parallel android:targetSdkVersion >= 13 && Device OS >= 14: AsyncTask is executed serial from AsyncTask.Java: ... public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; ... You can enforce parallel execution in SDK >= 11 executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,...);
  • 37. public class ManyAsyncTasksActivity extends Activity{ ... protected void onResume() { super.onResume(); TextView testV = (TextView) findViewById(R.id.async_text_1); for (int i = 0; i < 200; i++) { new WritingAsyncTask(testV,100).execute(i+","); } } ... public class WritingAsyncTask extends AsyncTask<String, Void, String>{... private final TextView view;//set in Constructor private final int timeout;//set in Constructor protected String doInBackground(String... params) { try {Thread.sleep(timeout);} catch (InterruptedException e) {} return params[0]; } protected void onPostExecute(String result) { view.setText(view.getText()+" "+result);} Moonraker What is shown when I start the Activity on my G. Nexus (target SDK is 11, A: 4.1.2) : a) Numbers from 0 to 199 in random order b) Application Error (App has stopped) c) Numbers from 0 to 199 in serial order d) Numbers from 0 to 127 in random order e) Numbers from 0 to 137 in random order
  • 38. public class ManyAsyncTasksActivity extends Activity{ ... protected void onResume() { super.onResume(); TextView testV = (TextView) findViewById(R.id.async_text_1); for (int i = 0; i < 200; i++) { new WritingAsyncTask(testV,100).execute(i+","); } } ... public class WritingAsyncTask extends AsyncTask<String, Void, String>{... private final TextView view;//set in Constructor private final int timeout;//set in Constructor protected String doInBackground(String... params) { try {Thread.sleep(timeout);} catch (InterruptedException e) {} return params[0]; } protected void onPostExecute(String result) { view.setText(view.getText()+" "+result);} Moonraker What is shown when I start the Activity on my G. Nexus (target SDK is 11, A: 4.1.2) : a) Numbers from 0 to 199 in random order b) Application Error (App has stopped) c) Numbers from 0 to 199 in serial order d) Numbers from 0 to 127 in random order e) Numbers from 0 to 137 in random order
  • 39. LogCat shows: java.lang.RuntimeException: Unable to resume activity {...}: java.util.concurrent. RejectedExecutionException: Task android.os.AsyncTask ... rejected from java.util.concurrent. ThreadPoolExecutor ... [Running, pool size = 128, active threads = 128, queued tasks = 10, completed tasks = 0] ThreadPoolExecutor currently only accepts a given number of Tasks, default value is a pool size of 128. private static final int MAXIMUM_POOL_SIZE = 128; ... private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(10);