SlideShare ist ein Scribd-Unternehmen logo
1 von 56
Downloaden Sie, um offline zu lesen
Android Code Puzzlers
+TIPS
& TRICKS

Can you solve all our challenges?

NLJUG JFall
Wednesday November 6th
!

Johan Pelgrim & Hugo Visser

The Dutch Android User Group

http://www.dutchaug.org
Johan Pelgrim
• Android Developer!
• Working at VX Company 


@jowipe

http://www.vxcompany.com!

• Organizer The Dutch Android User Group!
• Written Android articles and recipes for

http://www.androidcookbook.com

The Dutch Android User Group

http://www.dutchaug.org
Hugo Visser
• Android Developer!
• Working at Qbus


@botteaap

http://www.qbus-ict.nl!

• Organizer The Dutch Android User Group!
• Developer of Rainy Days 

and Figure Running and ...

The Dutch Android User Group

http://www.dutchaug.org
DutchAUG
• Open Group - Dutch Focus & Spread - Free to join!!
• Monthly meetups http://www.dutchaug.org !
• Started nov 2011 (at droidconNL)!
• Foundation since feb 2013!
• We are a Google Developer Group (GDG)!
• @dutchaug #dutchaug!
The Dutch Android User Group
•
The Dutch Android User Group

http://www.dutchaug.org
DutchAUG
Wiebe

Dennis

Hugo

Johan

Elsinga!
Itude Mobile

Visser!
Qbus

The Dutch Android User Group

http://www.dutchaug.org

Geurts!
Luminis

Pelgrim!
VX Company
DutchAUG
Main sponsor

http://www.nspyre.nl/android
The Dutch Android User Group

http://www.dutchaug.org
DutchAUG
Main sponsor

http://www.vxcompany.com
The Dutch Android User Group

http://www.dutchaug.org
The Dutch Android User Group

http://www.dutchaug.org
DutchAUG

Upcoming meetup

Android 4.4 KitKat
& Play Services 4
January
Utrecht
The Dutch Android User Group

http://www.dutchaug.org
Android Code Puzzlers

Can you solve all our challenges?

•
•
•

We present a puzzle
You chew on it for a while
If you know the answer

(and more importantly...why) 


you win!
The Dutch Android User Group

http://www.dutchaug.org
Everybody Ready?
The Dutch Android User Group

http://www.dutchaug.org
Layout puzzle
Which picture matches this layout:!

<?xml version="1.0" encoding="utf-8"?>!
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"!
android:layout_width="fill_parent"!
android:layout_height="fill_parent" >!
<TextView!
android:layout_height="wrap_content"!
android:layout_width="fill_parent"!
android:text="Layout Puzzle 1"!
android:layout_gravity="center"!
android:gravity="center_vertical" />!
</RelativeLayout>!

!

A)

B)

The Dutch Android User Group

C)!

http://www.dutchaug.org

pu

zz

le
Layout puzzle
Which picture matches this layout:!

<?xml version="1.0" encoding="utf-8"?>!
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"!
android:layout_width="fill_parent"!
android:layout_height="fill_parent" >!
<TextView!
android:layout_height="wrap_content"!
android:layout_width="fill_parent"!
android:text="Layout Puzzle 1"!
android:layout_gravity="center"!
android:gravity="center_vertical" />!
</RelativeLayout>!

!

A)

B)

The Dutch Android User Group

C)!

http://www.dutchaug.org

pu

zz

le
You Only Frag Twice
Single activity, with a single fragment!

!

Activity:!
protected void onCreate(Bundle savedInstanceState) {!
super.onCreate(savedInstanceState);!
setContentView(R.layout.single_fragment);!
if (savedInstanceState == null) {!
getFragmentManager().beginTransaction().add(R.id.single_fragment, !
new YouOnlyFragTwiceFragment());!
}!
}!

!

single_fragment.xml:!
<?xml version="1.0" encoding="utf-8"?>!
<merge>!
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"!
android:id="@+id/single_fragment"!
android:layout_width="fill_parent"!
android:layout_height="fill_parent" />!
</merge>!

!

What happens when the Activity is started?!
A) Fragment is shown and filling the screen!
B) Activity crashes!
C) Nothing is shown

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
You Only Frag Twice
Single activity, with a single fragment!

!

Activity:!
protected void onCreate(Bundle savedInstanceState) {!
super.onCreate(savedInstanceState);!
setContentView(R.layout.single_fragment);!
if (savedInstanceState == null) {!
getFragmentManager().beginTransaction().add(R.id.single_fragment, !
new YouOnlyFragTwiceFragment());!
.commit();
}!
}!

!

single_fragment.xml:!
<?xml version="1.0" encoding="utf-8"?>!
<merge>!
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"!
android:id="@+id/single_fragment"!
android:layout_width="fill_parent"!
android:layout_height="fill_parent" />!
</merge>!

!

What happens when the Activity is started?!
A) Fragment is shown and filling the screen!
B) Activity crashes!
C) Nothing is shown
C) Nothing is shown

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
License to click
Fragment layout:!
<Button android:text="Don't click me!"!
android:layout_centerInParent="true"!
android:onClick="clicked" />!

!

In activity:!
public void clicked(View v) {!
Toast.makeText(this, "onClick from activity", 1).show();!
}!

!
!

In fragment:!
public void clicked(View v) {!
Toast.makeText(getActivity(), "onClick from fragment", 1).show();!
}!

!

What happens when
A) Toast “onClick
B) Toast “onClick
C) First “onClick
D) First “onClick

I tap the button?!
from activity” is shown!
from fragment” is shown!
from activity” then “onClick from fragment” is shown!
from fragment” then “onClick from activity” is shown!

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
License to click
Fragment layout:!
<Button android:text="Don't click me!"!
android:layout_centerInParent="true"!
android:onClick="clicked" />!

!

In activity:!
public void clicked(View v) {!
Toast.makeText(this, "onClick from activity", 1).show();!
}!

!
!

In fragment:!
public void clicked(View v) {!
Toast.makeText(getActivity(), "onClick from fragment", 1).show();!
}!

!

What happens when
A) Toast “onClick
B) Toast “onClick
C) First “onClick
D) First “onClick

I tap the button?!
from activity” is shown!
from fragment” is shown!
from activity” then “onClick from fragment” is shown!
from fragment” then “onClick from activity” is shown!

A) Toast “onClick from activity” is shown

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
A view to a kill
public class GetViewActivity extends Activity {!

!

!
!
!
!
!
!
!
!
!
!
!
!
}!

!
@Override!
protected void onCreate(Bundle savedInstanceState) {!
!
super.onCreate(savedInstanceState);!
!
setContentView(R.layout.view_to_a_kill);!
!
!
!
getFragmentManager().beginTransaction()!
!
!
.replace(R.id.content, new GetViewFragment())!
!
!
.commit();!
}!
!
!

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
A view to a kill
public class GetViewFragment extends Fragment {!

!

!

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

!

!

!
!

!
!

!
!
!
!

!
!
!
}!

!

!

getView().setOnClickListener(new View.OnClickListener() {!
!
@Override!
public void onClick(View v) {!
!
!
Toast.makeText(getActivity(), "My name is droid, android", 1);!
!
}!
});!

@Override!
public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {!
!
return inf.inflate(R.layout.fragment_get_view, view);!
}!

!
!

!

}!
What happens when the Activity is started?!
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()

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
A view to a kill
public class GetViewFragment extends Fragment {!

!

!

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

!

!

!
!

!
!

!
!
!
!

!
!
!
}!

!

!

getView().setOnClickListener(new View.OnClickListener() {!
!
@Override!
public void onClick(View v) {!
!
!
Toast.makeText(getActivity(), "My name is droid, android", 1);!
!
}!
});!

@Override!
public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {!
!
return inf.inflate(R.layout.fragment_get_view, view);!
}!

!
!

!

}!
What happens when the Activity is started?!
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()
D) Exception in GetViewFragment.onCreate()!
E) Exception in Fragment.onCreateView()

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
A view to a kill
public class GetViewFragment extends Fragment {!

!

!

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

!

!

!
!

!
!

!
!
!
!

!
!
!
}!

!

!

getView().setOnClickListener(new View.OnClickListener() {!
!
@Override!
public void onClick(View v) {!
!
!
Toast.makeText(getActivity(), "My name is droid, android", 1);!
!
}!
});!

@Override!
public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {!
!
return inf.inflate(R.layout.fragment_get_view, view);!
}!

!
!

!

}!
What happens when the Activity is started?!
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()
D) Exception in GetViewFragment.onCreate()!
E) Exception in Fragment.onCreateView()

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
Alpha / Beta builds

The Dutch Android User Group

http://www.dutchaug.org

TI

