I have a Fragment which contains a Progressbar. I retrieve it in onCreateView() method where setVisibility() works fine.
Now, when I try to set visibility of the same progressbar (declared in fragment at class level) inside onActivityResult() nothing happens. Here is the code.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == REQUEST_CODE_PROFILE_VIDEO_PATH){
if(resultCode == Activity.RESULT_OK) {
String profileVideoPath = data.getExtras().getString(ProfileVideoRecordingActivity.VIDEO_PROFILE_PATH);
Log.d("DEBUG", profileVideoPath);
//Upload to server
File profileVideo = new File(profileVideoPath);
if(profileVideo.exists()) {
pbarVideoUpload.setVisibility(View.VISIBLE);
FireBaseWrapper fileUploader = new FireBaseWrapper();
String serverFolderPath = "videoprofile";
String contentType = "video/mp4";
FireBaseAfterUpload afterUpload = new FireBaseAfterUpload() {
#Override
public void onSuccess(String uploadURL) {
Log.d("DEBUG", "Successfully uploaded video to server");
Log.d("DEBUG", uploadURL);
pbarVideoUpload.setVisibility(View.GONE);
ProfileService profileService = new ProfileService(TAG) {
#Override
protected void onPreServiceCall() {
}
#Override
protected void onPostServiceCall() {
}
#Override
public void afterSuccess(Object object) {
ReturnCode successCode = (ReturnCode) object;
if(successCode.getSuccess()){
Log.d("DEBUG", "Profile Video URL updated in DB");
}else{
Log.d("DEBUG", "Profile Video URL NOT updated in DB");
}
}
#Override
public void afterError() {
Log.d("DEBUG", "Profile Video URL NOT updated in DB");
}
};
profileService.updateVideoPath(uploadURL);
}
#Override
public void onProgress(String data) {
}
#Override
public void onFaliure() {
Log.d("DEBUG", "Error! Didn't upload");
pbarVideoUpload.setVisibility(View.GONE);
}
};
try {
fileUploader.upload(profileVideo, profileVideo.getName(), serverFolderPath, afterUpload, contentType, false);
}catch (FileNotFoundException e){
Log.e("DEBUG", "FileNotFoundException", e);
}
}
}
}
}
I tried calling setVisibility() inside an Handler and also on UI thread using runOnUiThread(). Both approaches didn't work.
How can I control visibility of progressbar inside onActivityResult() of Fragment?
I need it as I am uploading a file inside onActivityResult() and need to display progress.
I think you onActivityResult not triggered as it is in fragment. Please use the below code in your activity which hold the fragment.
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
Fragment fragment = (Fragment) getSupportFragmentManager().findFragmentByTag(fragmentTag);
if (fragment != null) {
fragment.onActivityResult(requestCode, resultCode, intent);
}
}
put this
pbarVideoUpload.setVisibility(View.GONE);
Inside this also like I mentioned,
#Override
public void afterSuccess(Object object) {
ReturnCode successCode = (ReturnCode) object;
if(successCode.getSuccess()){
pbarVideoUpload.setVisibility(View.GONE);
Log.d("DEBUG", "Profile Video URL updated in DB");
}else{
Log.d("DEBUG", "Profile Video URL NOT updated in DB");
}
}
Fragments onCreate() was called after onActivityResult(). Hence the views were getting reinitialized and progressbar was not displayed.
Created a static variable isVideoUploading. Set its values appropriately in onActivityResult() and used it to show/hide progressbar in onCreate().
This solved half the problem. The progressbar was now visible when uploading started.
Second half of the problem was to hide the progressbar on complete of firebase async upload method. Problem was that since upload was being done in background thread which started in onActivityResult() there was no way for onCreateView() to fire again after upload was complete.
For this I sent a broadcast intent using LocalBroadcastManager when upload was complete and registered it in the same fragment. Once broadcast was received I hid the progressbar.
Related
I know I this question maybe asked before still I wanted to put my question up for all ,I need to make a scanner feature in my application , I am using a botton navigation in my project and due to that i am making more than one fragments on the same activity . Now in that fragment I need to call an ImageButton on the click of which camera activity has to open and after clicking the picture(or scanning lets suppose a QR code) it should go to the same fragment and return the scanned value. It worked in case of new activity but not working in fragment.
this is what I am doing
public class HomeFragment extends Fragment implements View.OnClickListener {
ImageButton btnScanner;
private TextView textViewName, textViewAddress;
//qr code scanner object
private IntentIntegrator qrScan;
public HomeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_home, container, false);
textViewName=(TextView)root.findViewById(R.id.textViewName);
textViewAddress=(TextView)root.findViewById(R.id.textViewAddress);
btnScanner=(ImageButton)root.findViewById(R.id.scannerBtn);
btnScanner.setOnClickListener(this);
qrScan = new IntentIntegrator(getActivity());
return root;
}
private void initViews(){
}
//Getting the scan results
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null) {
//if qrcode has nothing in it
if (result.getContents() == null) {
Toast.makeText(getContext(), "Result Not Found", Toast.LENGTH_LONG).show();
} else {
//if qr contains data
try {
//converting the data to json
JSONObject obj = new JSONObject(result.getContents());
//setting values to textviews
textViewName.setText(obj.getString("name"));
textViewAddress.setText(obj.getString("address"));
} catch ( JSONException e) {
e.printStackTrace();
//if control comes here
//that means the encoded format not matches
//in this case you can display whatever data is available on the qrcode
//to a toast
Toast.makeText(getContext(), result.getContents(), Toast.LENGTH_LONG).show();
}
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
#Override
public void onClick(View view) {
qrScan.initiateScan();
}
}
Here I am using the instance of a library class intentIntegrator.
I have also vited to
https://stackoverflow.com/questions/44622311/how-can-i-call-onactivityresult-inside-fragment-and-how-it-work/44622487#:~:text=if%20you%20call%20startActivityForResult(),deliver%20result%20to%20desired%20fragment.%20%7D&text=super.,-onActivityResult%20()%20will and
onActivityResult is not being called in Fragment yet my problem is not resolved
I'am trying to read the barcode via Zxing in fragment
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_caddie, container, false);
etCodigo = v.findViewById(R.id.etCodigo);
btnLeerCodigo = v.findViewById(R.id.btnLeerCodigo);
btnLeerCodigo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
escanear();
}
});
text = "";
return v;
}
public void escanear() {
IntentIntegrator intent = IntentIntegrator.forSupportFragment(FragmentCaddie.this);
//IntentIntegrator intent = new IntentIntegrator(getActivity());
intent.setDesiredBarcodeFormats(IntentIntegrator.ALL_CODE_TYPES);
intent.setPrompt("ESCANEAR CODIGO");
intent.setCameraId(0);
intent.setBeepEnabled(false);
intent.setBarcodeImageEnabled(false);
intent.initiateScan();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if(result != null) {
if(result.getContents() == null) {
Toast.makeText(getContext(), "Cancelaste el escaneo", Toast.LENGTH_SHORT).show();
} else {
text = text + " + " + result.getContents().toString() ;
etCodigo.setText(text);
escanear();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
The issue is it doesn't access the onActivityResult
The hosting activity overrides onActivityResult(), but it did not make a call to super.onActivityResult() for unhandled result codes. Apparently, even though the fragment is the one making the startActivityForResult() call, the activity gets the first shot at handling the result. This makes sense when you consider the modularity of fragments. Once I implemented super.onActivityResult() for all unhandled results, the fragment got a shot at handling the result.
Check this out:
onActivityResult is not being called in Fragment
I hope to be useful for u :)
The solution was quiet simple the onActivityResult that i implemented was Overrided from the parent activity
The solution is to call the fragment onActivityResult from the parent activity
private static final int BARECODE_REQUEST = 114910;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == BARECODE_REQUEST) {
super.onActivityResult(requestCode,resultCode,data);
}
}
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
I try to work with AsyncTaskLoader and I have one problem. I load in AsyncTaskLoader data from the internet then start other activity(BusModelsActivity) in method onLoadFinished
#Override
public void onLoadFinished(Loader<List<BusModelParcelable>> loader, List<BusModelParcelable> data) {
hideDialog();
Log.d("onLoadFinished", TestTags.TAG1);
Intent intent = new Intent(BusSearchParamActivity.this,BusModelsActivity.class);
intent.putParcelableArrayListExtra(AppVariables.BUS_MODELS_LIST, (ArrayList) data);
startActivity(intent);
}
but when I click back in activity BusModelsActivity and return to BusSearchParamActivity method onLoadFinished run again, and BusModelsActivity starts again. What to do with it? I call other activity when click at button:
public void pickUpButtonClick(View v) {
getSupportLoaderManager().initLoader(LOADER_MODELS,null,busModelsCallBack);
}
where busModelsCallBack is implementation of LoaderCallbacks interface. When I did debug it stoped only on onLoadFinished, not onCreateLoader or click button.
I am afraid to tell you that the AsyncTask behavior till now are not 100% granted. You have two ways to overcome this problem.
1)Do your actions in a Thread instead of AsyncTask. This will ensure that your code will be executed only once cause Thread never start twice until you want this. As following
new Thread(new Runnable() {
#Override
public void run() {
/All your code here
}
}).start();
2)Declare a static parameter in your activity called isPageLoaded initially with value false and set it to true inside your onLoadFinished after loading your page at the first time and check on its value before executing your onLoadFinished code as following:
#Override
public void onLoadFinished(Loader<List<BusModelParcelable>> loader, List<BusModelParcelable> data) {
if(!isPageLoaded){
hideDialog();
Log.d("onLoadFinished", TestTags.TAG1);
Intent intent = new Intent(BusSearchParamActivity.this,BusModelsActivity.class);
intent.putParcelableArrayListExtra(AppVariables.BUS_MODELS_LIST, (ArrayList) data);
startActivity(intent);
isPageLoaded = true;
}
}
Try:
private static boolean isClicked = false;
#Override
public void onLoadFinished(Loader<List<BusModelParcelable>> loader, List<BusModelParcelable> data) {
if(isClicked )
{
hideDialog();
Log.d("onLoadFinished", TestTags.TAG1);
Intent intent = new Intent(BusSearchParamActivity.this,BusModelsActivity.class);
intent.putParcelableArrayListExtra(AppVariables.BUS_MODELS_LIST, (ArrayList) data);
startActivity(intent);
isClicked = false;
}
}
public void pickUpButtonClick(View v) {
isClicked = true;
getSupportLoaderManager().initLoader(LOADER_MODELS,null,busModelsCallBack);
}
Is it possible to call startActivityForResult() from a non-activity class to get the results?
Scenario is something like this:
I have a class NonActivity (it doesn't derive from Activity as its not a UI).
This class will have bunch of functions(steps basically) to run.
One of the steps requires to show UI(Activity) and then get the result (user enter something).
Then been able to use that data in next following steps.
How can this be achieved without deriving from activity class as I don't have UI component?
Also since I don't want to derive from activity class that means I cannot override OnActivityResult(). Where results actually come from?
startActivityForResult() is only available from real on-screen activities, since it is a method in, well, Activity. Please redesign your application so that the user interface is driven from activities.
On the other hand, if your non Activity class is initialized and used from an onscreen Activity, you could pass that instance of the Activity to your class as a parameter in the constructor and use it to launch other Activities.
Be careful though. Using this method increases the risk of a memory leak, as the external class (Utils in my example) might keep a reference to the Activity even after its gone.
If all you want to do is access data, then you could try writing it to SharedPreferences or a Database or some files and then using the application context (passed in via a constructor again) to read it. This reduces the risk of a memory leak. Something like:
MyApiClass myApiClass = new MyApiClass(getApplicationContext());
EXAMPLE CODE
Main Activity:
public class Main extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Utils util = new Utils(this);
util.startTest();
}
#Override
protected void onActivityResult(int arg0, int arg1, Intent arg2) {
Toast.makeText(this, "onActivityResult called", Toast.LENGTH_LONG).show();
super.onActivityResult(arg0, arg1, arg2);
}
}
Utils class (which launches for result):
public class Utils {
Activity activity;
public Utils(Activity ac) {
activity = ac;
}
public void startTest() {
Intent i = new Intent(activity, Test.class);
activity.startActivityForResult(i, 1);
}
}
Test Activity:
public class Test extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(this, "Test", Toast.LENGTH_LONG).show();
this.setResult(Activity.RESULT_OK);
this.finish();
}
}
StartActivityForResult from a class using a fragment with no visible GUI. You might find something like this in a utility class.
see runGetUserAccount below. It creates its own fragment and executes a startActivityForResult. Then it has it's own onActivityResult.
public class MyGooglePlay {
private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 31502;
private ActionBarActivity activity;
private FragmentManager fragManager;
public MyGooglePlay(ActionBarActivity activity) {
this.activity = activity;
this.fragManager = activity.getSupportFragmentManager();
}
/**
* Starts an activity in Google Play Services so the user can pick an
* account
*/
private String mEmail = "";
static final int REQUEST_CODE_PICK_ACCOUNT = 1000;
public void runGetUserAccount() {
if (TextUtils.isEmpty(mEmail)) {
// run this code in gui less fragment so we can pickup the
// on activity result from inside the mygoogleplay class.
Fragment f = new Fragment() {
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
String[] accountTypes = new String[] { "com.google" };
Intent intent = AccountPicker.newChooseAccountIntent(null,
null, accountTypes, false, null, null, null, null);
startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT);
}
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
if (resultCode == Activity.RESULT_OK) {
set_Email(data
.getStringExtra(AccountManager.KEY_ACCOUNT_NAME));
// getUsername();
}
super.onActivityResult(requestCode, resultCode, data);
}
//this is to verify the fragment has been removed.
//you can log or put a breakpoint to verify
#Override public void onDestroy(){
super.onDestroy();
}
};
FragmentTransaction fragmentTransaction = this.fragManager
.beginTransaction();
fragmentTransaction.add(f, "getusername");
fragmentTransaction.commit();
}
}
/**
* #param mEmail
* the mEmail to set
*/
private void set_Email(String mEmail) {
this.mEmail = mEmail;
if (!TextUtils.isEmpty(mEmail)) {
// TODO notify caller email is ready;
// activity.onEmailReady(mEmail);
}
//we are done with the "getusername" fragment
Fragment f = fragManager.findFragmentByTag("getusername");
if (f!=null) {
fragManager.beginTransaction().remove(f).commit();
}
}
}
U should pass context as Activity,then u will get solution.
try this below code.it will work
In non Activity class
public class nonActivity {
public static void method(Activity activity)
{
Intent intent = new Intent(activity, SecondActivity.class);
activity. startActivityForResult(intent, REQUEST_CODE);
}
}
In SecondActivity
Intent intent = getIntent();
intent.putExtra("data", "data"); //here u can pass data to previous activity
setResult(RESULT_OK, intent);
finish();
In firstActivity
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
try {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
String status = data.getStringExtra("data");
//Do what u want with data
}
} catch (Exception e) {
System.out.println("=====Exception=====" + e.toString());
}
}
If you want the result back from the activity to your normal class, supposed it is a class with a custom adapter within it.
you cannot use startActivityForResult because you are not in an activity
what I did is that i launched the activity from the class with an intent. Then I calculated or did what I have to. From this activity I send the information to the main class supposed with a method MainActivity.the_method() and in the main activity I changed the custom adapter o did what I have to using the adapter object and calling adapter.getItem(position)
Hope this can give you an idea