Fragment data is lost when multiple time startActivityForResult is called - android

I have written the following code to set the String of fragment. By using startActivityForResult I am getting the value and set the to fragment string i.e (firstString, secondString)
But the problem is that whenever I call startActivityForResult the fragment is recreated and the previous data is lost. For example when I set secondString than the value of firstString is lost.
I have referred to few answers to save and restore the fragment data, but unable to do so.
boolean isEditing = true;
LinearLayout first_layout, second_layout;
TextView first_textview, second_textview;
String firstString, secondString;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_profile);
if(savedInstanceState!=null)
{
if(savedInstanceState.getBoolean("isEditing",false))
{
Log.e("onSaveInstanceState","Restored");
isEditing=true;
firstString = savedInstanceState.getString(firstString);
secondString = savedInstanceState.getString(secondString);
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.mf_postload, container, false);
// Linearlayout
first_layout = (LinearLayout) view.findViewById(R.id.payment_layout_MF_PostLoad);
second_layout = (LinearLayout) view.findViewById(R.id.remark_layout_MF_PostLoad);
// TextView
first_textview = (TextView) view.findViewById(R.id.payment_MF_PostLoad);
second_textview = (TextView) view.findViewById(R.id.remark_MF_PostLoad);
first_textview.setText(firstString);
second_textview.setText(firstString);
// Listner
first_layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity().getApplicationContext(), Remark.class);
Integer requestCode = 1;
intent.putExtra("requestCode", requestCode);
startActivityForResult(intent, requestCode);
}
});
second_layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity().getApplicationContext(), Remark.class);
Integer requestCode = 2;
intent.putExtra("requestCode", requestCode);
startActivityForResult(intent, requestCode);
}
});
return view;
}
#Override
public void onSaveInstanceState(Bundle bundle)
{
super.onSaveInstanceState(bundle);
Log.e("onSaveInstanceState","Called");
try
{
if(isEditing)
{
bundle.putBoolean("isEditing",true);
bundle.putString("firstString",firstString);
bundle.putString("secondString",secondString);
Log.e("onSaveInstanceState","Called and Saved");
}
else
{
bundle.putBoolean("isEditing",false);
Log.e("onSaveInstanceState","Called and not Saved");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
// Call Back method to get the Message form other Activity
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// First
if (requestCode == 1) {
if (resultCode == Activity.RESULT_OK && data != null) {
firstString = data.getStringExtra("remark_string");
first_textview.setText(firstString);
}
}
// Second
if (requestCode == 2) {
if (resultCode == Activity.RESULT_OK && data != null) {
secondString = data.getStringExtra("remark_string");
second_textview.setText(secondString);
}
}
}

Here is the overriding of onSaveInstance
//Like you see here am using a boolean to determine if i need to save the variable of not
//because if i am finishing the activity normally and its not the case where system kills it
//so i dont need to save these and if case that this boolean is true than the system is
//killing my activity and i need to save the values
#Override
public void onSaveInstanceState(Bundle bundle)
{
super.onSaveInstanceState(bundle);
Log.e("onSaveInstanceState","Called");
try
{
if(isEditing)
{
bundle.putBoolean("isEditing",true);
bundle.putString("photoFile", photoFile.getAbsoluteFile()+"");
bundle.putString("birthday",birthdayText.getText().toString());
bundle.putString("phone",phoneText.getText().toString());
bundle.putString("gender",genderText.getText().toString());
bundle.putString("martial",martialText.getText().toString());
bundle.putString("email",emailText.getText().toString());
bundle.putString("first",editFirstName.getText().toString());
bundle.putString("last",editLastName.getText().toString());
Log.e("onSaveInstanceState","Called and Saved");
}
else
{
bundle.putBoolean("isEditing",false);
Log.e("onSaveInstanceState","Called and not Saved");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
Here is the overriding of onCreate
//In onCreate am checking if i need to restore these values or not according
//to what i saved and in this way its like my activity never got killed
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
if(savedInstanceState!=null)
{
if(savedInstanceState.getBoolean("isEditing",false))
{
Log.e("onSaveInstanceState","Restored");
isEditing=true;
photoFile =new File(savedInstanceState.getString("photoFile"),"") ;
birthdayText.setText(savedInstanceState.getString("birthday","1/1/1980"));
phoneText.setText(savedInstanceState.getString("phone",""));
genderText.setText(savedInstanceState.getString("gender","Please specify gender"));
martialText.setText(savedInstanceState.getString("martial","Please specify marital"));
emailText.setText(savedInstanceState.getString("email",""));
editFirstName.setText(savedInstanceState.getString("first",""));
editLastName.setText(savedInstanceState.getString("last",""));
}
}
}

After some debugging I have solved, Thanks Haider.
#Override
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
Log.e("onSaveInstanceState", "Called");
bundle.putString("firstString", firstString);
bundle.putString("secondString", secondString);
Log.e("onSaveInstanceState", "Called and Saved" + firstString + " " + secondString);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("onSaveInstanceState", "Restored Called");
if (savedInstanceState != null) {
firstString = savedInstanceState.getString("firstString");
secondString = savedInstanceState.getString("secondString");
Log.e("onSaveInstanceState", "Restored" + firstString + " " + secondString);
}
}

Related

Using Spotify with PageFragment

I'm trying to hook up Spotify with my Android app. I want to be able to hit a button and have the user be able to start playing from their library on the 4th tab of the TabLayout, and have the ability to swipe back and forth from one tab to another without the music stopping. Here is my current view:
Tabbed View
When I hit start broadcast, I just have it hooked up to SpotifyActivity.java where I've logged in and it starts playing a song. However, I want to have it so that I don't have to invoke a new activity when I want to start accessing my library and playing music so that I can switch between tabs and use the rest of the functionality of the app while the music plays. I recently learned about Services in Android and I was wondering if there was a way to use that. I basically want the flow to be like this:
The 4th tab presents a "start broadcast" button. Once this is hit, you log in to Spotify (or continue if you're already logged in), and a new view (activity?) pops up that gets Spotify and a UI working. Once the music starts, I can switch back to any of the first three tabs and interact with those while the music plays, and then when I go back to the first tab the activity pops up again with the music player UI and Spotify stuff. Here is my code for PageFragment:
public class PageFragment extends Fragment {
public static final String ARG_PAGE = "ARG_PAGE";
private static User thisUser;
private int mPage;
public static PageFragment newInstance(int page, User localUser) {
Bundle args = new Bundle();
thisUser = localUser;
args.putInt(ARG_PAGE, page);
PageFragment fragment = new PageFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getInt(ARG_PAGE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = null;
TextView textView;
if (mPage == 1) {
//inflate the fragment_home_page
v = inflater.inflate(R.layout.fragment_home_page, container, false);
//handle profile and username information
}
else if (mPage == 2) {
//inflate the fragment_play_page
v = inflater.inflate(R.layout.fragment_play_page, container, false);
//handle music library information
}
else if(mPage == 3) {
//inflate the fragment_live_page
v = inflater.inflate(R.layout.fragment_live_page, container, false);
//handle live information
}
else if (mPage == 4) {
//inflate the fragment_nowplaying_page
v = inflater.inflate(R.layout.fragment_nowplaying_page, container, false);
Button startBroadcast = (Button) v.findViewById(R.id.start_broadcast);
//Links to SpotifyActivity
startBroadcast.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), SpotifyActivity.class);
startActivity(intent);
}
});
}
else {
Log.e("PageFragment ", "Unknown error occurred");
}
return v;
}
}
Here is my code for SpotifyActivity:
public class SpotifyActivity extends AppCompatActivity implements SpotifyPlayer.NotificationCallback, ConnectionStateCallback {
//CLIENT_ID=
//Callback
// Request code that will be used to verify if the result comes from correct activity
// Can be any integer
private static final int REQUEST_CODE = 1337;
private Player mPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spotify);
AuthenticationRequest.Builder builder = new AuthenticationRequest.Builder(CLIENT_ID,
AuthenticationResponse.Type.TOKEN,
REDIRECT_URI);
builder.setScopes(new String[]{"user-read-private", "streaming"});
AuthenticationRequest request = builder.build();
AuthenticationClient.openLoginActivity(this, REQUEST_CODE, request);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
//After the user logs in to authorize the application's scopes
// Check if result comes from the correct activity
if (requestCode == REQUEST_CODE) {
AuthenticationResponse response = AuthenticationClient.getResponse(resultCode, intent);
if (response.getType() == AuthenticationResponse.Type.TOKEN) {
Config playerConfig = new Config(this, response.getAccessToken(), CLIENT_ID);
Spotify.getPlayer(playerConfig, this, new SpotifyPlayer.InitializationObserver() {
#Override
public void onInitialized(SpotifyPlayer spotifyPlayer) {
mPlayer = spotifyPlayer;
mPlayer.addConnectionStateCallback(SpotifyActivity.this);
mPlayer.addNotificationCallback(SpotifyActivity.this);
}
#Override
public void onError(Throwable throwable) {
Log.e("MainActivity", "Could not initialize player: " + throwable.getMessage());
}
});
}
}
}
#Override
protected void onDestroy() {
Spotify.destroyPlayer(this);
super.onDestroy();
}
#Override
public void onPlaybackEvent(PlayerEvent playerEvent) {
Log.d("MainActivity", "Playback event received: " + playerEvent.name());
switch (playerEvent) {
// Handle event type as necessary
default:
break;
}
}
#Override
public void onPlaybackError(Error error) {
Log.d("MainActivity", "Playback error received: " + error.name());
switch (error) {
// Handle error type as necessary
default:
break;
}
}
#Override
public void onLoggedIn() {
Log.d("MainActivity", "User logged in");
mPlayer.playUri(null, "spotify:track:2TpxZ7JUBn3uw46aR7qd6V", 0, 0);
}
#Override
public void onLoggedOut() {
Log.d("MainActivity", "User logged out");
}
#Override
public void onLoginFailed(Error error) {
Log.d("MainActivity", "Login failed");
}
#Override
public void onTemporaryError() {
Log.d("MainActivity", "Temporary error occurred");
}
#Override
public void onConnectionMessage(String s) {
Log.d("MainActivity", "Received connection message: " + s);
}
}
Is there a way to set up Spotify's music player without losing it when I switch to other tabs?