P
Live And Let Die
public class ToastFragment extends Fragment {!
...!
public void onDestroy() {!
super.onDestroy();!
new ToastingAsyncTask().execute(null,null,null);!
}!

!

!

class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{!
protected Long doInBackground(String... params) {!
try {Thread.sleep(500);} catch (InterruptedException e) {}!
return null;!
}!
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));!
} !
}!
}
!
what happens when I change the orientation?!
A) Sysout: no_activity!
B) Sysout: activity_leak!
C) Sysout: null!
D) Exception in getActivity !
E) Exception in getString

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
Live And Let Die
public class ToastFragment extends Fragment {!
...!
public void onDestroy() {!
super.onDestroy();!
new ToastingAsyncTask().execute(null,null,null);!
}!

!

!

class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{!
protected Long doInBackground(String... params) {!
try {Thread.sleep(500);} catch (InterruptedException e) {}!
return null;!
}!
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));!
} !
}!
}
!
what happens when I change the orientation?!
A) Sysout: no_activity!
B) Sysout: activity_leak!
C) Sysout: null!
E) Exception in !
D) Exception in getActivity getString...
E) Exception in getString

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
Live And Let Die
public class ToastFragment extends Fragment {!
LogCat:
...!
public void onDestroy() {!
super.onDestroy();!
java.lang.IllegalStateException:
new ToastingAsyncTask().execute(null,null,null);!
}! Fragment ToastFragment not attached

!

to

Activity!

class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{!
! protected Long doInBackground(String... params) {!
try {Thread.sleep(500);} catch (InterruptedException e) {}!
return null;!
}!
!
protected void onPostExecute(Long result) {!
Know about the life cycle of Activities,
if (getActivity() == null){!
System.out.println(getString(R.string.no_activity));!
Fragments, Services!!
}else{!
!
System.out.println(getString(R.string.activity_leak));!
And...!
} !
}! !
}
!

A Context holds your Resources!!

!

“Use the source Luke!”!

what happens when I change the orientation?!
A) Sysout: no_activity!
B) Sysout: activity_leak!
C) Sysout: null!
D) Exception in getActivity !
E) Exception in getString

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
Live And Let Die

pu

!
public class Fragment ...!
!
public final String getString(int resId) {!
return getResources().getString(resId);!
}!
!
final public Resources getResources() {!
    if (mActivity == null) {!
        throw new IllegalStateException("Fragment " + this + !
" not attached to Activity");!
    }!
    return mActivity.getResources();!
}!
!

The Dutch Android User Group

http://www.dutchaug.org

zz

le
From Fragment with love
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", 1).show();!
return true;!
} !
}!

!

public class ActionbarActivity extends Activity {!
...!
public boolean onOptionsItemSelected(MenuItem item) {!
Toast.makeText(this, "from Activity", 1).show();!
return true;!
} !
}!

!

When clicking an ActionBar item: !
a) Shows toast “from Activity”!
b) Shows toast “from Fragment”!
c) Shows both toasts!
d) Shows toast depending on who created the menu item

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
From Fragment with love
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", 1).show();!
return true;!
} !
}!

!

public class ActionbarActivity extends Activity {!
...!
public boolean onOptionsItemSelected(MenuItem item) {!
Toast.makeText(this, "from Activity", 1).show();!
return true;!
} !
}!

!

When clicking an ActionBar item: !
a) Shows toast “from Activity”!
b) Shows toast “from Fragment”!
A) Shows toast “from Activity”
c) Shows both toasts!
d) Shows toast depending on who created the menu item

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
Support Library

D
e
tip vel
s & op
tr men
ick t

s

• Fragment / ListFragment / DialogFragment!
• ViewPager!
• LoaderManager / CursorLoader!
• Many many compat classes!
• LruCache / SparseArray!
• Navigation Drawer (DrawerLayout)
The Dutch Android User Group

http://www.dutchaug.org
Google Play Services

• Google Maps v2!
• Geofencing!
• Google+ Sign-in!
• Activity Recognition!
• Google Cloud Messaging!
• And more...
The Dutch Android User Group

http://www.dutchaug.org

D
e
tip vel
s & op
tr men
ick t

s
Casino Royal
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,500).execute("loves");!
new WritingAsyncTask(testV,100).execute("Alice");!
} ...!

!

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);!
}!
}!

!

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

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
Casino Royal
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,500).execute("loves");!
new WritingAsyncTask(testV,100).execute("Alice");!
} ...!

!

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);!
}!
}!

!

What is shown in the TextView when I start the Activity on my Galaxy Nexus: !
a) Alice loves Bob!
b) Bob Alice loves!
D) loves Alice!
c) BobThere is not enough information to decide...
d) There is not enough information to decide

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
Casino Royal

pu

zz

le

D) There is not enough information to decide...
!
You need to know the targetSdkVersion and the device OS version of the target device!

!

android:targetSdkVersion <

!

13:

parallel execution!

android:targetSdkVersion >= 13 !
&& Device OS >= 14: serial

!
!

execution!

This is what we see in AsyncTask.Java:!

!

public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); !
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;!

!
!

You are in control of the type of execution in SDK >= 11!

!
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,…);!
!

The Dutch Android User Group

http://www.dutchaug.org
Casino Royal
android:minSdkVersion=“14”!
!
Go for minSdkVersion=“14” (Android 4.0 / Ice Cream Sandwich)!
Second best minSdkVersion = “10” (Android 2.3.3 / Gingerbread)!
E.g. Google Play Services new API’s > 10!
Don’t do anything lower than 10!

!
android:targetSdkVersion=“19”!
!

Always set this to the latest Android API level!

!
!
android:maxSdkVersion!
!

Don’t use this. Everything is backwards compatible by default.!

!
!

The Dutch Android User Group

http://www.dutchaug.org

D
e
tip vel
s & op
tr men
ick t

s
Custom Views
View:!
public class MyCustomView extends LinearLayout {!
public MyCustomView(Context context, AttributeSet attrs) {!
super(context, attrs);!
LayoutInflater.from(context).inflate(R.layout.component, this, true);!
// more stuff here!
}!
}!

!

component.xml!
<?xml version="1.0" encoding="utf-8"?>!
<LinearLayout ... >!
<TextView android:id="@+id/label” ... />!
    <EditText android:id="@+id/value” ... />!
</LinearLayout>!

!

layout.xml!
<LinearLayout android:orientation="vertical">!
<org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>!
<org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>!
<org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>!
</LinearLayout>!

!

When you inflate layout.xml in an Activity: !
a) Everything works fine!
b) Exception on inflating the XML!
c) Everything appears to look fine, but there are subtle bugs!
d) The app crashes when entering text in the first EditText!

!

Hint: How does the view tree look when the layout is inflated?!

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
Custom Views
View:!
public class MyCustomView extends LinearLayout {!
public MyCustomView(Context context, AttributeSet attrs) {!
super(context, attrs);!
LayoutInflater.from(context).inflate(R.layout.component, this, true);!
// more stuff here!
}!
}!

!

component.xml!
<?xml version="1.0" encoding="utf-8"?>!
<LinearLayout ... >!
<TextView android:id="@+id/label” ... />!
    <EditText android:id="@+id/value” ... />!
</LinearLayout>!

!

layout.xml!
<LinearLayout android:orientation="vertical">!
<org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>!
<org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>!
<org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>!
</LinearLayout>!

!

When you inflate layout.xml in an Activity: !
a) Everything works fine!
b) Exception on inflating the XML! to look fine, but there!
C) Everything appears
c) Everything appears to look fine, but there are subtle bugs!
are crashes when entering text in the first EditText!
d) The app subtle bugs

!

Hint: How does the view tree look when the layout is inflated?!

The Dutch Android User Group

http://www.dutchaug.org

pu

zz

le
Custom Views

pu

zz

le

After inflate:!

!

<LinearLayout>!
<LinearLayout ... >!
<TextView android:id="@+id/label"
<EditText android:id="@+id/value"
</LinearLayout>!
<LinearLayout ...>!
<TextView android:id="@+id/label"
<EditText android:id="@+id/value"
</LinearLayout>!
<LinearLayout ...>!
<TextView android:id="@+id/label"
<EditText android:id="@+id/value"
</LinearLayout>!
</LinearLayout>!

... />!
... />!
... />!
... />!
... />!
... />!

!

Oops:!

!

1.OnSaveInstanceState is called in LinearLayout !
2.LinearLayout calls saveHierarchyState(SparseArray<Parcelable> state) on children!
3.Child returns Parcelable which is put in the state and keyed on the view id!
4.When state is restored, there is a single value for label, and a single value for value.!

!

The Dutch Android User Group

http://www.dutchaug.org
The World Is Not Enough

pu

zz

le

@Override!
protected void onStart() {!
! super.onStart();!
! ! !
! String[] longList = new String[1000000];!
! Intent intent = new Intent(Intent.ACTION_SEND);!
! intent.setType("text/plain");!
! intent.putExtra("dutchaug", longList);!
! startActivityForResult(intent, 100);!

!

}!

!
!

What happens when the activity is started?!
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 Dutch Android User Group

http://www.dutchaug.org
The World Is Not Enough

pu

zz

le

@Override!
protected void onStart() {!
! super.onStart();!
! ! !
! String[] longList = new String[1000000];!
! Intent intent = new Intent(Intent.ACTION_SEND);!
! intent.setType("text/plain");!
! intent.putExtra("dutchaug", longList);!
! startActivityForResult(intent, 100);!

!

}!

!
!

What happens when the activity is started?!
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...
D) Nothing happens, no invocation of onActivityResult

E) System-Intent-Picker for "sent" action will be shown normally

The Dutch Android User Group

