I have a trouble with getting Activity(Nullpointerexception) after that I have rotate screen and received callback from AsyncTask to update my views of the fragment. If I wont change orientation then everything is OK(but not all the time, sometimes this bug appears)
My main activity:
public class MainActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager_layout);
fm = getSupportFragmentManager();
fm.addOnBackStackChangedListener(this);
session = new SessionManager(getApplicationContext());
if (session.isAuthorizated()) {
disableTabs();
FragmentTransaction ft = fm.beginTransaction();
if (session.termsAndConditions()) {
ft.replace(android.R.id.content, new TermsAndConditionsFragment(), "terms-and-conditions").commit();
}
}
} else {
enableTabs();
mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter.addTab(actionBar.newTab().setText("Log in"), LoginFragment.class, null);
mTabsAdapter.addTab(actionBar.newTab().setText("Calculator"), CalculatorFragment.class, null);
}
}
That`s my fragment:
public class TermsAndConditionsFragment extends SherlockFragment implements OnClickListener, OnTouchListener, OnEditorActionListener, ValueSelectedListener, AsyncUpdateViewsListener {
private static final String TAG = "TermsAndConditionsFragment";
private TermsAndConditionsManager termsAndConditionsM;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prepareData();
}
public void prepareData() {
if (getSherlockActivity() == null)
Log.d(TAG, "Activity is null");
termsAndConditionsM = new TermsAndConditionsManager(getSherlockActivity().getApplicationContext());
termsAndConditions = termsAndConditionsM.getTermsAndConditions();
...
// some stuff
...
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = init(inflater, container);
return rootView;
}
private View init(LayoutInflater inflater, ViewGroup container) {
rootView = inflater.inflate(R.layout.fragment_terms_and_conditions, container, false);
//bla bla bla
return rootView;
}
public void updateTermsAndConditionsView() {
//update views here
}
#Override
public void onClick(View v) {
ft = fm.beginTransaction();
switch (v.getId()) {
case R.id.etHowMuch:
d = NumberPaymentsPickerFragment.newInstance(getSherlockActivity(), Integer.valueOf(howMuch.replace("£", "")), 0);
d.setValueSelectedListener(this);
d.show(getFragmentManager(), Const.HOW_MUCH);
break;
}
}
#Override
public void onValueSelected() {
Bundle args = new Bundle();
...
ExecuteServerTaskBackground task = new ExecuteServerTaskBackground(getSherlockActivity());
task.setAsyncUpdateViewsListener(this);
task.action = ServerAPI.GET_TERMS_AND_CONDITIONS;
task.args = args;
task.execute();
}
#Override
public void onUpdateViews() {
prepareData();
updateTermsAndConditionsView();
}
}
My AsyncTask with callback:
public class ExecuteServerTaskBackground extends AsyncTask<Void, Void, Void> {
private static final String TAG = "ExecuteServerTaskBackground";
Activity mActivity;
Context mContext;
private AsyncUpdateViewsListener callback;
public ExecuteServerTaskBackground(Activity activity) {
this.mActivity = activity;
this.mContext = activity.getApplicationContext();
}
public void setAsyncUpdateViewsListener(AsyncUpdateViewsListener listener) {
callback = listener;
}
#Override
protected Void doInBackground(Void... params) {
ServerAPI server = new ServerAPI(mContext);
if (!args.isEmpty())
msg = server.serverRequest(action, args);
else
msg = server.serverRequest(action, null);
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
callback.onUpdateViews();
}
}
Why does it behave so? How can I get activity correctly if I change orientation.
EDIT:
As I understand correctly nullpointer appears after orientation changed and asynctask executed due to wrong reference between asyctask and Activity. Recreated activity doesnt have this reference thats why when I receive callback I use wrong activity reference which isn`t exist anymore. But how can I save current activity reference?
EDIT:
I have decided to try realize my task throughout Service and that`s what I have done.
Activity:
public class MainFragment extends Fragment implements ServiceExecutorListener, OnClickListener {
private static final String TAG = MainFragment.class.getName();
Button btnSend, btnCheck;
TextView serviceStatus;
Intent intent;
Boolean bound = false;
ServiceConnection sConn;
RESTService service;
ProgressDialog pd = new ProgressDialog();
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
intent = new Intent(getActivity(), RESTService.class);
getActivity().startService(intent);
sConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.d(TAG, "MainFragment onServiceConnected");
service = ((RESTService.MyBinder) binder).getService();
service.registerListener(MainFragment.this);
if (service.taskIsDone())
serviceStatus.setText(service.getResult());
bound = true;
}
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "MainFragment onServiceDisconnected");
bound = false;
}
};
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main_fragment, container, false);
serviceStatus = (TextView) rootView.findViewById(R.id.tvServiceStatusValue);
btnSend = (Button) rootView.findViewById(R.id.btnSend);
btnCheck = (Button) rootView.findViewById(R.id.btnCheck);
btnSend.setOnClickListener(this);
btnCheck.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSend:
pd.show(getFragmentManager(), "ProgressDialog");
service.run(7);
service.run(2);
service.run(4);
break;
case R.id.btnCheck:
if (service != null)
serviceStatus.setText(String.valueOf(service.taskIsDone()) + service.getTasksCount());
break;
}
}
#Override
public void onStart() {
super.onStart();
Log.d(TAG, "Bind service");
getActivity().bindService(intent, sConn, 0);
}
#Override
public void onPause() {
super.onDestroy();
Log.d(TAG, "onDestroy: Unbind service");
if (!bound)
return;
getActivity().unbindService(sConn);
service.unregisterListener(this);
bound = false;
}
#Override
public void onComplete(String result) {
Log.d(TAG, "Task Completed");
pd.dismiss();
serviceStatus.setText(result);
}
}
Dialog:
public class ProgressDialog extends DialogFragment implements OnClickListener {
final String TAG = ProgressDialog.class.getName();
public Dialog onCreateDialog(Bundle savedInstanceState) {
setRetainInstance(true);
AlertDialog.Builder adb = new AlertDialog.Builder(getActivity())
.setTitle("Title!")
.setPositiveButton(R.string.yes, this)
.setNegativeButton(R.string.no, this)
.setNeutralButton(R.string.maybe, this)
.setCancelable(false)
.setMessage(R.string.message_text)
.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
return true;
}
});
return adb.create();
}
public void onClick(DialogInterface dialog, int which) {
int i = 0;
switch (which) {
case Dialog.BUTTON_POSITIVE:
i = R.string.yes;
break;
case Dialog.BUTTON_NEGATIVE:
i = R.string.no;
break;
case Dialog.BUTTON_NEUTRAL:
i = R.string.maybe;
break;
}
if (i > 0)
Log.d(TAG, "Dialog 2: " + getResources().getString(i));
}
public void onDismiss(DialogInterface dialog) {
Log.d(TAG, "Dialog 2: onDismiss");
// Fix to avoid simple dialog dismiss in orientation change
if ((getDialog() != null) && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
Log.d(TAG, "Dialog 2: onCancel");
}
}
Service:
public class RESTService extends Service {
final String TAG = RESTService.class.getName();
MyBinder binder = new MyBinder();
ArrayList<ServiceExecutorListener> listeners = new ArrayList<ServiceExecutorListener>();
Handler h = new Handler();
RequestManager mRequest;
ExecutorService es;
Object obj;
int time;
StringBuilder builder;
String result = null;
public void onCreate() {
super.onCreate();
Log.d(TAG, "RESTService onCreate");
es = Executors.newFixedThreadPool(1);
obj = new Object();
builder = new StringBuilder();
}
public void run(int time) {
RunRequest rr = new RunRequest(time);
es.execute(rr);
}
class RunRequest implements Runnable {
int time;
public RunRequest(int time) {
this.time = time;
Log.d(TAG, "RunRequest create");
}
public void run() {
Log.d(TAG, "RunRequest start, time = " + time);
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Log.d(TAG, "RunRequest obj = " + obj.getClass());
} catch (NullPointerException e) {
Log.d(TAG, "RunRequest error, null pointer");
}
builder.append("result " + time + ", ");
result = builder.toString();
sendCallback();
}
}
private void sendCallback() {
h.post(new Runnable() {
#Override
public void run() {
for (ServiceExecutorListener listener : listeners)
listener.onComplete();
}
});
}
public boolean taskIsDone() {
if (result != null)
return true;
return false;
}
public String getResult() {
return result;
}
public void registerListener(ServiceExecutorListener listener) {
listeners.add(listener);
}
public void unregisterListener(ServiceExecutorListener listener) {
listeners.remove(listener);
}
public IBinder onBind(Intent intent) {
Log.d(TAG, "RESTService onBind");
return binder;
}
public boolean onUnbind(Intent intent) {
Log.d(TAG, "RESTService onUnbind");
return true;
}
public class MyBinder extends Binder {
public RESTService getService() {
return RESTService.this;
}
}
}
As you mention in your edit, the current Activity is destroyed and recreated on orientation change.
But how can I save current activity reference?
You shouldn't. The previous Activity is no longer valid. This will not only cause NPEs but also memory leaks because the AsyncTask might hold the reference to old Activity, maybe forever.
Solution is to use Loaders.
Related
I have created an ExoPlayer inside a fragment. If during the playback I press the Home button, and get back to the player, the player seems to be empty, the play/pause button does not work anymore. The video is gone. The video player view seems to be completely empty.
public class PlaybackFragment extends Fragment implements View.OnClickListener, EventListener, PlaybackControlView.VisibilityListener {
private static final String TAG = PlaybackFragment.class.getSimpleName();
Video mVideo; //Video object passed in for playback
SimpleExoPlayerView mExoPlayerView;
private TextView mVideoTitle;
private SimpleExoPlayer mExoPlayer;
private FrameLayout mFullScreenButton; //Holds the fullscreen icon
private Dialog mFullScreenDialog;
private ImageView mFullScreenIcon;
private boolean mExoPlayerFullScreen; //full-screen dialog
private static final String LOG_TAG = PlaybackFragment.class.getSimpleName();
/**
* Root ViewGroup holding the fragment
*/
private ViewGroup mPlayerViewContainer;
/**
* Context used across the class
*/
private Context mContext;
/**
* Activity to which the fragment is added
*/
private Activity mActivity;
/**
* Uri received from calling activity containing Uri to the video to be played
*/
private Uri mUri;
public PlaybackFragment() {
super();
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreate: ");
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView: ");
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_playback, container, false);
mVideoTitle = root.findViewById(R.id.playback_video_title);
mExoPlayerView = root.findViewById(R.id.exoPlayerView);
mPlayerViewContainer = (ViewGroup) mExoPlayerView.getParent();
return root;
}
/**
* Sets the Uri to video to be played
* #param mediaUri
*/
public void playUri(Uri mediaUri) {
mUri = mediaUri;
}
#Override
public void onViewStateRestored(#Nullable Bundle savedInstanceState) {
Log.d(TAG, "onViewStateRestored: ");
super.onViewStateRestored(savedInstanceState);
}
private void preparePlayback() {
mExoPlayerView.setControllerVisibilityListener(this);
mExoPlayerView.requestFocus();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(trackSelectionFactory);
mExoPlayer =
ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector);
mExoPlayerView.setPlayer(mExoPlayer);
DataSource.Factory dsFactory = new DefaultDataSourceFactory(mContext,
com.google.android.exoplayer2.util.Util.getUserAgent(mContext, mActivity.getApplicationInfo().processName), null);
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource videoSource = new ExtractorMediaSource(mUri,
dsFactory, extractorsFactory, null, null);
// Prepare the player with the source.
mExoPlayer.prepare(videoSource);
//start player
mExoPlayer.setPlayWhenReady(true);
mExoPlayer.addListener(this);
// initFullscreenDialog();
initFullscreenButton();
}
#Override
public void onVisibilityChange(int visibility) {
}
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
Log.d(TAG, "onActivityCreated: ");
super.onActivityCreated(savedInstanceState);
mContext = mActivity = getActivity();
preparePlayback();
}
#Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart: ");
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onClick(View v) {
}
public void pause() {
mExoPlayer.stop();
}
//Interface to trigger playback-finish event in the parent activity
public interface OnPlayStateListener {
void onPlayFinish();
}
OnPlayStateListener mCallback;
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if(playbackState == Player.STATE_ENDED) {
quitFullScreen(); //Leave fullscreen after playback finished
mCallback.onPlayFinish();
Log.i(LOG_TAG,"onPlayFinish() triggered");
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
mCallback = (OnPlayStateListener) context;
} catch (ClassCastException e){
throw new ClassCastException(context.toString() + " must implement OnPlayStateListener");
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
Toast.makeText(mContext,error.getLocalizedMessage(),Toast.LENGTH_SHORT).show();
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
private void goFullScreen() {
Util.showFullScreen(mActivity, mExoPlayerView);
// ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
// mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_fullscreen_exit));
mExoPlayerFullScreen = true;
// mFullScreenDialog.show();
}
private void quitFullScreen() {
Util.quitFullScreen(mActivity, mPlayerViewContainer, mExoPlayerView);
// ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
// FrameLayout frame = mActivity.findViewById(R.id.main_media_frame);
// frame.addView(mExoPlayerView);
mExoPlayerFullScreen = false;
// mFullScreenDialog.dismiss();
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_fullscreen_expand));
}
private void initFullscreenButton() {
PlaybackControlView controlView = mExoPlayerView.findViewById(R.id.exo_controller);
mFullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
mFullScreenButton = controlView.findViewById(R.id.exo_fullscreen_button);
mFullScreenButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!mExoPlayerFullScreen) {
goFullScreen();
}
else {
quitFullScreen();
}
}
});
}
private void initFullscreenDialog() {
//The following uses anonymous class to create a custom dialog
mFullScreenDialog = new Dialog(mContext, android.R.style.Theme_DeviceDefault_NoActionBar_Fullscreen) {
#Override
public void onBackPressed() {
if(mExoPlayerFullScreen) {
quitFullScreen();
}
super.onBackPressed();
}
};
}
#Override
public void onDestroy() {
super.onDestroy();
if(mExoPlayer != null) mExoPlayer.release();
Log.d(TAG, "onDestroy: ");
}
/**
* Moves forward or backward by step milliseconds <br/>
* #param step specifies step size. It is a positive or negative integer for moving forward and
* backward, respectively.
*/
public void movePlayPos(int step) {
mExoPlayer.seekTo(mExoPlayer.getCurrentPosition() + step);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
Log.d(TAG, "onSaveInstanceState: ");
super.onSaveInstanceState(outState);
outState.putLong("position", mExoPlayer.getCurrentPosition());
}
}
I have checked the fragment lifecycle in Logcat, but it seems that after I get back to the player activity, only the fragment's onStart() is called. So, there is no way to restore the state. Any ideas how I can save a video playback position upon pause and resume playback on the activity's onResume?
You can save the current position of exoplayer in onPause() and then seek to that position in onResume().
try this:
long position;
#Override
protected void onPause() {
super.onPause();
if(mExoPlayerView != null && mExoPlayerView.getPlayWhenReady()) {
position = mExoPlayerView.getCurrentPosition();
mExoPlayerView.setPlayWhenReady(false);
}
}
#Override
protected void onResume() {
super.onResume();
if(mExoPlayerView != null) {
mExoPlayerView.seekTo(position);
mExoPlayerView.setPlayWhenReady(true);
}
}
I have created simple chatting application and it contains some ListView which handles all chat messages, but every ListView is defined in another class. I want to clear my list items from Clear Chat from an overflow menu, which is present in main activity. How can I achieve this?
Here is my main activity called WiFiServiceDiscoveryActivity:
public class WiFiServiceDiscoveryActivity extends AppCompatActivity implements
DeviceClickListener, Handler.Callback, MessageTarget,
ConnectionInfoListener {
public static final String TAG = "wifidirectdemo";
// TXT RECORD properties
public static final String TXTRECORD_PROP_AVAILABLE = "available";
public static final String SERVICE_INSTANCE = " ";
public static final String SERVICE_REG_TYPE = "_presence._tcp";
public static final int MESSAGE_READ = 0x400 + 1;
public static final int MY_HANDLE = 0x400 + 2;
private WifiP2pManager manager;
static final int SERVER_PORT = 4545;
private final IntentFilter intentFilter = new IntentFilter();
private Channel channel;
private BroadcastReceiver receiver = null;
private WifiP2pDnsSdServiceRequest serviceRequest;
private Handler handler = new Handler(this);
private WiFiChatFragment chatFragment;
private WiFiDirectServicesList servicesList;
private TextView statusTxtView;
Toolbar toolbar;
private String friend;
private WiFiP2pService service;
WiFiChatFragment listView;
WiFiChatFragment.ChatMessageAdapter a;
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
toolbar=(Toolbar)findViewById(R.id.toolbar);
statusTxtView = (TextView) findViewById(R.id.status_text);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter
.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter
.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
startRegistrationAndDiscovery();
servicesList = new WiFiDirectServicesList();
getFragmentManager().beginTransaction()
.add(R.id.container_root, servicesList, "services").commit();
setSupportActionBar(toolbar);
}
#Override
protected void onRestart() {
Fragment frag = getFragmentManager().findFragmentByTag("services");
if (frag != null) {
getFragmentManager().beginTransaction().remove(frag).commit();
}
super.onRestart();
}
#Override
protected void onStop() {
if (manager != null && channel != null) {
manager.removeGroup(channel, new ActionListener() {
#Override
public void onFailure(int reasonCode) {
Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);
}
#Override
public void onSuccess() {
}
});
}
super.onStop();
}
/**
* Registers a local service and then initiates a service discovery
*/
private void startRegistrationAndDiscovery() {
Map<String, String> record = new HashMap<String, String>();
record.put(TXTRECORD_PROP_AVAILABLE, "visible");
WifiP2pDnsSdServiceInfo service = WifiP2pDnsSdServiceInfo.newInstance(
SERVICE_INSTANCE, SERVICE_REG_TYPE, record);
manager.addLocalService(channel, service, new ActionListener() {
#Override
public void onSuccess() {
//appendStatus("Added Local Service");
}
#Override
public void onFailure(int error) {
// appendStatus("Failed to add a service");
}
});
discoverService();
}
private void discoverService() {
/*
* Register listeners for DNS-SD services. These are callbacks invoked
* by the system when a service is actually discovered.
*/
manager.setDnsSdResponseListeners(channel,
new DnsSdServiceResponseListener() {
#Override
public void onDnsSdServiceAvailable(String instanceName,
String registrationType, WifiP2pDevice srcDevice) {
// A service has been discovered. Is this our app?
if (instanceName.equalsIgnoreCase(SERVICE_INSTANCE)) {
// update the UI and add the item the discovered
// device.
WiFiDirectServicesList fragment = (WiFiDirectServicesList) getFragmentManager()
.findFragmentByTag("services");
if (fragment != null) {
WiFiDevicesAdapter adapter = ((WiFiDevicesAdapter) fragment
.getListAdapter());
service = new WiFiP2pService();
service.device = srcDevice;
service.instanceName = instanceName;
service.serviceRegistrationType = registrationType;
adapter.add(service);
adapter.notifyDataSetChanged();
Log.d(TAG, "onBonjourServiceAvailable "
+ instanceName);
}
}
}
}, new DnsSdTxtRecordListener() {
/**
* A new TXT record is available. Pick up the advertised
* buddy name.
*/
#Override
public void onDnsSdTxtRecordAvailable(
String fullDomainName, Map<String, String> record,
WifiP2pDevice device) {
Log.d(TAG,
device.deviceName + " is "
+ record.get(TXTRECORD_PROP_AVAILABLE));
}
});
// After attaching listeners, create a service request and initiate
// discovery.
serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
manager.addServiceRequest(channel, serviceRequest,
new ActionListener() {
#Override
public void onSuccess() {
// appendStatus("Added service discovery request");
}
#Override
public void onFailure(int arg0) {
appendStatus("Failed adding service discovery request");
}
});
manager.discoverServices(channel, new ActionListener() {
#Override
public void onSuccess() {
//appendStatus("Service discovery initiated");
}
#Override
public void onFailure(int arg0) {
appendStatus("Service discovery failed");
}
});
}
#Override
public void connectP2p(WiFiP2pService service) {
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = service.device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
if (serviceRequest != null)
manager.removeServiceRequest(channel, serviceRequest,
new ActionListener() {
#Override
public void onSuccess() {
}
#Override
public void onFailure(int arg0) {
}
});
manager.connect(channel, config, new ActionListener() {
#Override
public void onSuccess() {
appendStatus("Connecting to service");
}
#Override
public void onFailure(int errorCode) {
appendStatus("Failed connecting to service");
}
});
}
#Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
Log.d(TAG, readMessage);
(chatFragment).pushMessage("Friend :" + readMessage);
break;
case MY_HANDLE:
Object obj = msg.obj;
(chatFragment).setChatManager((ChatManager) obj);
}
return true;
}
#Override
public void onResume() {
super.onResume();
receiver = new HomeActivity(manager, channel, this);
registerReceiver(receiver, intentFilter);
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
#Override
public void onConnectionInfoAvailable(WifiP2pInfo p2pInfo) {
Thread handler = null;
if (p2pInfo.isGroupOwner) {
Log.d(TAG, "Connected as group owner");
try {
handler = new GroupOwnerSocketHandler(
((MessageTarget) this).getHandler());
handler.start();
} catch (IOException e) {
Log.d(TAG,
"Failed to create a server thread - " + e.getMessage());
return;
}
} else {
Log.d(TAG, "Connected as peer");
handler = new ClientSocketHandler(
((MessageTarget) this).getHandler(),
p2pInfo.groupOwnerAddress);
handler.start();
}
chatFragment = new WiFiChatFragment();
getFragmentManager().beginTransaction()
.replace(R.id.container_root, chatFragment).commit();
statusTxtView.setVisibility(View.GONE);
}
public void appendStatus(String status) {
String current = statusTxtView.getText().toString();
statusTxtView.setText(current + "\n" + status);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
Toast.makeText(this, "Settings selected", Toast.LENGTH_SHORT)
.show();
break;
case R.id.clean:
Toast.makeText(this, "Clear Chat", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
return true;
}
}
And another class which has the ListView called WiFiChatFragment:
public class WiFiChatFragment extends Fragment {
private View view;
private ChatManager chatManager;
private TextView chatLine;
private ListView listView;
ChatMessageAdapter adapter = null;
private List<String> items = new ArrayList<String>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_chat, container, false);
chatLine = (TextView) view.findViewById(R.id.txtChatLine);
listView = (ListView) view.findViewById(android.R.id.list);
adapter = new ChatMessageAdapter(getActivity(), android.R.id.text1,
items);
listView.setAdapter(adapter);
view.findViewById(R.id.button1).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (chatManager != null) {
chatManager.write(chatLine.getText().toString()
.getBytes());
pushMessage("Me: " + chatLine.getText().toString());
chatLine.setText("");
chatLine.clearFocus();
}
}
});
return view;
}
public interface MessageTarget {
public Handler getHandler();
}
public void setChatManager(ChatManager obj) {
chatManager = obj;
}
public void pushMessage(String readMessage) {
adapter.add(readMessage);
adapter.notifyDataSetChanged();
}
/**
* ArrayAdapter to manage chat messages.
*/
public class ChatMessageAdapter extends ArrayAdapter<String> {
List<String> messages = null;
public ChatMessageAdapter(Context context, int textViewResourceId,
List<String> items) {
super(context, textViewResourceId, items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(android.R.layout.simple_list_item_1, null);
}
String message = items.get(position);
if (message != null && !message.isEmpty()) {
TextView nameText = (TextView) v
.findViewById(android.R.id.text1);
if (nameText != null) {
nameText.setText(message);
if (message.startsWith("Me: ")) {
nameText.setBackgroundResource(R.drawable.bubble_b );
nameText.setTextAppearance(getActivity(),
R.style.normalText);
} else {
nameText.setBackgroundResource(R.drawable.bubble_a );
nameText.setTextAppearance(getActivity(),
R.style.boldText);
}
}
}
return v;
}
}
}
Hey Adesh you could do this when the overflow item is clicked:
Call setListAdapter() again. This time with an empty ArrayList.
Hope it helps !
I am using the library barcodescanner from https://github.com/dm77/barcodescanner.
Currently the scanner displays a rectangle and a laser across the middle.
that looks similar to:
I am looking to make this view into a square since I am only scanning QR codes and to remove the laser and would appreciate some help.
My code that I have written so far for the scanner fragment is below
public class ScannerFragment extends Fragment implements
ZBarScannerView.ResultHandler
{
private static final String FLASH_STATE = "FLASH_STATE";
private static final String AUTO_FOCUS_STATE = "AUTO_FOCUS_STATE";
private static final String SELECTED_FORMATS = "SELECTED_FORMATS";
private static final String CAMERA_ID = "CAMERA_ID";
private ZBarScannerView mScannerView;
private boolean mFlash;
private boolean mAutoFocus;
private ArrayList<Integer> mSelectedIndices;
private int mCameraId = -1;
Communicator messenger;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
messenger=(Communicator) getActivity();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
mScannerView = new ZBarScannerView(getActivity());
if (state != null) {
mFlash = state.getBoolean(FLASH_STATE, false);
mAutoFocus = state.getBoolean(AUTO_FOCUS_STATE, true);
mSelectedIndices = state.getIntegerArrayList(SELECTED_FORMATS);
mCameraId = state.getInt(CAMERA_ID, -1);
} else {
mFlash = false;
mAutoFocus = true;
mSelectedIndices = null;
mCameraId = -1;
}
setupFormats();
return mScannerView;
}
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
setHasOptionsMenu(true);
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
MenuItem menuItem;
if (mFlash) {
menuItem = menu.add(Menu.NONE, R.id.menu_flash, 0, R.string.flash_on);
} else {
menuItem = menu.add(Menu.NONE, R.id.menu_flash, 0, R.string.flash_off);
}
MenuItemCompat.setShowAsAction(menuItem, MenuItem.SHOW_AS_ACTION_ALWAYS);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.menu_flash:
mFlash = !mFlash;
if (mFlash) {
item.setTitle(R.string.flash_on);
} else {
item.setTitle(R.string.flash_off);
}
mScannerView.setFlash(mFlash);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onResume() {
super.onResume();
mScannerView.setResultHandler(this);
mScannerView.startCamera();
mScannerView.setFlash(mFlash);
mScannerView.setAutoFocus(mAutoFocus);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(FLASH_STATE, mFlash);
outState.putBoolean(AUTO_FOCUS_STATE, mAutoFocus);
outState.putIntegerArrayList(SELECTED_FORMATS, mSelectedIndices);
outState.putInt(CAMERA_ID, mCameraId);
}
#Override
public void handleResult(Result rawResult) {
new Thread(new Runnable() {
#Override
public void run() {
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getActivity().getApplicationContext(), notification);
r.play();
}
catch (Exception e) {
}
}
}).start();
QRResults scanResult = QRResults.getInstance();
scanResult.Extract(rawResult.getContents());
if (scanResult.dataExtractedOK)
{
if (scanResult.canPerformElectricityComparison() || scanResult.canPerformGasComparison())
{
messenger.updateTextView("Found Code");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
Intent i = new Intent(getActivity(), SearchResult.class);
startActivity(i);
}
}, 2000);
}
}
else
{
messenger.updateTextView("Invalid Code");
// Restart Camera after 2 second delay
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
mScannerView.startCamera();
mScannerView.setFlash(mFlash);
mScannerView.setAutoFocus(mAutoFocus);
messenger.updateTextView("Finding code...");
}
}, 2000);
}
}
public void onFormatsSaved(ArrayList<Integer> selectedIndices) {
mSelectedIndices = selectedIndices;
setupFormats();
}
public void setupFormats() {
List<BarcodeFormat> formats = new ArrayList<BarcodeFormat>();
formats.add(BarcodeFormat.QRCODE);
}
#Override
public void onPause() {
super.onPause();
mScannerView.stopCamera();
}
I think I need to extend a class from the library and override some of the methods in it but I'm not sure how to do this and have the overridden methods used in my scanner class.
Thank you for your time.
Add library module in a project (not as a dependency). Here is a tutorial how to add a library module in Android Studio.
Go to library module and find in ViewFinderView.java class drawLaser(Canvas canvas) method (draws the line in the middle).
In Contacts Tab, trying to fetch list of all Facebook Friends
In Month Tab, trying to fetch list of Facebook Friends those Birthdays in Current Month
In Week Tab, trying to fetch list of Facebook Friends those Birthdays in Current Week
I have written code for all and i am not getting any error while build and run my program, but i am not getting list of friends in any of the Tab.
Please let me know, where i am doing silly mistake...where i am missing..
TabSample.Java :-
public class TabSample extends TabActivity {
String response;
private static JSONArray jsonArray;
public static TabHost mTabHost;
private MyFacebook fb = MyFacebook.getInstance();
public static MyLocalDB db = null;
private BcReceiver bcr = null;
private BcReceiverAlarm bcra = null;
private PendingIntent mAlarmSender;
private boolean isAlarmSet;
private ProgressDialog busyDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAlarmSender = PendingIntent.getService(TabSample.this, 0, new Intent(
TabSample.this, BdRemService.class), 0);
setContentView(R.layout.main);
if (db == null) {
db = new MyLocalDB(this);
db.open();
}
if (!fb.isReady()) {
Log.v(TAG, "TabSample- initiating facebook");
fb.init(this);// after finishing, this will call loadContents itself
} else {
loadContents();
}
busyDialog = new ProgressDialog(this);
busyDialog.setIndeterminate(true);
busyDialog.setMessage("Refreshing");
Bundle extras = getIntent().getExtras();
if (extras == null) {
return;
}
response = getIntent().getStringExtra("FRIENDS");
try {
jsonArray = new JSONArray(response);
} catch (JSONException e) {
FacebookUtility.displayMessageBox(this,
this.getString(R.string.json_failed));
}
setTabs();
}
private void setTabs() {
addTab("Contacts", com.chr.tatu.sample.friendslist.ContactTab.class);
addTab("Month", com.chr.tatu.sample.friendslist.MonthTab.class);
addTab("Week", com.chr.tatu.sample.friendslist.WeekTab.class);
}
private void setupTabHost() {
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabHost.setup();
}
private void setupTab(final View view, final String tag, Intent intent,
int id) {
View tabview = createTabView(mTabHost.getContext(), tag, id);
TabSpec setContent = mTabHost.newTabSpec(tag).setIndicator(tabview)
.setContent(intent);
mTabHost.addTab(setContent);
}
private void addTab(String labelId, Class<?> c) {
TabHost tabHost = getTabHost();
Intent intent = new Intent(this, c);
intent.putExtra("FRIENDS", response);
TabHost.TabSpec spec = tabHost.newTabSpec("tab" + labelId);
View tabIndicator = LayoutInflater.from(this).inflate(
R.layout.tab_indicator, getTabWidget(), false);
TextView title = (TextView) tabIndicator.findViewById(R.id.title);
title.setText(labelId);
spec.setIndicator(tabIndicator);
spec.setContent(intent);
tabHost.addTab(spec);
}
private static View createTabView(final Context context, final String text,
final int id)
{
View view = LayoutInflater.from(context).inflate(
R.layout.tab_indicator, null);
return view;
}
#Override
protected void onResume() {
if (bcr == null) {
bcr = new BcReceiver();
registerReceiver(bcr, new IntentFilter(MyUtils.BIRTHDAY_ALERT));
}
if (bcra == null) {
bcra = new BcReceiverAlarm();
registerReceiver(bcra, new IntentFilter(MyUtils.ALARM_RESET));
}
super.onResume();
}
public void loadContents() {
if (fb.getFriendsCount() > 0) {
return;
}
fb.setMyFriends(db.getAllFriends());
if (fb.getFriendsCount() > 0) {
notifyTabSample(Note.FRIENDLIST_CHANGED);
} else {
fb.reLoadAllFriends();
}
// 4. initiate alarm
if (!isAlarmSet) {
setAlarm(true);
}
}
private void setAlarm(boolean isON) {
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
if (isON) {
am.setRepeating(AlarmManager.RTC_WAKEUP, MyUtils
.getAlarmStartTimeAsLong(MyUtils.getAlarmHour(), MyUtils
.getAlarmMinute()), 24 * 60 * 60 * 1000,
mAlarmSender);
isAlarmSet = true;
Log.v(TAG, "TabSample- alarm set");
} else {
am.cancel(mAlarmSender);
isAlarmSet = true;
Log.v(TAG, "TabSample- alarm cancelled");
}
}
public void notifyTabSample(Note what) {
switch (what) {
case FRIENDLIST_RELOADED:
db.syncFriends(fb.getMyFriends());
sendBroadcast(new Intent(MyUtils.FRIENDLIST_CHANGED));
break;
case FRIENDLIST_CHANGED:
sendBroadcast(new Intent(MyUtils.FRIENDLIST_CHANGED));
// setup timer
break;
default:
break;
}
}
ContactTab.Java :-
public class ContactTab extends ListActivity {
private MyFacebook fb = MyFacebook.getInstance();
private BcReceiver bcr = null;
private MyAdapter adapter;
private List<MyFriend> list;
private ProgressDialog busyDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
busyDialog = new ProgressDialog(this);
busyDialog.setIndeterminate(true);
busyDialog.setMessage("Refreshing");
}
private void refreshList() {
new Thread() {
public void run() {
list = fb.getAllFriends();
Log.v(TAG, "contactstab- refresh called. " + list.size());
adapter = new MyAdapter(ContactTab.this, list);
handler.sendEmptyMessage(0);
}
}.start();
}
#Override
protected void onResume() {
if (bcr == null) {
bcr = new BcReceiver();
registerReceiver(bcr, new IntentFilter(MyUtils.FRIENDLIST_CHANGED));
}
refreshList();
super.onResume();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
MyFriend friend = (MyFriend) this.getListAdapter().getItem(position);
Intent intent = new Intent(ContactTab.this, PersonalGreeting.class);
intent.putExtra("fbID", friend.getFbID());
intent.putExtra("name", friend.getName());
intent.putExtra("pic", friend.getPic());
startActivity(intent);
}
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(getApplication()).inflate(R.layout.menu, menu);
return (super.onPrepareOptionsMenu(menu));
}
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
switch (item.getItemId()) {
case R.id.globalGreeting:
intent = new Intent(ContactTab.this, com.chr.tatu.sample.friendslist.GlobalGreeting.class);
startActivity(intent);
break;
case R.id.Settings:
intent = new Intent(ContactTab.this, com.chr.tatu.sample.friendslist.Settings.class);
startActivity(intent);
}
return (super.onOptionsItemSelected(item));
}
public class BcReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
runOnUiThread(new Runnable() {
public void run() {
refreshList();
}
});
}
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
setListAdapter(adapter);
//busyDialog.dismiss();
}
};
}
MonthTab.Java :-
public class MonthTab extends ListActivity {
private MyFacebook fb = MyFacebook.getInstance();
private BcReceiver bcr = null;
private MyAdapter adapter;
private List<MyFriend> list;
private ProgressDialog busyDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
busyDialog = new ProgressDialog(this);
busyDialog.setIndeterminate(true);
busyDialog.setMessage("Please wait ...");
busyDialog.show();
refreshList();
}
private void refreshList() {
// list = fb.getFilteredFriends(Filter.MONTH);
list = fb.getFilteredFriends(Filter.MONTH);
adapter = new MyAdapter(MonthTab.this, list);
setListAdapter(adapter);
busyDialog.dismiss();
}
#Override
protected void onResume() {
if (bcr == null) {
bcr = new BcReceiver();
registerReceiver(bcr, new IntentFilter(MyUtils.FRIENDLIST_CHANGED));
}
super.onResume();
}
#Override
#SuppressWarnings("unchecked")
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
MyFriend friend = (MyFriend) this.getListAdapter().getItem(position);
Intent intent = new Intent(MonthTab.this, PersonalGreeting.class);
intent.putExtra("fbID", friend.getFbID());
intent.putExtra("name", friend.getName());
startActivity(intent);
}
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(getApplication()).inflate(R.layout.menu, menu);
return (super.onPrepareOptionsMenu(menu));
}
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
switch (item.getItemId()) {
case R.id.globalGreeting:
intent = new Intent(MonthTab.this, GlobalGreeting.class);
startActivity(intent);
break;
case R.id.Settings:
intent = new Intent(MonthTab.this, Settings.class);
startActivity(intent);
}
return (super.onOptionsItemSelected(item));
}
public class BcReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
runOnUiThread(new Runnable() {
public void run() {
refreshList();
}
});
}
}
}
I have an Handler registered in an Activity. handleMessage() calls notifyDataSetChanged on an Adapter. Things work while the Activity has initial focus. However, when I navigate out of the Activity and back in, notifyDataSetChanged() does not work.
FileAdapter is an ArrayAdapter. MergeAdapter is a custom class by CommonsWare. _mergeAdapter contains _fileAdapter.
Activity code:
public void setUpDownloadHandler() {
// Define the Handler that receives messages from the thread and update the progress
_downloadHandler = new Handler() {
public void handleMessage(Message message) {
super.handleMessage(message);
String fileId = (String) message.obj;
int progress = message.arg1;
FileInfo tempFile = null;
for (FileInfo file: _files) {
if (file.getFileId().equals(fileId)) {
file.setDownloadProgress(progress);
tempFile = file;
}
}
if (tempFile != null) {
_files.remove(tempFile);
_files.add(tempFile);
}
_fileAdapter.notifyDataSetChanged();
_mergeAdapter.notifyDataSetChanged();
}
};
}
Passing the handler:
RunnableTask task = new DownloadFileRunnableImpl(application, the_workspace_url, the_file_info, the_workspace_info.getTitle(), the_internal_storage_directory,
_downloadHandler);
Background thread code:
if(temp > previous) {
Message message = new Message();
message.arg1 = _currentProgress.intValue();
message.obj = _fileId;
_progressHandler.sendMessage(message);
previous = temp;
}
The other piece of information is that I'm passing the handler through a Binder and then into the runnable. I do this to run the background thread in a Service. I don't think this is the problem.
EDIT:
It seems like the handler is not associated with the activity the second time it is navigated to (perhaps because onCreate creates a new handler). Is there a way to re-associate or retain the old handler?
Update
The activity is being destroyed when it loses focus to another activity.
I would try putting a log message in your activity's onDestroy method to see if it is getting destroyed, when you navigate away from your activity. So your task may have the handler from the old activity.
Here is my answer, I relied heavily on http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentRetainInstance.html
Really just took their code and changed it so that I have to remake the fragment everytime I want to start the thread (work) again. And it communicates with the Activity through a handler.
public class Main extends Activity implements WorkProgressListener {
private static final String TAG = "tag";
private Handler handler;
private Button startWorkBtn;
private ProgressDialog progressDialog;
private boolean onSaveInstanceFlag = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG,"Main onCreate " + Utils.getThreadId());
setContentView(R.layout.main);
handler = new ProgressHandler();
startWorkBtn = (Button)this.findViewById(R.id.start_work_btn);
startWorkBtn.setEnabled(false);
startWorkBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick (View v) {
Log.i("tag","Main: startWorkBtn onClick ");
startWorkBtn.setEnabled(false);
FragmentManager fm = getFragmentManager();
Fragment workF = (Fragment)fm.findFragmentByTag("work");
if (null == workF) {
workF = new WorkFragment();
Log.i(TAG,"Main new WorkF" + Utils.getThreadId());
startProgressDialog(true);
startWorkBtn.setEnabled(false);
fm.beginTransaction().add(workF, "work").commit();
Log.i(TAG,"Main add(workF) " + Utils.getThreadId());
}
else {
// should never be able to get here.
}
}
});
FragmentManager fm = getFragmentManager();
Fragment loadingFragment = fm.findFragmentByTag("work");
Log.i(TAG,"Main findFragment " + Utils.getThreadId());
if (null == loadingFragment) {
this.startWorkBtn.setEnabled(true);
}
else {
// could also decide to show progress dialog based on savedInstanceState
this.startProgressDialog(true);
}
} // end onCreate
#Override
public void onRestart() {
Log.i(TAG,"Main onRestart " + Utils.getThreadId() );
super.onRestart();
this.onSaveInstanceFlag = false;
}
#Override
public void onResume () {
Log.i(TAG,"Main onResume " + Utils.getThreadId());
super.onResume();
this.onSaveInstanceFlag = false;
}
#Override
public void onSaveInstanceState (Bundle savedInstanceState) {
Log.i(TAG,"Main onSaveInstanceState "+ Utils.getThreadId());
this.onSaveInstanceFlag = true;
super.onSaveInstanceState(savedInstanceState);
if (null != this.progressDialog) {
savedInstanceState.putBoolean("progressDialog", true);
}
else {
savedInstanceState.putBoolean("progressDialog", false);
}
}
#Override
public void onStop () {
Log.i(TAG,"Main onStop " + Utils.getThreadId());
super.onStop();
}
#Override
public void onDestroy () {
Log.i(TAG,"Main onDestroy " + Utils.getThreadId());
super.onDestroy();
this.closeProgressDialog();
this.handler.removeCallbacksAndMessages(null);
}
public class ProgressHandler extends Handler {
#Override
public void handleMessage (Message msg) {
Log.i(TAG,"Main ProgressDialogHandler handleMessage");
Bundle b = msg.getData();
boolean isDone = b.getBoolean("isDone");
String tag = b.getString("tag");
if (isDone && !onSaveInstanceFlag) {
FragmentManager fm = getFragmentManager();
Fragment loader = (Fragment)fm.findFragmentByTag(tag);
fm.beginTransaction().remove(loader).commit();
closeProgressDialog();
Main.this.startWorkBtn.setEnabled(true);
}
}
}
#Override
public void sendProgress(String tag, int progress, int max) {
if ( progress == max) {
Log.i(TAG,"Main sendProgress " + Utils.getThreadId());
Message message = handler.obtainMessage();
Bundle b = new Bundle();
b.putBoolean("isDone", true);
b.putString("tag",tag);
message.setData(b);
this.handler.sendMessage(message);
}
}
private void startProgressDialog(boolean show) {
this.progressDialog = new ProgressDialog(this);
this.progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
this.progressDialog.setMessage("loading");
this.progressDialog.setCancelable(false);
this.progressDialog.show();
}
private void closeProgressDialog() {
if (null != this.progressDialog) {
progressDialog.cancel();
this.progressDialog = null;
}
}
} // end Main
public class WorkFragment extends Fragment {
private static final String TAG = "tag";
private boolean mReady = false;
private boolean mQuiting = false;
private boolean done = false;
public WorkFragment () {}
final Thread mThread = new Thread() {
#Override
public void run () {
synchronized(this) {
while (!mReady) {
Log.i(TAG,"WorkF notReady"+ Utils.getThreadId());
if (mQuiting) {
return;
}
try {
wait();
} catch (InterruptedException e) {
}
}
} // end synchronized
Log.i(TAG,"WorkF starting work "+ Utils.getThreadId());
try {
Log.i(TAG,"WorkF about to sleep"+ Utils.getThreadId());
Thread.currentThread().sleep(10000l);
Log.i(TAG,"WorkF almost finished "+ Utils.getThreadId());
done = true;
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized(this) {
while (!mReady) {
Log.i(TAG,"Activity notReady"+ Utils.getThreadId());
if (mQuiting) {
return;
}
try {
wait();
} catch (InterruptedException e) {
}
}
((WorkProgressListener)getActivity()).sendProgress(WorkFragment.this.getTag(), 100, 100);
} // end synchronized 2
}
};
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.i(TAG,"WorkF, onAttach: "+ Utils.getThreadId());
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG,"WorkF, onCreate: "+ Utils.getThreadId());
setRetainInstance(true);
mThread.start();
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG,"WorkF, onActivityCreated: "+ Utils.getThreadId());
if (done) {
((WorkProgressListener)getActivity()).sendProgress(WorkFragment.this.getTag(), 100, 100);
}
synchronized (mThread) {
mReady = true;
mThread.notify();
}
}
#Override
public void onStart()
{
super.onStart();
Log.i(TAG,"WorkF, onStart: "+ Utils.getThreadId() );
}
#Override
public void onDestroy() {
synchronized (mThread) {
mReady = false;
mQuiting = true;
mThread.notify();
}
super.onDestroy();
}
#Override
public void onDetach() {
synchronized (mThread) {
mReady = false;
mThread.notify();
}
super.onDetach();
}
public void restart() {
synchronized (mThread) {
mThread.notify();
}
}
}// end WorkFragment
public interface WorkProgressListener {
public void sendProgress (String tag, int progress, int max);
}