ZXing double image/overlay after scan

I am using the ZXing library, fully integrated with jar files, in my Android app and have the following problem:
Problem:
After scanning a barcode, the scanned image stays on top on the live camera feed at about 50% transparency for about 1-2 seconds.
Question:
Is there any way to have just the scanned image appear at 0% transparency, instead of the strange overlay? Or, even better, can it show a custom fragment?
Thank you.
Code: [w/o unrelated parts]
public static void initiateScan(Fragment fragment) {
IntentIntegrator ii = new IntentIntegrator(fragment);
DisplayMetrics dm = fragment.getResources().getDisplayMetrics();
ii.addExtra("SCAN_WIDTH", dm.heightPixels);
ii.addExtra("SCAN_HEIGHT", dm.widthPixels / 4);
ii.addExtra("SCAN_MODE", "ONE_D_MODE");
List<String> c = new ArrayList<String>();
c.add("CODE_39");
ii.initiateScan(c, -1);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==IntentIntegrator.REQUEST_CODE) { // scan from ZXing
String raw_vin=null;
String vin = null;
boolean success=false;
IntentResult result = IntentIntegrator.parseActivityResult(requestCode,
resultCode, data);
if(result!=null)
{
String content = result.getContents();
if(content!=null)
{
raw_vin=content;
vin=raw_vin;
success=true;
}
}
}
}
Example:
Here is what I have in the build.gradle file for dependencies:
compile 'com.google.zxing:core:3.2.1'
compile 'com.journeyapps:zxing-android-embedded:3.0.3#aar'
Try this in the initiateScan method:
public static void initiateScan(Fragment fragment) {
IntentIntegrator ii = IntentIntegrator.forSupportFragment(fragment);
DisplayMetrics dm = fragment.getResources().getDisplayMetrics();
ii.addExtra("SCAN_WIDTH", dm.heightPixels);
ii.addExtra("SCAN_HEIGHT", dm.widthPixels / 4);
ii.addExtra("SCAN_MODE", "ONE_D_MODE");
ii.initiateScan(Collections.singletonList("CODE_39"));
}
Let me know how that works for you.
I am not able to explain why this problem happen, but I am using ZXing for my barcode scanner application without 50% transparent as you. The following is my solution:
Layout:
<com.journeyapps.barcodescanner.CompoundBarcodeView
android:id="#+id/barcode_scanner"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_margin="2dp">
</com.journeyapps.barcodescanner.CompoundBarcodeView>
In fragment:
private CompoundBarcodeView barcodeView;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (container == null) {
return null;
}
View v = inflater.inflate(R.layout.webservice_layout, container, false);
barcodeView = (CompoundBarcodeView) v.findViewById(R.id.barcode_scanner);
barcodeView.decodeContinuous(callback);
......
}
Callback function:
private BarcodeCallback callback = new BarcodeCallback() {
#Override
public void barcodeResult(BarcodeResult result) {
if (SOAP_ACTION.equals("") || SOAP_METHOD.equals("") || soapProperty.equals("")) {
barcodeView.pause();
} else {
if (result.getText() != null) {
barcodeView.setStatusText(result.getText());
barcodeView.pause();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
barcodeView.resume();
}
}, 1000);
}
}
}
};
Hope this help!
My approach is the following:
//start the scanning
public void startQRCodeScanning() {
IntentIntegrator integrator = IntentIntegrator.forFragment(this);
integrator.setCaptureActivity(ScanActivity);
integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES);
integrator.setBeepEnabled(false);
integrator.setOrientationLocked(true);
integrator.initiateScan();
}
//onActivityResult:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null) {
if (result.getContents() == null) {
Log.d(TAG, "Cancelled scan");
//we want to finish the current activity
//as it does not make sense to do anything else
finishActivity();
} else {
Log.d(TAG, "Scanned " + result.getContents());
setConnectionString(result.getContents());
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
//next I have the QRCodeScanningActivity
public class QRCodeScannerActivity extends Activity {
private CaptureManager capture;
private CompoundBarcodeView barcodeScannerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_scanner);
if (getResources().getBoolean(R.bool.portrait_only)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP);
}
barcodeScannerView = (CompoundBarcodeView)findViewById(R.id.zxing_barcode_scanner);
capture = new CaptureManager(this, barcodeScannerView);
capture.initializeFromIntent(getIntent(), savedInstanceState);
capture.decode();
}
#Override
protected void onResume() {
super.onResume();
capture.onResume();
}
#Override
protected void onPause() {
super.onPause();
capture.onPause();
}
#Override
protected void onDestroy() {
super.onDestroy();
capture.onDestroy();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
capture.onSaveInstanceState(outState);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return barcodeScannerView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}
//Next you need to define the layouts and everything.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black">
<com.journeyapps.barcodescanner.CompoundBarcodeView
android:id="#+id/zxing_barcode_scanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_scanner_layout="#layout/barcode_scanner_layout"/>
</FrameLayout>
</RelativeLayout>