http://www.dutchaug.org
The World Is Not Enough

pu

zz

le

Logcat shows:!
26-02 17:25:53.391: E/JavaBinder(6247): !!! FAILED BINDER TRANSACTION !!!!

!

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 (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.!

The Dutch Android User Group

http://www.dutchaug.org
No more puzzles...
But some more:

The Dutch Android User Group

http://www.dutchaug.org
compound drawable

D
e
tip vel
s & op
tr men
ick t

s

<RelativeLayout ...>!

!

!

!
!

!

<LinearLayout ...>!
<ImageView!
android:layout_marginRight="15dp"!
android:layout_width="wrap_content"!
android:layout_height="wrap_content"!
android:src="@drawable/dutchaug" />!
<TextView!
android:layout_width="wrap_content"!
android:layout_height="wrap_content"!
android:text="DutchAUG" />!
</LinearLayout>!
<!-- this does not require a nested LinearLayout -->!
<TextView!
android:drawableLeft="@drawable/dutchaug"!
android:drawablePadding="15dp"!
android:layout_width="wrap_content"!
android:layout_height="wrap_content"!
android:text="DutchAUG" />!

</RelativeLayout>!

The Dutch Android User Group

http://www.dutchaug.org

DutchAUG
Level list drawable

D
e
tip vel
s & op
tr men
ick t

s

• Drawables have setLevel() 0...10000!
• Assign drawable level range
!
Somewhere in a BaseAdapter far, far away...!

!

if (error) {!
Drawable d = getContext().getResources().getDrawable(R.drawable.error);!
mTextView.setCompoundDrawablesWithIntrinsicBounds(d, null, null, null)!
} else {!
Drawable d = getContext().getResources().getDrawable(R.drawable.ok);!
mTextView.setCompoundDrawablesWithIntrinsicBounds(d, null, null, null)
}!

The Dutch Android User Group

http://www.dutchaug.org
Level list drawable
Level list drawable:!

!

<level-list xmlns:android="http://schemas.android.com/apk/res/android">!
  <item android:maxLevel="0" android:drawable="@drawable/ic_state_ok" />!
  <item android:maxLevel="1" android:drawable="@drawable/ic_state_error" /> !
<!-- more variants... -->!
</level-list>!

!

BetterAdapter.java!

!

// Constants please!!
private static final int LEVEL_OK = 0;!
private static final int LEVEL_ERROR = 1;!

!

if (error) {!
mTextView.getCompoundDrawables()[0].setLevel(LEVEL_ERROR)!
} else {!
mTextView.getCompoundDrawables()[0].setLevel(LEVEL_OK)!
}!

!

Or less verbose:!
!
mTextView.getCompoundDrawables()[0].setLevel(error ? LEVEL_ERROR : LEVEL_OK)!

!

The Dutch Android User Group

http://www.dutchaug.org

D
e
tip vel
s & op
tr men
ick t

s
android.text.format.DateUtils

D
e
tip vel
s & op
tr men
ick t

s

• CharSequence

getRelativeTimeSpanString
(long time, long now, long minResolution)!

• now – System.currentTimeMillis()!
• minResolution – e.g. SECOND_IN_MILLIS
the smallest unit of time will be
seconds.!

• English example: “2 seconds ago”!
• Or in German: “Vor 2 Sekunden”
The Dutch Android User Group

http://www.dutchaug.org

so
android.text.TextUtils

D
e
tip vel
s & op
tr men
ick t

s

• boolean isDigitsOnly(CharSequence str)!
• boolean isEmpty(CharSequence str)!
• String htmlEncode(String s)!
• CharSequence commaEllipsize(...)!
• CharSequence ellipsize(...)
fromHTML
<string name="htmlFormattedText">!
<![CDATA[!
<p>Text with markup for!
<strong>bold</strong>!
and <em>italic</em> text.</p>!
<p>There is also support for a !
<tt>monospaced</tt>font. !
But no use for the !
<code>code</code> tag!</p>!
]]>!
</string>

TextView view = (TextView)findViewById(R.id.sampleText);!
String formattedText = getString(R.string.htmlFormattedText);!
Spanned result = Html.fromHtml(formattedText);!
view.setText(result);

The Dutch Android User Group

http://www.dutchaug.org

D
e
tip vel
s & op
tr men
ick t

s
Annotation Processors

• @InjectView (Butter Knife)


http://jakewharton.github.io/butterknife/!

• @Frozen @Argument


https://bitbucket.org/hvisser/bundles!

• Android Annotations


http://androidannotations.org

The Dutch Android User Group

http://www.dutchaug.org

D
e
tip vel
s & op
tr men
ick t

s
Annotation Processors
public class MainActivityBefore extends Activity {!

!
!
!

int mLoginCount;!
String mCurrentUser;!
long mSessionExpiresAt;!
@Override!
protected void onCreate(Bundle savedInstanceState) {!
super.onCreate(savedInstanceState);!
setContentView(R.layout.activity_main);!
if (savedInstanceState != null) {!
mLoginCount = savedInstanceState.getInt("login_count");!
mCurrentUser = savedInstanceState.getString("user");!
mSessionExpiresAt = savedInstanceState.getLong("session_expire");!

!

DemoBeforeFragment fragment = new DemoBeforeFragment();!
Bundle args = new Bundle();!
args.putString("greeting", "Hello!");!
fragment.setArguments(args);!

!
!
!

D
e
tip vel
s & op
tr men
ick t

s

getFragmentManager().beginTransaction().add(R.id.main_fragment, fragment).commit();!
}!
}!
@Override!
protected void onSaveInstanceState(Bundle outState) {!
super.onSaveInstanceState(outState);!
outState.putInt("login_count", mLoginCount);!
outState.putString("user", mCurrentUser);!
// something is not quite right here...!
outState.putLong("session_expre", mSessionExpiresAt);!
}!

}!

The Dutch Android User Group

http://www.dutchaug.org
Annotation Processors

D
e
tip vel
s & op
tr men
ick t

s

public class DemoBeforeFragment extends Fragment {!
TextView mTextView;!
Button mLoginButton;!

!
!

!

String mGreeting;!
int mVisitCount = 0;!
@Override!
public void onCreate(Bundle savedInstanceState) {!
super.onCreate(savedInstanceState);!
mGreeting = getArguments().getString("greeting");!
mVisitCount = getArguments().getInt("visit_count", 0);!
}!
@Override!
public View onCreateView(LayoutInflater inflater, ViewGroup container, !
Bundle savedInstanceState) {!
View view = inflater.inflate(R.layout.activity_main, container, false);!
mTextView = (TextView) view.findViewById(R.id.greeting);!
mLoginButton = (Button) view.findViewById(R.id.login);!
mTextView.setText(mGreeting);!
return view;!
}!

}

The Dutch Android User Group

http://www.dutchaug.org
Annotation Processors

D
e
tip vel
s & op
tr men
ick t

s

public class MainActivityAfter extends Activity {!

!
!

!

@Frozen int mLoginCount;!
@Frozen String mCurrentUser;!
@Frozen long mSessionExpiresAt;!
@Override!
protected void onCreate(Bundle savedInstanceState) {!
super.onCreate(savedInstanceState);!
setContentView(R.layout.activity_main);!
MainActivityAfterState.restoreInstanceState(this, savedInstanceState);!
if (savedInstanceState != null) {!
Fragment fragment = DemoAfterFragmentBuilder.newDemoAfterFragment("Hello");!
getFragmentManager().beginTransaction().add(R.id.main_fragment,!
fragment).commit();!
}!
}!
@Override!
protected void onSaveInstanceState(Bundle outState) {!
super.onSaveInstanceState(outState);!
MainActivityAfterState.saveInstanceState(this, outState);!
}!

}

The Dutch Android User Group

http://www.dutchaug.org
Annotation Processors

D
e
tip vel
s & op
tr men
ick t

s

public class DemoAfterFragment extends Fragment {!
@InjectView(R.id.greeting) TextView mTextView;!
@InjectView(R.id.login) Button mLoginButton;!

!
!

!

!

@Argument String mGreeting;!
@Argument(required=false) int mVisitCount = 0;!
@Override!
public void onCreate(Bundle savedInstanceState) {!
super.onCreate(savedInstanceState);!
DemoAfterFragmentBuilder.injectArguments(this);!
}!
@Override!
public View onCreateView(LayoutInflater inflater, ViewGroup container, !
Bundle savedInstanceState) {!
View view = inflater.inflate(R.layout.activity_main, container, false);!
Views.inject(this, view);!

!

mTextView = (TextView) view.findViewById(R.id.greeting);!
mLoginButton = (Button) view.findViewById(R.id.login);!
mTextView.setText(mGreeting);!
return view;!
}!
}

The Dutch Android User Group

http://www.dutchaug.org
Proguard

• Code optimalizations


E.g. Log.d has no side effects!

• Code reduction


Unused methods / classes!

• Code obfuscation (secure?)


DexGuard does a better job!

Watch Eric LaFortune on

http://youtube.com/dutchaug
The Dutch Android User Group

http://www.dutchaug.org
Use Lint

• From Eclipse!
• lint <project dir>!
• Jenkins lint plugin

The Dutch Android User Group

http://www.dutchaug.org

D
e
tip vel
s & op
tr men
ick t

s
Jenkins
test and deploy

• Automate Android build,your AndroidManifest!
E.g. use Jenkins build number in

• “There’s a plug-in for that!”

Watch Christopher Orr on

http://youtube.com/dutchaug
The Dutch Android User Group

http://www.dutchaug.org
http://bit.ly/android-puzzlers

THE END
Thanks for your
participation!
Get the puzzle code
The Dutch Android User Group

http://www.dutchaug.org

Weitere ähnliche Inhalte

Was ist angesagt?

Android Unit Testing With Robolectric
Android Unit Testing With RobolectricAndroid Unit Testing With Robolectric
Android Unit Testing With RobolectricDanny Preussler
 
Groovy And Grails JUG Padova
Groovy And Grails JUG PadovaGroovy And Grails JUG Padova
Groovy And Grails JUG PadovaJohn Leach
 
Android Code Puzzles (DroidCon Amsterdam 2012)
Android Code Puzzles (DroidCon Amsterdam 2012)Android Code Puzzles (DroidCon Amsterdam 2012)
Android Code Puzzles (DroidCon Amsterdam 2012)Danny Preussler
 
The 2016 Android Developer Toolbox [MOBILIZATION]
The 2016 Android Developer Toolbox [MOBILIZATION]The 2016 Android Developer Toolbox [MOBILIZATION]
The 2016 Android Developer Toolbox [MOBILIZATION]Nilhcem
 
The Spirit of Testing
The Spirit of TestingThe Spirit of Testing
The Spirit of TestingMarco Cedaro
 
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)Danny Preussler
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear EssentialsNilhcem
 
