After reading some issue roundups on Xiaoke’s Blog, I realized I’ve encountered many of the same problems. Here’s a collected summary.

Fragment State Restoration

When a FragmentActivity is recreated, the system restores all Fragment lists from the FragmentManager and re-adds them to the activity. However, the Fragment instances are restored without their internal state – you must manually handle state restoration in onCreate or onRestoreInstanceState. The key difference is that onRestoreInstanceState is called after onStart, so choose based on timing needs.

FragmentActivity State Restoration Source

1
2
3
4
5
6
7
// Inside onCreate()
if (savedInstanceState != null) {
    Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
    // FragmentManager.restoreAllState re-adds previously saved
    // Fragments to the FragmentManager and restores the BackStack
    mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
}

FragmentActivity State Saving Source

1
2
3
4
5
6
7
8
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Parcelable p = mFragments.saveAllState();
    if (p != null) {
        outState.putParcelable(FRAGMENTS_TAG, p);
    }
}

Google recommends creating and initializing Fragments in onCreate only when savedInstanceState is null:

1
2
3
4
5
6
7
8
if (savedInstanceState == null) {
    DetailsFragment details = new DetailsFragment();
    details.setArguments(getIntent().getExtras());
    getFragmentManager()
        .beginTransaction()
        .add(android.R.id.content, details)
        .commit();
}

Related discussion: Failure Delivering Result onActivityResult

Background and Selector Require Real Drawables

On certain Samsung and Motorola devices, using pseudo-drawables defined in colors.xml results in a solid black background. You must use actual image drawables or defined shapes instead:

1
2
<color name="mail_published_time_color">#bcbcbc</color>
<drawable name="ab_bg_black">#aa191919</drawable>

Showing a Dialog in onActivityResult

When calling other apps via startActivityForResult, you may need to process results asynchronously and show a dialog. However, calling Dialog.show() directly inside onActivityResult throws an error – onActivityResult is called before onResume, and at that point the FragmentManager believes its state is already saved and refuses to commit transactions.

Similarly, you cannot commit FragmentTransaction operations after onSaveInstanceState has been called. Both issues affect DialogFragment usage.

Two correct approaches:

  • Option 1: Show the dialog in onPostResume.
  • Option 2: Set a flag (e.g., mPendingShowDialog = true) in onActivityResult, then check it in onResume. This applies not just to Dialogs but to any Fragment transaction or commit. If you must commit after onSaveInstanceState, use commitAllowingStateLoss.

ListView Empty Area Display Issue

When a ListView is set to MATCH_PARENT but has too few items to fill the space, the ListView shrinks to fit its content, leaving the empty area with the default background color. Fix this by setting the overscroll footer to transparent in your theme:

1
<item name="android:overScrollFooter">@android:color/transparent</item>

Or directly in the layout:

1
android:overScrollFooter="@android:color/transparent"

Reference: Background Color ListView - Stack Overflow

Drawable Shape Solid Fill Issue

When <solid> has no color set, the theoretical default is transparent. However, on some Samsung devices it renders as black. Always set it explicitly:

1
2
3
4
5
6
7
8
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="@android:color/transparent"/>
    <stroke
        android:width="1dp"
        android:color="@color/soft_white"/>
    <corners android:radius="1dp"/>
</shape>

WebView Word Wrap Issue

Starting from Android 4.4 (API 19), WebView does not automatically break long lines. You can try setting the layout algorithm in code:

1
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);

TEXT_AUTOSIZING heuristically boosts paragraph font sizes to improve readability in overview mode on wide-viewport layouts. However, many web pages still require handling at the HTML level:

1
<pre style="word-wrap: break-word; white-space: pre-wrap;">

Using the Dialer’s SecretCode Feature

Android’s dialer supports special Secret Codes that launch custom Intents. When a user enters *#*#CODE#*#*, the system broadcasts android.provider.Telephony.SECRET_CODE or (API 29+) android.telephony.action.SECRET_CODE.

1
2
3
4
5
6
<receiver android:name=".receiver.DiagnoserReceiver">
    <intent-filter>
        <action android:name="android.provider.Telephony.SECRET_CODE"/>
        <data android:scheme="android_secret_code" android:host="111222"/>
    </intent-filter>
</receiver>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class DiagnoserReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        if ("android.provider.Telephony.SECRET_CODE".equals(intent.getAction())) {
            Intent i = new Intent(Intent.ACTION_MAIN);
            i.setClass(context, Diagnoser.class);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(i);
        }
    }
}

More details: Create a secret doorway to your app.

Importing an Existing Git Repo Into Another

The recommended approach is Git Subtree Merge:

1
2
3
4
5
6
7
git remote add rack_remote git@github.com:schacon/rack.git
git fetch rack_remote
git merge -s ours --no-commit rack_remote/master
git read-tree --prefix=rack/ -u rack_remote/master
git commit -m "Imported rack as a subtree."
# Track upstream updates later:
git pull -s subtree rack_remote master

Git automatically recognizes the subtree root directory, so no need to specify the prefix in subsequent merges.

Reference: About Git Subtree Merges

CardView Ripple Effect (Android Lollipop)

The AppCompat support library omits the ripple effect. To see ripples, use Android 5.0+ and test on a compatible device. The official AppCompat v7 explanation:

“Why are there no ripples on pre-Lollipop? A lot of what allows RippleDrawable to run smoothly is Android 5.0’s new RenderThread. To optimize for performance on previous versions of Android, we’ve left RippleDrawable out for now.”

Use android:foreground (not background) pointing to selectableItemBackground, to avoid conflicts with CardView’s shadow and corner radius rendering.

1
2
3
4
5
6
7
8
<android.support.v7.widget.CardView 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:foreground="?android:attr/selectableItemBackground"
    android:clickable="true">
    ...
</android.support.v7.widget.CardView>

Mac OS X Cursor Movement and Text Editing Shortcuts

Reference: Apple official keyboard shortcut documentation.

Cursor movement shortcuts:

  • Control-F: Forward one character
  • Control-B: Backward one character
  • Control-P: Previous line (up)
  • Control-N: Next line (down)
  • Control-A: Move to beginning of line (Ahead)
  • Control-E: Move to end of line (End)

Text editing shortcuts:

  • Control-H: Delete character before cursor
  • Control-D: Delete character after cursor
  • Control-K: Delete from cursor to end of line
  • Control-Shift-A: Select from cursor to beginning of line
  • Control-Shift-E: Select from cursor to end of line

Switching Git Versions

Xcode bundles its own Git. If you have installed another version and want to switch to the Homebrew-managed one, use symlinks:

1
2
3
cd /Applications/Xcode.app/Contents/Developer/usr/bin
sudo mv ./git ./git-xcode-usr-bin
sudo ln -s /usr/local/bin/git ./git

References