package android.support.v4.app;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import com.actionbarsherlock.ActionBarSherlock;
import com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener;
import com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener;
import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener;
import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener;
import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
public class FragmentActivity extends Activity
implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener {
private static final String TAG = "FragmentActivity";
private static final String FRAGMENTS_TAG = "android:support:fragments";
private static final int HONEYCOMB = 11;
static final int MSG_REALLY_STOPPED = 1;
static final int MSG_RESUME_PENDING = 2;
final Handler mHandler = new Handler() {
@Override
switch (msg.what) {
case MSG_REALLY_STOPPED:
if (mStopped) {
doReallyStop(false);
}
break;
case MSG_RESUME_PENDING:
mFragments.dispatchResume();
mFragments.execPendingActions();
break;
default:
super.handleMessage(msg);
}
}
};
final FragmentManagerImpl mFragments = new FragmentManagerImpl();
boolean mCreated;
boolean mResumed;
boolean mStopped;
boolean mReallyStopped;
boolean mRetaining;
boolean mCheckedForLoaderManager;
boolean mLoadersStarted;
HCSparseArray<LoaderManagerImpl> mAllLoaderManagers;
LoaderManagerImpl mLoaderManager;
final ActionBarSherlock mSherlock = ActionBarSherlock.asDelegateFor(this);
Object activity;
Object custom;
HashMap<String, Object> children;
ArrayList<Fragment> fragments;
HCSparseArray<LoaderManagerImpl> loaders;
}
public static final int[] Fragment = {
0x01010003, 0x010100d0, 0x010100d1
};
public static final int Fragment_id = 1;
public static final int Fragment_name = 0;
public static final int Fragment_tag = 2;
}
return mSherlock.getActionBar();
}
return mSherlock.startActionMode(callback);
}
@Override
}
@Override
}
public MenuInflater () {
return mSherlock.getMenuInflater();
}
@Override
return true;
}
@Override
public boolean (int featureId, Menu menu) {
if (featureId == Window.FEATURE_OPTIONS_PANEL) {
boolean show = onCreateOptionsMenu(menu);
show |= mFragments.dispatchCreateOptionsMenu(menu, getSupportMenuInflater());
return show;
}
return false;
}
public boolean (Menu menu) {
return true;
}
@Override
return mSherlock.dispatchPrepareOptionsMenu(menu);
}
@Override
public boolean (int featureId, View view, Menu menu) {
if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
boolean goforit = onPrepareOptionsMenu(menu);
goforit |= mFragments.dispatchPrepareOptionsMenu(menu);
return goforit && menu.hasVisibleItems();
}
return true;
}
public boolean (Menu menu) {
return true;
}
@Override
throw new RuntimeException("This should never be called. Create reproducible test case and report!");
}
@Override
public boolean (int featureId, MenuItem item) {
switch (featureId) {
case Window.FEATURE_OPTIONS_PANEL:
if (onOptionsItemSelected(item)) {
return true;
}
return mFragments.dispatchOptionsItemSelected(item);
default:
return false;
}
}
public boolean (MenuItem item) {
return false;
}
public void () {
mSherlock.dispatchInvalidateOptionsMenu();
}
@Override
public void () {
if (!mSherlock.dispatchOpenOptionsMenu()) {
super.openOptionsMenu();
}
}
@Override
public void () {
if (!mSherlock.dispatchCloseOptionsMenu()) {
super.closeOptionsMenu();
}
}
@Override
mSherlock.addContentView(view, params);
}
@Override
mSherlock.setContentView(layoutResId);
}
@Override
mSherlock.setContentView(view, params);
}
@Override
mSherlock.setContentView(view);
}
@Override
mSherlock.dispatchTitleChanged(title, color);
super.onTitleChanged(title, color);
}
@Override
public final boolean onMenuOpened(
int featureId, android.view.Menu menu) {
if (mSherlock.dispatchMenuOpened(featureId, menu)) {
return true;
}
return super.onMenuOpened(featureId, menu);
}
@Override
public void onPanelClosed(
int featureId, android.view.Menu menu) {
mSherlock.dispatchPanelClosed(featureId, menu);
super.onPanelClosed(featureId, menu);
}
@Override
public boolean onKeyUp(
int keyCode, KeyEvent event) {
if (mSherlock.dispatchKeyUp(keyCode, event)) {
return true;
}
return super.onKeyUp(keyCode, event);
}
mSherlock.requestFeature((int)featureId);
}
mSherlock.setProgress(progress);
}
mSherlock.setProgressBarIndeterminate(indeterminate);
}
mSherlock.setProgressBarIndeterminateVisibility(visible);
}
mSherlock.setProgressBarVisibility(visible);
}
mSherlock.setSecondaryProgress(secondaryProgress);
}
@Override
int index = requestCode>>16;
if (index != 0) {
index--;
if (mFragments.mActive == null || index < 0 || index >= mFragments.mActive.size()) {
Log.w(TAG, "Activity result fragment index out of range: 0x"
+ Integer.toHexString(requestCode));
return;
}
Fragment frag = mFragments.mActive.get(index);
if (frag == null) {
Log.w(TAG, "Activity result no fragment exists for index: 0x"
+ Integer.toHexString(requestCode));
}
frag.onActivityResult(requestCode&0xffff, resultCode, data);
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
if (!mFragments.popBackStackImmediate()) {
finish();
}
}
@Override
super.onConfigurationChanged(newConfig);
mSherlock.dispatchConfigurationChanged(newConfig);
mFragments.dispatchConfigurationChanged(newConfig);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
mFragments.attachActivity(this);
if (getLayoutInflater().getFactory() == null) {
getLayoutInflater().setFactory(this);
}
super.onCreate(savedInstanceState);
NonConfigurationInstances nc = (NonConfigurationInstances)
getLastNonConfigurationInstance();
if (nc != null) {
mAllLoaderManagers = nc.loaders;
}
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
}
mFragments.dispatchCreate();
}
@Override
public View
onCreateView(String name, Context context, AttributeSet attrs) {
if (!"fragment".equals(name)) {
return super.onCreateView(name, context, attrs);
}
String fname = attrs.getAttributeValue(null, "class");
TypedArray a = context.obtainStyledAttributes(attrs, FragmentTag.Fragment);
if (fname == null) {
fname = a.getString(FragmentTag.Fragment_name);
}
int id = a.getResourceId(FragmentTag.Fragment_id, View.NO_ID);
String tag = a.getString(FragmentTag.Fragment_tag);
a.recycle();
View parent = null;
int containerId = parent != null ? parent.getId() : 0;
if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
throw new IllegalArgumentException(attrs.getPositionDescription()
+ ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);
}
Fragment fragment = id != View.NO_ID ? mFragments.findFragmentById(id) : null;
if (fragment == null && tag != null) {
fragment = mFragments.findFragmentByTag(tag);
}
if (fragment == null && containerId != View.NO_ID) {
fragment = mFragments.findFragmentById(containerId);
}
if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
+ Integer.toHexString(id) + " fname=" + fname
+ " existing=" + fragment);
if (fragment == null) {
fragment = Fragment.instantiate(this, fname);
fragment.mFromLayout = true;
fragment.mFragmentId = id != 0 ? id : containerId;
fragment.mContainerId = containerId;
fragment.mTag = tag;
fragment.mInLayout = true;
fragment.mFragmentManager = mFragments;
fragment.onInflate(this, attrs, fragment.mSavedFragmentState);
mFragments.addFragment(fragment, true);
} else if (fragment.mInLayout) {
throw new IllegalArgumentException(attrs.getPositionDescription()
+ ": Duplicate id 0x" + Integer.toHexString(id)
+ ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
+ " with another fragment for " + fname);
} else {
fragment.mInLayout = true;
if (!fragment.mRetaining) {
fragment.onInflate(this, attrs, fragment.mSavedFragmentState);
}
mFragments.moveToState(fragment);
}
if (fragment.mView == null) {
throw new IllegalStateException("Fragment " + fname
+ " did not create a view.");
}
if (id != 0) {
fragment.mView.setId(id);
}
if (fragment.mView.getTag() == null) {
fragment.mView.setTag(tag);
}
return fragment.mView;
}
@Override
super.onDestroy();
doReallyStop(false);
mFragments.dispatchDestroy();
if (mLoaderManager != null) {
mLoaderManager.doDestroy();
}
}
@Override
public boolean onKeyDown(
int keyCode, KeyEvent event) {
if (android.os.Build.VERSION.SDK_INT < 5
&& keyCode == KeyEvent.KEYCODE_BACK
&& event.getRepeatCount() == 0) {
onBackPressed();
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
super.onLowMemory();
mFragments.dispatchLowMemory();
}
@Override
if (super.onMenuItemSelected(featureId, item)) {
return true;
}
switch (featureId) {
case Window.FEATURE_CONTEXT_MENU:
return mFragments.dispatchContextItemSelected(item);
default:
return false;
}
}
@Override
mSherlock.dispatchPause();
super.onPause();
mResumed = false;
if (mHandler.hasMessages(MSG_RESUME_PENDING)) {
mHandler.removeMessages(MSG_RESUME_PENDING);
mFragments.dispatchResume();
}
mFragments.dispatchPause();
}
@Override
super.onResume();
mHandler.sendEmptyMessage(MSG_RESUME_PENDING);
mResumed = true;
mFragments.execPendingActions();
}
@Override
super.onPostResume();
mSherlock.dispatchPostResume();
mHandler.removeMessages(MSG_RESUME_PENDING);
mFragments.dispatchResume();
mFragments.execPendingActions();
}
@Override
if (mStopped) {
doReallyStop(true);
}
Object custom = onRetainCustomNonConfigurationInstance();
ArrayList<Fragment> fragments = mFragments.retainNonConfig();
boolean retainLoaders = false;
if (mAllLoaderManagers != null) {
for (int i=mAllLoaderManagers.size()-1; i>=0; i--) {
LoaderManagerImpl lm = mAllLoaderManagers.valueAt(i);
if (lm.mRetaining) {
retainLoaders = true;
} else {
lm.doDestroy();
mAllLoaderManagers.removeAt(i);
}
}
}
if (fragments == null && !retainLoaders && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = null;
nci.custom = custom;
nci.children = null;
nci.fragments = fragments;
nci.loaders = mAllLoaderManagers;
return nci;
}
@Override
super.onSaveInstanceState(outState);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
}
@Override
super.onStart();
mStopped = false;
mReallyStopped = false;
mHandler.removeMessages(MSG_REALLY_STOPPED);
if (!mCreated) {
mCreated = true;
mFragments.dispatchActivityCreated();
}
mFragments.noteStateNotSaved();
mFragments.execPendingActions();
if (!mLoadersStarted) {
mLoadersStarted = true;
if (mLoaderManager != null) {
mLoaderManager.doStart();
} else if (!mCheckedForLoaderManager) {
mLoaderManager = getLoaderManager(-1, mLoadersStarted, false);
}
mCheckedForLoaderManager = true;
}
mFragments.dispatchStart();
if (mAllLoaderManagers != null) {
for (int i=mAllLoaderManagers.size()-1; i>=0; i--) {
LoaderManagerImpl lm = mAllLoaderManagers.valueAt(i);
lm.finishRetain();
lm.doReportStart();
}
}
}
@Override
mSherlock.dispatchStop();
super.onStop();
mStopped = true;
mHandler.sendEmptyMessage(MSG_REALLY_STOPPED);
mFragments.dispatchStop();
}
return null;
}
NonConfigurationInstances nc = (NonConfigurationInstances)
getLastNonConfigurationInstance();
return nc != null ? nc.custom : null;
}
void () {
invalidateOptionsMenu();
}
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
if (android.os.Build.VERSION.SDK_INT >= HONEYCOMB) {
}
writer.print(prefix); writer.print("Local FragmentActivity ");
writer.print(Integer.toHexString(System.identityHashCode(this)));
writer.println(" State:");
String innerPrefix = prefix + " ";
writer.print(innerPrefix); writer.print("mCreated=");
writer.print(mCreated); writer.print("mResumed=");
writer.print(mResumed); writer.print(" mStopped=");
writer.print(mStopped); writer.print(" mReallyStopped=");
writer.println(mReallyStopped);
writer.print(innerPrefix); writer.print("mLoadersStarted=");
writer.println(mLoadersStarted);
if (mLoaderManager != null) {
writer.print(prefix); writer.print("Loader Manager ");
writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
writer.println(":");
mLoaderManager.dump(prefix + " ", fd, writer, args);
}
mFragments.dump(prefix, fd, writer, args);
}
if (!mReallyStopped) {
mReallyStopped = true;
mRetaining = retaining;
mHandler.removeMessages(MSG_REALLY_STOPPED);
onReallyStop();
}
}
if (mLoadersStarted) {
mLoadersStarted = false;
if (mLoaderManager != null) {
if (!mRetaining) {
mLoaderManager.doStop();
} else {
mLoaderManager.doRetain();
}
}
}
mFragments.dispatchReallyStop();
}
}
return mFragments;
}
@Override
if (requestCode != -1 && (requestCode&0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
}
super.startActivityForResult(intent, requestCode);
}
int requestCode) {
if (requestCode == -1) {
super.startActivityForResult(intent, -1);
return;
}
if ((requestCode&0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
}
super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff));
}
if (mAllLoaderManagers != null) {
LoaderManagerImpl lm = mAllLoaderManagers.get(index);
if (lm != null && !lm.mRetaining) {
lm.doDestroy();
mAllLoaderManagers.remove(index);
}
}
}
if (mLoaderManager != null) {
return mLoaderManager;
}
mCheckedForLoaderManager = true;
mLoaderManager = getLoaderManager(-1, mLoadersStarted, true);
return mLoaderManager;
}
LoaderManagerImpl
getLoaderManager(
int index,
boolean started,
boolean create) {
if (mAllLoaderManagers == null) {
mAllLoaderManagers = new HCSparseArray<LoaderManagerImpl>();
}
LoaderManagerImpl lm = mAllLoaderManagers.get(index);
if (lm == null) {
if (create) {
lm = new LoaderManagerImpl(this, started);
mAllLoaderManagers.put(index, lm);
}
} else {
lm.updateActivity(this);
}
return lm;
}
}