jQuery Internals + Cool Stuff
jQuery Internals + Cool StuffjQuery Internals + Cool Stuff
jQuery Internals + Cool Stuffjeresig
 
Performance #6 threading
Performance #6  threadingPerformance #6  threading
Performance #6 threadingVitali Pekelis
 
Naive application development
Naive application developmentNaive application development
Naive application developmentShaka Huang
 
Gdg san diego android 11 meetups what's new in android - ui and dev tools
Gdg san diego android 11 meetups  what's new in android  - ui and dev toolsGdg san diego android 11 meetups  what's new in android  - ui and dev tools
Gdg san diego android 11 meetups what's new in android - ui and dev toolsSvetlin Stanchev
 
Androidの本当にあった怖い話
Androidの本当にあった怖い話Androidの本当にあった怖い話
Androidの本当にあった怖い話Yusuke Yamamoto
 
Session #6 loaders and adapters
Session #6  loaders and adaptersSession #6  loaders and adapters
Session #6 loaders and adaptersVitali Pekelis
 
HTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranHTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranRobert Nyman
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suckRoss Bruniges
 
Tinkerbelles return home from their Guinness world-record attempt on Sunday
Tinkerbelles return home from their Guinness world-record attempt on SundayTinkerbelles return home from their Guinness world-record attempt on Sunday
Tinkerbelles return home from their Guinness world-record attempt on Sundaychicagonewsyesterday
 
JavaScript APIs you’ve never heard of (and some you have)
JavaScript APIs you’ve never heard of (and some you have)JavaScript APIs you’ve never heard of (and some you have)
JavaScript APIs you’ve never heard of (and some you have)Nicholas Zakas
 
jQuery For Developers Stack Overflow Dev Days Toronto
jQuery For Developers Stack Overflow Dev Days TorontojQuery For Developers Stack Overflow Dev Days Toronto
jQuery For Developers Stack Overflow Dev Days TorontoRalph Whitbeck
 

Was ist angesagt? (20)

Android Unit Testing With Robolectric
Android Unit Testing With RobolectricAndroid Unit Testing With Robolectric
Android Unit Testing With Robolectric
 
Groovy And Grails JUG Padova
Groovy And Grails JUG PadovaGroovy And Grails JUG Padova
Groovy And Grails JUG Padova
 
Android Code Puzzles (DroidCon Amsterdam 2012)
Android Code Puzzles (DroidCon Amsterdam 2012)Android Code Puzzles (DroidCon Amsterdam 2012)
Android Code Puzzles (DroidCon Amsterdam 2012)
 
The 2016 Android Developer Toolbox [MOBILIZATION]
The 2016 Android Developer Toolbox [MOBILIZATION]The 2016 Android Developer Toolbox [MOBILIZATION]
The 2016 Android Developer Toolbox [MOBILIZATION]
 
The Spirit of Testing
The Spirit of TestingThe Spirit of Testing
The Spirit of Testing
 
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)
 
droidparts
droidpartsdroidparts
droidparts
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear Essentials
 
jQuery Internals + Cool Stuff
jQuery Internals + Cool StuffjQuery Internals + Cool Stuff
jQuery Internals + Cool Stuff
 
Performance #6 threading
Performance #6  threadingPerformance #6  threading
Performance #6 threading
 
Naive application development
Naive application developmentNaive application development
Naive application development
 
Gdg san diego android 11 meetups what's new in android - ui and dev tools
Gdg san diego android 11 meetups  what's new in android  - ui and dev toolsGdg san diego android 11 meetups  what's new in android  - ui and dev tools
Gdg san diego android 11 meetups what's new in android - ui and dev tools
 
Androidの本当にあった怖い話
Androidの本当にあった怖い話Androidの本当にあった怖い話
Androidの本当にあった怖い話
 
Session #6 loaders and adapters
Session #6  loaders and adaptersSession #6  loaders and adapters
Session #6 loaders and adapters
 
Li How To2 10
Li How To2 10Li How To2 10
Li How To2 10
 
HTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranHTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - Altran
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suck
 
Tinkerbelles return home from their Guinness world-record attempt on Sunday
Tinkerbelles return home from their Guinness world-record attempt on SundayTinkerbelles return home from their Guinness world-record attempt on Sunday
Tinkerbelles return home from their Guinness world-record attempt on Sunday
 
JavaScript APIs you’ve never heard of (and some you have)
JavaScript APIs you’ve never heard of (and some you have)JavaScript APIs you’ve never heard of (and some you have)
JavaScript APIs you’ve never heard of (and some you have)
 
jQuery For Developers Stack Overflow Dev Days Toronto
jQuery For Developers Stack Overflow Dev Days TorontojQuery For Developers Stack Overflow Dev Days Toronto
jQuery For Developers Stack Overflow Dev Days Toronto
 

Ähnlich wie Android Code Puzzlers & Tips from DutchAUG Meetup

Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016Loïc Knuchel
 
Android Wear: A Developer's Perspective
Android Wear: A Developer's PerspectiveAndroid Wear: A Developer's Perspective
Android Wear: A Developer's PerspectiveVin Lim
 
Android and android phone
Android and android phoneAndroid and android phone
Android and android phonedaniellejoyce
 
Mobile Java with GWT: Still "Write Once, Run Everywhere"
Mobile Java with GWT: Still "Write Once, Run Everywhere"Mobile Java with GWT: Still "Write Once, Run Everywhere"
Mobile Java with GWT: Still "Write Once, Run Everywhere"Alex Theedom
 
Mobile html5 today
Mobile html5 todayMobile html5 today
Mobile html5 todayIdo Green
 
Lecture #3 activities and intents
Lecture #3  activities and intentsLecture #3  activities and intents
Lecture #3 activities and intentsVitali Pekelis
 
Building Beautiful and Interactive Metro apps with JavaScript, HTML5 & CSS3
Building Beautiful and Interactive Metro apps with JavaScript, HTML5 & CSS3Building Beautiful and Interactive Metro apps with JavaScript, HTML5 & CSS3
Building Beautiful and Interactive Metro apps with JavaScript, HTML5 & CSS3Doris Chen
 
Auf Augenhöhe mit Android Studio und Gradle
Auf Augenhöhe mit Android Studio und GradleAuf Augenhöhe mit Android Studio und Gradle
Auf Augenhöhe mit Android Studio und Gradleinovex GmbH
 
Developing Android Apps
Developing Android AppsDeveloping Android Apps
Developing Android AppsClaire Lee
 
#Code2Create:: Introduction to App Development in Flutter with Dart
#Code2Create:: Introduction to App Development in Flutter with Dart#Code2Create:: Introduction to App Development in Flutter with Dart
#Code2Create:: Introduction to App Development in Flutter with DartGDGKuwaitGoogleDevel
 
A Noob’S Guide To Android Application Development
A Noob’S Guide To Android Application DevelopmentA Noob’S Guide To Android Application Development
A Noob’S Guide To Android Application DevelopmentZi Yong Chua
 
Android Workshop
Android WorkshopAndroid Workshop
Android WorkshopJunda Ong
 

Ähnlich wie Android Code Puzzlers & Tips from DutchAUG Meetup (20)

Mini curso Android
Mini curso AndroidMini curso Android
Mini curso Android
 
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
 
Android Wear: A Developer's Perspective
Android Wear: A Developer's PerspectiveAndroid Wear: A Developer's Perspective
Android Wear: A Developer's Perspective
 
Android
AndroidAndroid
Android
 
Android and android phone
Android and android phoneAndroid and android phone
Android and android phone
 
Android Made Simple
Android Made SimpleAndroid Made Simple
Android Made Simple
 