AddView on DialogFragment after orientation change not working

I have an activity which needs to trigger 4 different DialogFragments in which i trigger an intent do get images from camera or gallery.
I can retain the fragment state and continue to observe the "onActivityResult" and send it to the dialogfragmentx but when they recreate and i try to show again the images that i got from the gallery, when i use "addView" on the linearlayout it does nothing.
Here is my code from the activity:
private DFrag_room frag_room;
private DFrag_terrace frag_terrace;
private DFrag_garden frag_garden;
private DFrag_parking frag_parking;
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (frag_room != null) {
getSupportFragmentManager().putFragment(outState, "fragment_room", frag_room);
}
if (frag_terrace != null) {
getSupportFragmentManager().putFragment(outState, "fragment_terrace", frag_terrace);
}
if (frag_garden != null) {
getSupportFragmentManager().putFragment(outState, "fragment_garden", frag_garden);
}
if (frag_parking != null) {
getSupportFragmentManager().putFragment(outState, "fragment_parking", frag_parking);
}
}
#Override
public void onRestoreInstanceState(Bundle inState){
FragmentManager fm = getSupportFragmentManager();
frag_room = (DFrag_room) fm.getFragment(inState, "fragment_room");
frag_terrace = (DFrag_terrace) fm.getFragment(inState, "fragment_terrace");
frag_garden = (DFrag_garden) fm.getFragment(inState, "fragment_garden");
frag_parking = (DFrag_parking) fm.getFragment(inState, "fragment_parking");
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (frag_room != null) {
frag_room.onActivityResult(requestCode, resultCode, data);
}
if (frag_terrace != null) {
frag_terrace.onActivityResult(requestCode, resultCode, data);
}
if (frag_garden != null) {
frag_garden.onActivityResult(requestCode, resultCode, data);
}
if (frag_parking != null) {
frag_parking.onActivityResult(requestCode, resultCode, data);
}
}
and the code from one of the dialogfragments (the procedure is the same on every one)
private LinearLayout layout_images;
private ImageView img_add_image;
private File photoFile;
private ArrayList<Uri> images;
public DFrag_room() {
}
public interface DFrag_roomListener {
void onFinishRoom();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dfrag_room, container);
layout_images = (LinearLayout) view.findViewById(R.id.dfrag_room_imgs_layout);
img_add_image = (ImageView) view.findViewById(R.id.dfrag_room_img_add_img);
img_add_image.setOnClickListener(this);
if (savedInstanceState != null) {
images = (ArrayList<Uri>) savedInstanceState.getSerializable("images");
for (int i = 0; i < images.size(); i++) {
addImage(images.get(i));
}
}
setRetainInstance(true);
return view;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); // <-- must call this if you want to retain dialogFragment upon rotation
outState.putSerializable("images", images);
}
#Override
public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
#Override
public void onActivityResult(int reqCode, int resCode, Intent data) {
switch (reqCode) {
case CONF.REQ_PHOTO:
if (resCode == Activity.RESULT_OK) {
if ((photoFile != null)) {
Uri img = Uri.fromFile(photoFile);
images.add(img);
addImage(img);
}
}
break;
case CONF.REQ_GALLERY:
if (resCode == Activity.RESULT_OK) {
images.add(data.getData());
addImage(data.getData());
}
break;
}
super.onActivityResult(resCode, resCode, data);
}
public void addImage(Uri img_uri) {
int margin = getResources().getDimensionPixelOffset(R.dimen.padding_x_small);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(img_add_image.getWidth(), img_add_image.getHeight());
params.setMargins(0, 0, margin, 0);
RoundedImageView new_img = new RoundedImageView(getActivity());
new_img.setLayoutParams(params);
new_img.setScaleType(ImageView.ScaleType.CENTER_CROP);
new_img.setBackgroundResource(R.drawable.bg_white_stroke);
new_img.setCornerRadius((float) 6);
Glide.with(getActivity()).load(img_uri).thumbnail(0.8f).into(new_img);
layout_images.addView(new_img, 0);
}
When i get the image from the intent it works fine, but when i get it from the saved list of uris (onCreateView) it doesen't work
EDIT:
Sorry, the app doesen't crash, i don't see the image in my layout, it calls "addImage" but i don't see the images.
Solved, i tried to create an imageview with 0 width and 0 height beacusa I create it from the onCreate method where img_add_image.getWidth() is 0.

How to use FB FriendPickerFragment to show you list of all your friends in order to invite them to use your app

EDIT-----: So I did manage to make it show me users and be able to select some, and to send me back the selected users to my app but there is a slight problem. "Uri.parse("picker://friend");" doesn't give me the list of my friends, but only a list of the friends that I have and have my app installed.
I followed this example: https://developers.facebook.com/docs/android/scrumptious/show-friends but I am trying to modify it, so basically I took out the selectionActivity and Fragment. So I have from my activity a button that calls the PickerActivity which contains FriendPickerFragment. I can select my friends from there, but back in my activities onActivityResult i get back "data" as null.
I have an Application class in my app, where i save the FB session, and also have the login function in there.
In my MainActivity onCreate I have this:
MyApp.getInstance().facebookLogin(PSAddFriendsActivity.this, new CrudStateCallback() {
#Override
public void onResponse(final String string) {
Log.i("", "session : session is opened? : " + MyApp.getInstance().fbSession.getAccessToken());
}
});
After having logged in, I instantiate a list with the current friends I have in my app, and the first position of this list is a FB button:
#Override
protected void onListItemClick(ListView l, View v, int position, long id){
super.onListItemClick(l, v, position, id);
if(position == 0){
startPickerActivity(PSPickerActivity.FRIEND_PICKER, 0);
}else if(position ==1){
//TODO: OPEN CONTACTS PAGE TO ADD FRIENDS
}
}
This is my onACtivityResult and the "startPickerActivity" from this class:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
Log.i("","--------------data is : " + data);
Log.i("","--------------resultCode is : " + resultCode);
Log.i("","--------------requestCode is : " + requestCode);
}
public void startPickerActivity(Uri data, int requestCode) {
Intent intent = new Intent();
intent.setData(data);
intent.setClass(PSAddFriendsActivity.this, PickerActivity.class);
startActivityForResult(intent, requestCode);
}
This is the PickerActivity, how I took it from FB:
public class PickerActivity extends FragmentActivity{
private FriendPickerFragment friendPickerFragment;
public static final Uri FRIEND_PICKER = Uri.parse("picker://friend");
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pickers);
Bundle args = getIntent().getExtras();
FragmentManager manager = getSupportFragmentManager();
Fragment fragmentToShow = null;
Uri intentUri = getIntent().getData();
if (FRIEND_PICKER.equals(intentUri)) {
if (savedInstanceState == null) {
friendPickerFragment = new FriendPickerFragment(args);
} else {
friendPickerFragment =
(FriendPickerFragment) manager.findFragmentById(R.id.picker_fragment);
}
// Set the listener to handle errors
friendPickerFragment.setOnErrorListener(new PickerFragment.OnErrorListener() {
#Override
public void onError(PickerFragment<?> fragment,
FacebookException error) {
PSPickerActivity.this.onError(error);
}
});
// Set the listener to handle button clicks
friendPickerFragment.setOnDoneButtonClickedListener(
new PickerFragment.OnDoneButtonClickedListener() {
#Override
public void onDoneButtonClicked(PickerFragment<?> fragment) {
finishActivity();
}
});
fragmentToShow = friendPickerFragment;
} else {
// Nothing to do, finish
setResult(RESULT_CANCELED);
finish();
return;
}
manager.beginTransaction()
.replace(R.id.picker_fragment, fragmentToShow)
.commit();
}
private void onError(Exception error) {
onError(error.getLocalizedMessage(), false);
}
private void onError(String error, final boolean finishActivity) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.error_dialog_title).
setMessage(error).
setPositiveButton(R.string.error_dialog_button_text,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if (finishActivity) {
finishActivity();
}
}
});
builder.show();
}
private void finishActivity() {
setResult(RESULT_OK, null);
finish();
}
#Override
protected void onStart() {
super.onStart();
if (FRIEND_PICKER.equals(getIntent().getData())) {
try {
friendPickerFragment.loadData(false);
} catch (Exception ex) {
onError(ex);
}
}
}
#Override
protected void onResume() {
Log.i("", "location test onResume");
super.onResume();
MyApp.getInstance().pref.setIsBackground(this, false);
MyApp.getInstance().startLocationClient();
}
#Override
protected void onPause() {
Log.i("", "location test onPause");
super.onPause();
MyApp.getInstance().pref.setIsBackground(this, true);
}
}
Now I looked over this fragment, do not know if I have to add something or save something from the fragment on "onDoneButtonClicked"? or what exactly, because my main activity does return null as data..
forgot to call this in the finishActivty:
if (FRIEND_PICKER.equals(getIntent().getData())) {
if (friendPickerFragment != null) {
MyApp.getInstance().setSelectedUsers(friendPickerFragment.getSelection());
}
}
Now I can get from my Application the list of selected users.
About my edit, after this i found out that with Graph2.0 you cannot get a list of your whole friendlist. You can only get back the info of friends that also liked the app. It is possible to invite friends to like an app but only if you set it as a Game from the FB developers page