Mobile Java with GWT: Still "Write Once, Run Everywhere"
Mobile Java with GWT: Still "Write Once, Run Everywhere"Mobile Java with GWT: Still "Write Once, Run Everywhere"
Mobile Java with GWT: Still "Write Once, Run Everywhere"
 
Appcelerator Alloy MVC
Appcelerator Alloy MVCAppcelerator Alloy MVC
Appcelerator Alloy MVC
 
Mobile html5 today
Mobile html5 todayMobile html5 today
Mobile html5 today
 
Lecture #3 activities and intents
Lecture #3  activities and intentsLecture #3  activities and intents
Lecture #3 activities and intents
 
Building Beautiful and Interactive Metro apps with JavaScript, HTML5 & CSS3
Building Beautiful and Interactive Metro apps with JavaScript, HTML5 & CSS3Building Beautiful and Interactive Metro apps with JavaScript, HTML5 & CSS3
Building Beautiful and Interactive Metro apps with JavaScript, HTML5 & CSS3
 
Auf Augenhöhe mit Android Studio und Gradle
Auf Augenhöhe mit Android Studio und GradleAuf Augenhöhe mit Android Studio und Gradle
Auf Augenhöhe mit Android Studio und Gradle
 
Android Studio und gradle
Android Studio und gradleAndroid Studio und gradle
Android Studio und gradle
 
Developing Android Apps
Developing Android AppsDeveloping Android Apps
Developing Android Apps
 
Android
AndroidAndroid
Android
 
Synapseindia android apps application
Synapseindia android apps applicationSynapseindia android apps application
Synapseindia android apps application
 
#Code2Create:: Introduction to App Development in Flutter with Dart
#Code2Create:: Introduction to App Development in Flutter with Dart#Code2Create:: Introduction to App Development in Flutter with Dart
#Code2Create:: Introduction to App Development in Flutter with Dart
 
A Noob’S Guide To Android Application Development
A Noob’S Guide To Android Application DevelopmentA Noob’S Guide To Android Application Development
A Noob’S Guide To Android Application Development
 
CDI 1.1 university
CDI 1.1 universityCDI 1.1 university
CDI 1.1 university
 
Android Workshop
Android WorkshopAndroid Workshop
Android Workshop
 

Mehr von NLJUG

The future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
The future of Web-Scale - Johan Tillema, Rene Boere & Chris QuachThe future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
The future of Web-Scale - Johan Tillema, Rene Boere & Chris QuachNLJUG
 
Speedy perception trumps speedy reception–smart asynchronous interactions - L...
Speedy perception trumps speedy reception–smart asynchronous interactions - L...Speedy perception trumps speedy reception–smart asynchronous interactions - L...
Speedy perception trumps speedy reception–smart asynchronous interactions - L...NLJUG
 
Decoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
Decoding the airspace above you with Java and $7 hardware - Bert Jan SchrijverDecoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
Decoding the airspace above you with Java and $7 hardware - Bert Jan SchrijverNLJUG
 
Using Docker to Develop, Test and Run Maven Projects - Wouter Danes
Using Docker to Develop, Test and Run Maven Projects - Wouter DanesUsing Docker to Develop, Test and Run Maven Projects - Wouter Danes
Using Docker to Develop, Test and Run Maven Projects - Wouter DanesNLJUG
 
Kill the mutants and test your tests - Roy van Rijn
Kill the mutants and test your tests - Roy van RijnKill the mutants and test your tests - Roy van Rijn
Kill the mutants and test your tests - Roy van RijnNLJUG
 
Real-time user interfaces - sosm gewoon makkelijker - Allard Buijze
Real-time user interfaces - sosm gewoon makkelijker - Allard BuijzeReal-time user interfaces - sosm gewoon makkelijker - Allard Buijze
Real-time user interfaces - sosm gewoon makkelijker - Allard BuijzeNLJUG
 
The end of traditional enterprise IT - ING's journey to the next generation I...
The end of traditional enterprise IT - ING's journey to the next generation I...The end of traditional enterprise IT - ING's journey to the next generation I...
The end of traditional enterprise IT - ING's journey to the next generation I...NLJUG
 
Performance van Java 8 en verder - Jeroen Borgers
Performance van Java 8 en verder - Jeroen BorgersPerformance van Java 8 en verder - Jeroen Borgers
Performance van Java 8 en verder - Jeroen BorgersNLJUG
 
Introduction to Reactive with Play and Akka - Markus Jura
Introduction to Reactive with Play and Akka - Markus JuraIntroduction to Reactive with Play and Akka - Markus Jura
Introduction to Reactive with Play and Akka - Markus JuraNLJUG
 
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...NLJUG
 
Workshop angular dart presentatie - Atos
Workshop angular dart presentatie - AtosWorkshop angular dart presentatie - Atos
Workshop angular dart presentatie - AtosNLJUG
 
Workshop spring boot presentatie - Atos
Workshop spring boot presentatie - AtosWorkshop spring boot presentatie - Atos
Workshop spring boot presentatie - AtosNLJUG
 
Cultivating the jenkins job jungle with groovy - Patrick van Dissel
Cultivating the jenkins job jungle with groovy - Patrick van DisselCultivating the jenkins job jungle with groovy - Patrick van Dissel
Cultivating the jenkins job jungle with groovy - Patrick van DisselNLJUG
 
Rethink your architecture - Marten Deinum
Rethink your architecture - Marten DeinumRethink your architecture - Marten Deinum
Rethink your architecture - Marten DeinumNLJUG
 
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopperEvolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopperNLJUG
 
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...NLJUG
 
Apache Wicket: 10 jaar en verder - Martijn Dashorst
Apache Wicket: 10 jaar en verder - Martijn DashorstApache Wicket: 10 jaar en verder - Martijn Dashorst
Apache Wicket: 10 jaar en verder - Martijn DashorstNLJUG
 
Opening - Bert Ertman
Opening - Bert ErtmanOpening - Bert Ertman
Opening - Bert ErtmanNLJUG
 
Returning the right results - Jettro Coenradie
Returning the right results - Jettro CoenradieReturning the right results - Jettro Coenradie
Returning the right results - Jettro CoenradieNLJUG
 
Reactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
Reactive programming met Java 8 en Java EE 7 - Martijn BlankestijnReactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
Reactive programming met Java 8 en Java EE 7 - Martijn BlankestijnNLJUG
 

Mehr von NLJUG (20)

The future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
The future of Web-Scale - Johan Tillema, Rene Boere & Chris QuachThe future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
The future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
 
Speedy perception trumps speedy reception–smart asynchronous interactions - L...
Speedy perception trumps speedy reception–smart asynchronous interactions - L...Speedy perception trumps speedy reception–smart asynchronous interactions - L...
Speedy perception trumps speedy reception–smart asynchronous interactions - L...
 
Decoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
Decoding the airspace above you with Java and $7 hardware - Bert Jan SchrijverDecoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
Decoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
 
Using Docker to Develop, Test and Run Maven Projects - Wouter Danes
Using Docker to Develop, Test and Run Maven Projects - Wouter DanesUsing Docker to Develop, Test and Run Maven Projects - Wouter Danes
Using Docker to Develop, Test and Run Maven Projects - Wouter Danes
 
Kill the mutants and test your tests - Roy van Rijn
Kill the mutants and test your tests - Roy van RijnKill the mutants and test your tests - Roy van Rijn
Kill the mutants and test your tests - Roy van Rijn
 
Real-time user interfaces - sosm gewoon makkelijker - Allard Buijze
Real-time user interfaces - sosm gewoon makkelijker - Allard BuijzeReal-time user interfaces - sosm gewoon makkelijker - Allard Buijze
Real-time user interfaces - sosm gewoon makkelijker - Allard Buijze
 
The end of traditional enterprise IT - ING's journey to the next generation I...
The end of traditional enterprise IT - ING's journey to the next generation I...The end of traditional enterprise IT - ING's journey to the next generation I...
The end of traditional enterprise IT - ING's journey to the next generation I...
 
Performance van Java 8 en verder - Jeroen Borgers
Performance van Java 8 en verder - Jeroen BorgersPerformance van Java 8 en verder - Jeroen Borgers
Performance van Java 8 en verder - Jeroen Borgers
 
Introduction to Reactive with Play and Akka - Markus Jura
Introduction to Reactive with Play and Akka - Markus JuraIntroduction to Reactive with Play and Akka - Markus Jura
Introduction to Reactive with Play and Akka - Markus Jura
 
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
 
Workshop angular dart presentatie - Atos
Workshop angular dart presentatie - AtosWorkshop angular dart presentatie - Atos
Workshop angular dart presentatie - Atos
 
Workshop spring boot presentatie - Atos
Workshop spring boot presentatie - AtosWorkshop spring boot presentatie - Atos
Workshop spring boot presentatie - Atos
 
Cultivating the jenkins job jungle with groovy - Patrick van Dissel
Cultivating the jenkins job jungle with groovy - Patrick van DisselCultivating the jenkins job jungle with groovy - Patrick van Dissel
Cultivating the jenkins job jungle with groovy - Patrick van Dissel
 