The value of the variable has been suddenly set to 0

I'm doing an activity to measure how long it takes a person to do an exercise, but it has a bug that I couldn't resolve yet...
The TrainingFragment shows a list of exercises that the user can click and then my ExerciseActivity is launched and runs until the variable "remainingsSets" is setted to 0.
When I click in the first time at any exercise, everything works fine, the ExerciseActivity works correctly end return to the TrainingFragment. But then, if I try to click in another exercise, the ExerciseActivity is just closed.
In my debug, I could see that the variable "remainingSets" comes with it's right value (remainingSets = getIntent().getIntExtra("remaining_sets", 3)), but when the startButton is clicked, I don't know why the variable "remainingSets" is setted to 0 and then the activity is closed because this condition: if (remainingSets > 0){...}.
Here is my TrainingFragment:
public class TrainingFragment extends Fragment {
private final static int START_EXERCISE = 1;
private Training training;
private String lastItemClicked;
private String[] values;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Bundle bundle = getArguments();
if (bundle != null) {
training = bundle.getParcelable("training");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return (ScrollView) inflater.inflate(R.layout.template_exercises, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
LinearLayout exercisesContainer = (LinearLayout) getView().findViewById(R.id.exercises);
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
List<Exercise> exercises = training.getExercises();
values = new String[exercises.size()];
if (savedInstanceState != null) {
values = savedInstanceState.getStringArray("values");
}
for (int i = 0; i < exercises.size(); i++) {
final View exerciseView = inflater.inflate(R.layout.template_exercise, null);
exerciseView.setTag(String.valueOf(i));
TextView remainingSets = (TextView) exerciseView.findViewById(R.id.remaining_sets);
if (savedInstanceState != null) {
remainingSets.setText(values[i]);
} else {
String sets = exercises.get(i).getSets();
remainingSets.setText(sets);
values[i] = sets;
}
exerciseView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), ExerciseActivity.class);
intent.putExtra("remaining_sets",
Integer.valueOf(((TextView) v.findViewById(R.id.remaining_sets)).getText().toString()));
lastItemClicked = v.getTag().toString();
startActivityForResult(intent, START_EXERCISE);
}
});
exercisesContainer.addView(exerciseView);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putStringArray("values", values);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
View view = ((LinearLayout) getView().findViewById(R.id.exercises)).findViewWithTag(lastItemClicked);
if (requestCode == START_EXERCISE) {
if (resultCode == Activity.RESULT_OK) { // the exercise had been
// finished.
((TextView) view.findViewById(R.id.remaining_sets)).setText("0");
view.setClickable(false);
values[Integer.valueOf(lastItemClicked)] = "0";
} else if (resultCode == Activity.RESULT_CANCELED) {
String remainingSets = data.getStringExtra("remaining_sets");
((TextView) view.findViewById(R.id.remaining_sets)).setText(remainingSets);
values[Integer.valueOf(lastItemClicked)] = remainingSets;
}
}
}
}
My ExerciseActivity:
public class ExerciseActivity extends Activity {
private Chronometer chronometer;
private TextView timer;
private Button startButton;
private Button endButton;
private int remainingSets;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exercise);
ExerciseEvents.addExerciseListener(new PopupExerciseListener());
chronometer = (Chronometer) findViewById(R.id.exercise_doing_timer);
timer = (TextView) findViewById(R.id.timer);
startButton = (Button) findViewById(R.id.start_exercise);
startButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ExerciseEvents.onExerciseBegin();
}
});
endButton = (Button) findViewById(R.id.end_exercise);
endButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ExerciseEvents.onExerciseRest();
}
});
}
#Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("remaining_sets", String.valueOf(remainingSets));
setResult(RESULT_CANCELED, intent);
super.onBackPressed();
}
public class PopupExerciseListener implements ExerciseListener {
public PopupExerciseListener() {
remainingSets = getIntent().getIntExtra("remaining_sets", 3);
}
#Override
public void onExerciseBegin() {
if (remainingSets > 0) {
chronometer.setVisibility(View.VISIBLE);
timer.setVisibility(View.GONE);
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();
startButton.setVisibility(View.GONE);
endButton.setVisibility(View.VISIBLE);
} else {
ExerciseEvents.onExerciseFinish();
}
}
#Override
public void onExerciseFinish() {
setResult(RESULT_OK);
finish();
}
#Override
public void onExerciseRest() {
chronometer.setVisibility(View.GONE);
endButton.setVisibility(View.GONE);
timer.setVisibility(View.VISIBLE);
long restTime = getIntent().getLongExtra("time_to_rest", 60) * 1000;
new CountDownTimer(restTime, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timer.setText(String.valueOf(millisUntilFinished / 1000));
}
#Override
public void onFinish() {
ExerciseEvents.onExerciseBegin();
}
}.start();
remainingSets--;
}
}
}
And my ExerciseEvents:
public class ExerciseEvents {
private static LinkedList<ExerciseListener> mExerciseListeners = new LinkedList<ExerciseListener>();
public static void addExerciseListener(ExerciseListener listener) {
mExerciseListeners.add(listener);
}
public static void removeExerciseListener(String listener) {
mExerciseListeners.remove(listener);
}
public static void onExerciseBegin() {
for (ExerciseListener l : mExerciseListeners) {
l.onExerciseBegin();
}
}
public static void onExerciseRest() {
for (ExerciseListener l : mExerciseListeners) {
l.onExerciseRest();
}
}
public static void onExerciseFinish() {
for (ExerciseListener l : mExerciseListeners) {
l.onExerciseFinish();
}
}
public static interface ExerciseListener {
public void onExerciseBegin();
public void onExerciseRest();
public void onExerciseFinish();
}
}
Could anyone give me any help?
After you updated your code, I see you have a big memory leak in your code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exercise);
ExerciseEvents.addExerciseListener(new PopupExerciseListener());
....
}
The call ExerciseEvents.addExerciseListener(new PopupExerciseListener()) adds a new PopupExerciseListener to a static/global list: ExcerciseEvents.mExerciseListeners. Since the class PopupExerciseListener is an inner-class, it implicitly holds a reference to its enclosing ExcerciseActivity. This mean your code is holding on to each instance of ExcerciseActivity forever. Not good.
This may also explain the weird behavior you see. When one of the onExcersizeXXX() methods is called, it will call all ExcerciseListeners in the linked-list, the ones from previous screens and the current one.
Try this in your ExcerciseActivity.java:
....
ExerciseListener mExerciseListener;
....
#Override
protected void onCreate(Bundle savedInstanceState) {
....
....
mExerciseListener = new PopupExerciseListener()
ExerciseEvents.addExerciseListener(mExerciseListener);
....
....
}
#Override
protected void onDestroy() {
ExerciseEvents.removeExerciseListener(mExerciseListener);
super.onDestroy();
}
....
In onDestroy, you deregister your listener, preventing a memory leak and preventing odd multiple callbacks to PopupExerciseListeners that are attached to activities that no longer exist.

Categories

Resources