Rethink your architecture - Marten Deinum
Rethink your architecture - Marten DeinumRethink your architecture - Marten Deinum
Rethink your architecture - Marten Deinum
 
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopperEvolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
 
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
 
Apache Wicket: 10 jaar en verder - Martijn Dashorst
Apache Wicket: 10 jaar en verder - Martijn DashorstApache Wicket: 10 jaar en verder - Martijn Dashorst
Apache Wicket: 10 jaar en verder - Martijn Dashorst
 
Opening - Bert Ertman
Opening - Bert ErtmanOpening - Bert Ertman
Opening - Bert Ertman
 
Returning the right results - Jettro Coenradie
Returning the right results - Jettro CoenradieReturning the right results - Jettro Coenradie
Returning the right results - Jettro Coenradie
 
Reactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
Reactive programming met Java 8 en Java EE 7 - Martijn BlankestijnReactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
Reactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
 

Kürzlich hochgeladen

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 

Kürzlich hochgeladen (20)

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 

Android Code Puzzlers & Tips from DutchAUG Meetup

  • 1. Android Code Puzzlers +TIPS & TRICKS Can you solve all our challenges? NLJUG JFall Wednesday November 6th ! Johan Pelgrim & Hugo Visser The Dutch Android User Group http://www.dutchaug.org
  • 2. Johan Pelgrim • Android Developer! • Working at VX Company 
 @jowipe http://www.vxcompany.com! • Organizer The Dutch Android User Group! • Written Android articles and recipes for
 http://www.androidcookbook.com The Dutch Android User Group http://www.dutchaug.org
  • 3. Hugo Visser • Android Developer! • Working at Qbus
 @botteaap http://www.qbus-ict.nl! • Organizer The Dutch Android User Group! • Developer of Rainy Days 
 and Figure Running and ... The Dutch Android User Group http://www.dutchaug.org
  • 4. DutchAUG • Open Group - Dutch Focus & Spread - Free to join!! • Monthly meetups http://www.dutchaug.org ! • Started nov 2011 (at droidconNL)! • Foundation since feb 2013! • We are a Google Developer Group (GDG)! • @dutchaug #dutchaug! The Dutch Android User Group • The Dutch Android User Group http://www.dutchaug.org
  • 5. DutchAUG Wiebe Dennis Hugo Johan Elsinga! Itude Mobile Visser! Qbus The Dutch Android User Group http://www.dutchaug.org Geurts! Luminis Pelgrim! VX Company
  • 6. DutchAUG Main sponsor http://www.nspyre.nl/android The Dutch Android User Group http://www.dutchaug.org
  • 7. DutchAUG Main sponsor http://www.vxcompany.com The Dutch Android User Group http://www.dutchaug.org
  • 8. The Dutch Android User Group http://www.dutchaug.org
  • 9. DutchAUG Upcoming meetup Android 4.4 KitKat & Play Services 4 January Utrecht The Dutch Android User Group http://www.dutchaug.org
  • 10. Android Code Puzzlers Can you solve all our challenges? • • • We present a puzzle You chew on it for a while If you know the answer
 (and more importantly...why) 
 you win! The Dutch Android User Group http://www.dutchaug.org
  • 11. Everybody Ready? The Dutch Android User Group http://www.dutchaug.org
  • 12. Layout puzzle Which picture matches this layout:! <?xml version="1.0" encoding="utf-8"?>! <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"! android:layout_width="fill_parent"! android:layout_height="fill_parent" >! <TextView! android:layout_height="wrap_content"! android:layout_width="fill_parent"! android:text="Layout Puzzle 1"! android:layout_gravity="center"! android:gravity="center_vertical" />! </RelativeLayout>! ! A) B) The Dutch Android User Group C)! http://www.dutchaug.org pu zz le
  • 13. Layout puzzle Which picture matches this layout:! <?xml version="1.0" encoding="utf-8"?>! <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"! android:layout_width="fill_parent"! android:layout_height="fill_parent" >! <TextView! android:layout_height="wrap_content"! android:layout_width="fill_parent"! android:text="Layout Puzzle 1"! android:layout_gravity="center"! android:gravity="center_vertical" />! </RelativeLayout>! ! A) B) The Dutch Android User Group C)! http://www.dutchaug.org pu zz le
  • 14. You Only Frag Twice Single activity, with a single fragment! ! Activity:! protected void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! setContentView(R.layout.single_fragment);! if (savedInstanceState == null) {! getFragmentManager().beginTransaction().add(R.id.single_fragment, ! new YouOnlyFragTwiceFragment());! }! }! ! single_fragment.xml:! <?xml version="1.0" encoding="utf-8"?>! <merge>! <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"! android:id="@+id/single_fragment"! android:layout_width="fill_parent"! android:layout_height="fill_parent" />! </merge>! ! What happens when the Activity is started?! A) Fragment is shown and filling the screen! B) Activity crashes! C) Nothing is shown The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 15. You Only Frag Twice Single activity, with a single fragment! ! Activity:! protected void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! setContentView(R.layout.single_fragment);! if (savedInstanceState == null) {! getFragmentManager().beginTransaction().add(R.id.single_fragment, ! new YouOnlyFragTwiceFragment());! .commit(); }! }! ! single_fragment.xml:! <?xml version="1.0" encoding="utf-8"?>! <merge>! <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"! android:id="@+id/single_fragment"! android:layout_width="fill_parent"! android:layout_height="fill_parent" />! </merge>! ! What happens when the Activity is started?! A) Fragment is shown and filling the screen! B) Activity crashes! C) Nothing is shown C) Nothing is shown The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 16. License to click Fragment layout:! <Button android:text="Don't click me!"! android:layout_centerInParent="true"! android:onClick="clicked" />! ! In activity:! public void clicked(View v) {! Toast.makeText(this, "onClick from activity", 1).show();! }! ! ! In fragment:! public void clicked(View v) {! Toast.makeText(getActivity(), "onClick from fragment", 1).show();! }! ! What happens when A) Toast “onClick B) Toast “onClick C) First “onClick D) First “onClick I tap the button?! from activity” is shown! from fragment” is shown! from activity” then “onClick from fragment” is shown! from fragment” then “onClick from activity” is shown! The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 17. License to click Fragment layout:! <Button android:text="Don't click me!"! android:layout_centerInParent="true"! android:onClick="clicked" />! ! In activity:! public void clicked(View v) {! Toast.makeText(this, "onClick from activity", 1).show();! }! ! ! In fragment:! public void clicked(View v) {! Toast.makeText(getActivity(), "onClick from fragment", 1).show();! }! ! What happens when A) Toast “onClick B) Toast “onClick C) First “onClick D) First “onClick I tap the button?! from activity” is shown! from fragment” is shown! from activity” then “onClick from fragment” is shown! from fragment” then “onClick from activity” is shown! A) Toast “onClick from activity” is shown The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 18. A view to a kill public class GetViewActivity extends Activity {! ! ! ! ! ! ! ! ! ! ! ! ! ! }! ! @Override! protected void onCreate(Bundle savedInstanceState) {! ! super.onCreate(savedInstanceState);! ! setContentView(R.layout.view_to_a_kill);! ! ! ! getFragmentManager().beginTransaction()! ! ! .replace(R.id.content, new GetViewFragment())! ! ! .commit();! }! ! ! The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 19. A view to a kill public class GetViewFragment extends Fragment {! ! ! @Override! public void onCreate(Bundle savedInstanceState) {! ! super.onCreate(savedInstanceState);! ! ! ! ! ! ! ! ! ! ! ! ! ! }! ! ! getView().setOnClickListener(new View.OnClickListener() {! ! @Override! public void onClick(View v) {! ! ! Toast.makeText(getActivity(), "My name is droid, android", 1);! ! }! });! @Override! public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {! ! return inf.inflate(R.layout.fragment_get_view, view);! }! ! ! ! }! What happens when the Activity is started?! 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() The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 20. A view to a kill public class GetViewFragment extends Fragment {! ! ! @Override! public void onCreate(Bundle savedInstanceState) {! ! super.onCreate(savedInstanceState);! ! ! ! ! ! ! ! ! ! ! ! ! ! }! ! ! getView().setOnClickListener(new View.OnClickListener() {! ! @Override! public void onClick(View v) {! ! ! Toast.makeText(getActivity(), "My name is droid, android", 1);! ! }! });! @Override! public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {! ! return inf.inflate(R.layout.fragment_get_view, view);! }! ! ! ! }! What happens when the Activity is started?! 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() D) Exception in GetViewFragment.onCreate()! E) Exception in Fragment.onCreateView() The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 21. A view to a kill public class GetViewFragment extends Fragment {! ! ! @Override! public void onCreate(Bundle savedInstanceState) {! ! super.onCreate(savedInstanceState);! ! ! ! ! ! ! ! ! ! ! ! ! ! }! ! ! getView().setOnClickListener(new View.OnClickListener() {! ! @Override! public void onClick(View v) {! ! ! Toast.makeText(getActivity(), "My name is droid, android", 1);! ! }! });! @Override! public View onCreateView(LayoutInflater inf, ViewGroup view, Bundle saved) {! ! return inf.inflate(R.layout.fragment_get_view, view);! }! ! ! ! }! What happens when the Activity is started?! 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() D) Exception in GetViewFragment.onCreate()! E) Exception in Fragment.onCreateView() The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 22. Alpha / Beta builds The Dutch Android User Group http://www.dutchaug.org TI P
  • 23. Live And Let Die public class ToastFragment extends Fragment {! ...! public void onDestroy() {! super.onDestroy();! new ToastingAsyncTask().execute(null,null,null);! }! ! ! class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{! protected Long doInBackground(String... params) {! try {Thread.sleep(500);} catch (InterruptedException e) {}! return null;! }! 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));! } ! }! } ! what happens when I change the orientation?! A) Sysout: no_activity! B) Sysout: activity_leak! C) Sysout: null! D) Exception in getActivity ! E) Exception in getString The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 24. Live And Let Die public class ToastFragment extends Fragment {! ...! public void onDestroy() {! super.onDestroy();! new ToastingAsyncTask().execute(null,null,null);! }! ! ! class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{! protected Long doInBackground(String... params) {! try {Thread.sleep(500);} catch (InterruptedException e) {}! return null;! }! 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));! } ! }! } ! what happens when I change the orientation?! A) Sysout: no_activity! B) Sysout: activity_leak! C) Sysout: null! E) Exception in ! D) Exception in getActivity getString... E) Exception in getString The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 25. Live And Let Die public class ToastFragment extends Fragment {! LogCat: ...! public void onDestroy() {! super.onDestroy();! java.lang.IllegalStateException: new ToastingAsyncTask().execute(null,null,null);! }! Fragment ToastFragment not attached ! to Activity! class ToastingAsyncTask extends AsyncTask<String, Integer, Long>{! ! protected Long doInBackground(String... params) {! try {Thread.sleep(500);} catch (InterruptedException e) {}! return null;! }! ! protected void onPostExecute(Long result) {! Know about the life cycle of Activities, if (getActivity() == null){! System.out.println(getString(R.string.no_activity));! Fragments, Services!! }else{! ! System.out.println(getString(R.string.activity_leak));! And...! } ! }! ! } ! A Context holds your Resources!! ! “Use the source Luke!”! what happens when I change the orientation?! A) Sysout: no_activity! B) Sysout: activity_leak! C) Sysout: null! D) Exception in getActivity ! E) Exception in getString The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 26. Live And Let Die pu ! public class Fragment ...! ! public final String getString(int resId) {! return getResources().getString(resId);! }! ! final public Resources getResources() {!     if (mActivity == null) {!         throw new IllegalStateException("Fragment " + this + ! " not attached to Activity");!     }!     return mActivity.getResources();! }! ! The Dutch Android User Group http://www.dutchaug.org zz le
  • 27. From Fragment with love 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", 1).show();! return true;! } ! }! ! public class ActionbarActivity extends Activity {! ...! public boolean onOptionsItemSelected(MenuItem item) {! Toast.makeText(this, "from Activity", 1).show();! return true;! } ! }! ! When clicking an ActionBar item: ! a) Shows toast “from Activity”! b) Shows toast “from Fragment”! c) Shows both toasts! d) Shows toast depending on who created the menu item The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 28. From Fragment with love 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", 1).show();! return true;! } ! }! ! public class ActionbarActivity extends Activity {! ...! public boolean onOptionsItemSelected(MenuItem item) {! Toast.makeText(this, "from Activity", 1).show();! return true;! } ! }! ! When clicking an ActionBar item: ! a) Shows toast “from Activity”! b) Shows toast “from Fragment”! A) Shows toast “from Activity” c) Shows both toasts! d) Shows toast depending on who created the menu item The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 29. Support Library D e tip vel s & op tr men ick t
 s • Fragment / ListFragment / DialogFragment! • ViewPager! • LoaderManager / CursorLoader! • Many many compat classes! • LruCache / SparseArray! • Navigation Drawer (DrawerLayout) The Dutch Android User Group http://www.dutchaug.org
  • 30. Google Play Services • Google Maps v2! • Geofencing! • Google+ Sign-in! • Activity Recognition! • Google Cloud Messaging! • And more... The Dutch Android User Group http://www.dutchaug.org D e tip vel s & op tr men ick t
 s
  • 31. Casino Royal 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,500).execute("loves");! new WritingAsyncTask(testV,100).execute("Alice");! } ...! ! 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);! }! }! ! 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 The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 32. Casino Royal 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,500).execute("loves");! new WritingAsyncTask(testV,100).execute("Alice");! } ...! ! 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);! }! }! ! What is shown in the TextView when I start the Activity on my Galaxy Nexus: ! a) Alice loves Bob! b) Bob Alice loves! D) loves Alice! c) BobThere is not enough information to decide... d) There is not enough information to decide The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 33. Casino Royal pu zz le D) There is not enough information to decide... ! You need to know the targetSdkVersion and the device OS version of the target device! ! android:targetSdkVersion < ! 13: parallel execution! android:targetSdkVersion >= 13 ! && Device OS >= 14: serial ! ! execution! This is what we see in AsyncTask.Java:! ! public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); ! private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;! ! ! You are in control of the type of execution in SDK >= 11! ! executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,…);! ! The Dutch Android User Group http://www.dutchaug.org
  • 34. Casino Royal android:minSdkVersion=“14”! ! Go for minSdkVersion=“14” (Android 4.0 / Ice Cream Sandwich)! Second best minSdkVersion = “10” (Android 2.3.3 / Gingerbread)! E.g. Google Play Services new API’s > 10! Don’t do anything lower than 10! ! android:targetSdkVersion=“19”! ! Always set this to the latest Android API level! ! ! android:maxSdkVersion! ! Don’t use this. Everything is backwards compatible by default.! ! ! The Dutch Android User Group http://www.dutchaug.org D e tip vel s & op tr men ick t
 s
  • 35. Custom Views View:! public class MyCustomView extends LinearLayout {! public MyCustomView(Context context, AttributeSet attrs) {! super(context, attrs);! LayoutInflater.from(context).inflate(R.layout.component, this, true);! // more stuff here! }! }! ! component.xml! <?xml version="1.0" encoding="utf-8"?>! <LinearLayout ... >! <TextView android:id="@+id/label” ... />!     <EditText android:id="@+id/value” ... />! </LinearLayout>! ! layout.xml! <LinearLayout android:orientation="vertical">! <org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>! <org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>! <org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>! </LinearLayout>! ! When you inflate layout.xml in an Activity: ! a) Everything works fine! b) Exception on inflating the XML! c) Everything appears to look fine, but there are subtle bugs! d) The app crashes when entering text in the first EditText! ! Hint: How does the view tree look when the layout is inflated?! The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 36. Custom Views View:! public class MyCustomView extends LinearLayout {! public MyCustomView(Context context, AttributeSet attrs) {! super(context, attrs);! LayoutInflater.from(context).inflate(R.layout.component, this, true);! // more stuff here! }! }! ! component.xml! <?xml version="1.0" encoding="utf-8"?>! <LinearLayout ... >! <TextView android:id="@+id/label” ... />!     <EditText android:id="@+id/value” ... />! </LinearLayout>! ! layout.xml! <LinearLayout android:orientation="vertical">! <org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>! <org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>! <org.dutchaug.androidpuzzlers.customviewmess.MyCustomView/>! </LinearLayout>! ! When you inflate layout.xml in an Activity: ! a) Everything works fine! b) Exception on inflating the XML! to look fine, but there! C) Everything appears c) Everything appears to look fine, but there are subtle bugs! are crashes when entering text in the first EditText! d) The app subtle bugs ! Hint: How does the view tree look when the layout is inflated?! The Dutch Android User Group http://www.dutchaug.org pu zz le
  • 37. Custom Views pu zz le After inflate:! ! <LinearLayout>! <LinearLayout ... >! <TextView android:id="@+id/label" <EditText android:id="@+id/value" </LinearLayout>! <LinearLayout ...>! <TextView android:id="@+id/label" <EditText android:id="@+id/value" </LinearLayout>! <LinearLayout ...>! <TextView android:id="@+id/label" <EditText android:id="@+id/value" </LinearLayout>! </LinearLayout>! ... />! ... />! ... />! ... />! ... />! ... />! ! Oops:! ! 1.OnSaveInstanceState is called in LinearLayout ! 2.LinearLayout calls saveHierarchyState(SparseArray<Parcelable> state) on children! 3.Child returns Parcelable which is put in the state and keyed on the view id! 4.When state is restored, there is a single value for label, and a single value for value.! ! The Dutch Android User Group http://www.dutchaug.org
  • 38. The World Is Not Enough pu zz le @Override! protected void onStart() {! ! super.onStart();! ! ! ! ! String[] longList = new String[1000000];! ! Intent intent = new Intent(Intent.ACTION_SEND);! ! intent.setType("text/plain");! ! intent.putExtra("dutchaug", longList);! ! startActivityForResult(intent, 100);! ! }! ! ! What happens when the activity is started?! 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 Dutch Android User Group http://www.dutchaug.org
  • 39. The World Is Not Enough pu zz le @Override! protected void onStart() {! ! super.onStart();! ! ! ! ! String[] longList = new String[1000000];! ! Intent intent = new Intent(Intent.ACTION_SEND);! ! intent.setType("text/plain");! ! intent.putExtra("dutchaug", longList);! ! startActivityForResult(intent, 100);! ! }! ! ! What happens when the activity is started?! 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... D) Nothing happens, no invocation of onActivityResult
 E) System-Intent-Picker for "sent" action will be shown normally The Dutch Android User Group http://www.dutchaug.org
  • 40. The World Is Not Enough pu zz le Logcat shows:! 26-02 17:25:53.391: E/JavaBinder(6247): !!! FAILED BINDER TRANSACTION !!!! ! 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 (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.! The Dutch Android User Group http://www.dutchaug.org
  • 41. No more puzzles... But some more: The Dutch Android User Group http://www.dutchaug.org
  • 42. compound drawable D e tip vel s & op tr men ick t
 s <RelativeLayout ...>! ! ! ! ! ! <LinearLayout ...>! <ImageView! android:layout_marginRight="15dp"! android:layout_width="wrap_content"! android:layout_height="wrap_content"! android:src="@drawable/dutchaug" />! <TextView! android:layout_width="wrap_content"! android:layout_height="wrap_content"! android:text="DutchAUG" />! </LinearLayout>! <!-- this does not require a nested LinearLayout -->! <TextView! android:drawableLeft="@drawable/dutchaug"! android:drawablePadding="15dp"! android:layout_width="wrap_content"! android:layout_height="wrap_content"! android:text="DutchAUG" />! </RelativeLayout>! The Dutch Android User Group http://www.dutchaug.org DutchAUG
  • 43. Level list drawable D e tip vel s & op tr men ick t
 s • Drawables have setLevel() 0...10000! • Assign drawable level range ! Somewhere in a BaseAdapter far, far away...! ! if (error) {! Drawable d = getContext().getResources().getDrawable(R.drawable.error);! mTextView.setCompoundDrawablesWithIntrinsicBounds(d, null, null, null)! } else {! Drawable d = getContext().getResources().getDrawable(R.drawable.ok);! mTextView.setCompoundDrawablesWithIntrinsicBounds(d, null, null, null) }! The Dutch Android User Group http://www.dutchaug.org
  • 44. Level list drawable Level list drawable:! ! <level-list xmlns:android="http://schemas.android.com/apk/res/android">!   <item android:maxLevel="0" android:drawable="@drawable/ic_state_ok" />!   <item android:maxLevel="1" android:drawable="@drawable/ic_state_error" /> ! <!-- more variants... -->! </level-list>! ! BetterAdapter.java! ! // Constants please!! private static final int LEVEL_OK = 0;! private static final int LEVEL_ERROR = 1;! ! if (error) {! mTextView.getCompoundDrawables()[0].setLevel(LEVEL_ERROR)! } else {! mTextView.getCompoundDrawables()[0].setLevel(LEVEL_OK)! }! ! Or less verbose:! ! mTextView.getCompoundDrawables()[0].setLevel(error ? LEVEL_ERROR : LEVEL_OK)! ! The Dutch Android User Group http://www.dutchaug.org D e tip vel s & op tr men ick t
 s
  • 45. android.text.format.DateUtils D e tip vel s & op tr men ick t
 s • CharSequence getRelativeTimeSpanString (long time, long now, long minResolution)! • now – System.currentTimeMillis()! • minResolution – e.g. SECOND_IN_MILLIS the smallest unit of time will be seconds.! • English example: “2 seconds ago”! • Or in German: “Vor 2 Sekunden” The Dutch Android User Group http://www.dutchaug.org so
  • 46. android.text.TextUtils D e tip vel s & op tr men ick t
 s • boolean isDigitsOnly(CharSequence str)! • boolean isEmpty(CharSequence str)! • String htmlEncode(String s)! • CharSequence commaEllipsize(...)! • CharSequence ellipsize(...)
  • 47. fromHTML <string name="htmlFormattedText">! <![CDATA[! <p>Text with markup for! <strong>bold</strong>! and <em>italic</em> text.</p>! <p>There is also support for a ! <tt>monospaced</tt>font. ! But no use for the ! <code>code</code> tag!</p>! ]]>! </string> TextView view = (TextView)findViewById(R.id.sampleText);! String formattedText = getString(R.string.htmlFormattedText);! Spanned result = Html.fromHtml(formattedText);! view.setText(result); The Dutch Android User Group http://www.dutchaug.org D e tip vel s & op tr men ick t
 s
  • 48. Annotation Processors • @InjectView (Butter Knife)
 http://jakewharton.github.io/butterknife/! • @Frozen @Argument
 https://bitbucket.org/hvisser/bundles! • Android Annotations
 http://androidannotations.org The Dutch Android User Group http://www.dutchaug.org D e tip vel s & op tr men ick t
 s
  • 49. Annotation Processors public class MainActivityBefore extends Activity {! ! ! ! int mLoginCount;! String mCurrentUser;! long mSessionExpiresAt;! @Override! protected void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! setContentView(R.layout.activity_main);! if (savedInstanceState != null) {! mLoginCount = savedInstanceState.getInt("login_count");! mCurrentUser = savedInstanceState.getString("user");! mSessionExpiresAt = savedInstanceState.getLong("session_expire");! ! DemoBeforeFragment fragment = new DemoBeforeFragment();! Bundle args = new Bundle();! args.putString("greeting", "Hello!");! fragment.setArguments(args);! ! ! ! D e tip vel s & op tr men ick t
 s getFragmentManager().beginTransaction().add(R.id.main_fragment, fragment).commit();! }! }! @Override! protected void onSaveInstanceState(Bundle outState) {! super.onSaveInstanceState(outState);! outState.putInt("login_count", mLoginCount);! outState.putString("user", mCurrentUser);! // something is not quite right here...! outState.putLong("session_expre", mSessionExpiresAt);! }! }! The Dutch Android User Group http://www.dutchaug.org
  • 50. Annotation Processors D e tip vel s & op tr men ick t
 s public class DemoBeforeFragment extends Fragment {! TextView mTextView;! Button mLoginButton;! ! ! ! String mGreeting;! int mVisitCount = 0;! @Override! public void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! mGreeting = getArguments().getString("greeting");! mVisitCount = getArguments().getInt("visit_count", 0);! }! @Override! public View onCreateView(LayoutInflater inflater, ViewGroup container, ! Bundle savedInstanceState) {! View view = inflater.inflate(R.layout.activity_main, container, false);! mTextView = (TextView) view.findViewById(R.id.greeting);! mLoginButton = (Button) view.findViewById(R.id.login);! mTextView.setText(mGreeting);! return view;! }! } The Dutch Android User Group http://www.dutchaug.org
  • 51. Annotation Processors D e tip vel s & op tr men ick t
 s public class MainActivityAfter extends Activity {! ! ! ! @Frozen int mLoginCount;! @Frozen String mCurrentUser;! @Frozen long mSessionExpiresAt;! @Override! protected void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! setContentView(R.layout.activity_main);! MainActivityAfterState.restoreInstanceState(this, savedInstanceState);! if (savedInstanceState != null) {! Fragment fragment = DemoAfterFragmentBuilder.newDemoAfterFragment("Hello");! getFragmentManager().beginTransaction().add(R.id.main_fragment,! fragment).commit();! }! }! @Override! protected void onSaveInstanceState(Bundle outState) {! super.onSaveInstanceState(outState);! MainActivityAfterState.saveInstanceState(this, outState);! }! } The Dutch Android User Group http://www.dutchaug.org
  • 52. Annotation Processors D e tip vel s & op tr men ick t
 s public class DemoAfterFragment extends Fragment {! @InjectView(R.id.greeting) TextView mTextView;! @InjectView(R.id.login) Button mLoginButton;! ! ! ! ! @Argument String mGreeting;! @Argument(required=false) int mVisitCount = 0;! @Override! public void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! DemoAfterFragmentBuilder.injectArguments(this);! }! @Override! public View onCreateView(LayoutInflater inflater, ViewGroup container, ! Bundle savedInstanceState) {! View view = inflater.inflate(R.layout.activity_main, container, false);! Views.inject(this, view);! ! mTextView = (TextView) view.findViewById(R.id.greeting);! mLoginButton = (Button) view.findViewById(R.id.login);! mTextView.setText(mGreeting);! return view;! }! } The Dutch Android User Group http://www.dutchaug.org
  • 53. Proguard • Code optimalizations
 E.g. Log.d has no side effects! • Code reduction
 Unused methods / classes! • Code obfuscation (secure?)
 DexGuard does a better job! Watch Eric LaFortune on
 http://youtube.com/dutchaug The Dutch Android User Group http://www.dutchaug.org
  • 54. Use Lint • From Eclipse! • lint <project dir>! • Jenkins lint plugin The Dutch Android User Group http://www.dutchaug.org D e tip vel s & op tr men ick t
 s
  • 55. Jenkins test and deploy
 • Automate Android build,your AndroidManifest! E.g. use Jenkins build number in • “There’s a plug-in for that!” Watch Christopher Orr on
 http://youtube.com/dutchaug The Dutch Android User Group http://www.dutchaug.org
  • 56. http://bit.ly/android-puzzlers THE END Thanks for your participation! Get the puzzle code The Dutch Android User Group http://www.dutchaug.org