victoralbertos / rxactivityresult Goto Github PK
View Code? Open in Web Editor NEWA reactive-tiny-badass-vindictive library to break with the OnActivityResult implementation as it breaks the observable chain.
License: Apache License 2.0
A reactive-tiny-badass-vindictive library to break with the OnActivityResult implementation as it breaks the observable chain.
License: Apache License 2.0
##Summary
If the screen has been closed before the second Activity back, then the first Activity will not receive a callback
---------------------------------------------------------------------------
FirstActivity.class
RxActivityResult.on(this)
.startIntent(new Intent(this, SecondActivity.class))
.subscribe(new Action1<Result<StartActivity>>() {
@Override
public void call(Result<StartActivity> startActivityResult) {
if (startActivityResult.resultCode() == RESULT_OK) {
} else {
}
}
});
---------------------------------------------------------------------------
SecondActivity.class
//click this button and close the phone screen,the firstActivity will never receive the result
findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Observable.timer(10, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
setResult(RESULT_OK);
finish();
}
});
}
});
Hi
After checking that we had a significant delay since the activity was launched until the result was received, we started to remove and comment all the code, seems that problem happens when ProgressView is visible, we tested on a multitude of devices and it seems that the error is in Samsung, we could not check if the error is a this model in exclusive or in all samsung.
I make a example in a fork
Error - Samsung Galaxy S7 SM-G935F
Checked - Lg nexus, Motorola, Sony Xperia
Thank you in advance.
The Andorid method does have three parameters in the method onActivityResult: requestCode, resultCode and data.
onActivityResult(int requestCode, int resultCode, Intent data)
However, the Result class does not have these parameters
Is it possible to start an intent with Bundle options?
Such as
public void startActivityForResult(
@RequiresPermission Intent intent,
int requestCode,
@Nullable Bundle options)
activity.startActivityForResult(intent,requestCode,options)
If you launch an activity B
from activity A
via this library. After the launch, to claim system resources, android killed both A & holder activity, but not B (as it is the activity interacting with the user).
In this scenario
onResult
of HolderActivity
as its not persisted in the bundleonSaveInstanceState
onResult
during onSaveInstanceState
, by the time B
is done & HolderActivity
is recreated, there is no guarantee you will have access to A
& its subscription as activity itself is not present.As per my understanding, as per the current implementation framework will not work as intended
We're trying to integrate this library with Google SignIn, and however subscriber gets no result.
After investigation, we found that there's potential issue for this library. For Google SignIn, they use a SignInHubActivity
, which presents a dialog then puts itself into pause state. Then when user click on the dialog option, it will set result and finish activity.
At this moment, RxActivityResult.activitiesLifecycle.getLiveActivity()
returns null
and thus breaks the expected subscription behavior.
Possibly related: #36
Possible fix: use getOLiveActivity
instead
In #3 you talked about startIntentSenderForResult
but what an implementation for startActivityForResult
a lot of api like the Google login for example requires to call it.
1.Use HolderFragmet to observe Activity: https://github.com/AnotherJack/AvoidOnResult
2.Use BaseActivity whch many of us may use
3.User Hook : https://github.com/guofeng007/OnResultManagerHook
When using the v7:25.3.1 app compat libraries I get the following exception when focus is returned back to the original activity.
java.lang.RuntimeException: Unable to destroy activity {com.myproject.mobile.android/rx_activity_result2.HolderActivity}: java.lang.IllegalStateException: Fragment has not been attached yet.
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:5061)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:5084)
at android.app.ActivityThread.access$1700(ActivityThread.java:221)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1853)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.IllegalStateException: Fragment has not been attached yet.
at android.support.v4.app.Fragment.instantiateChildFragmentManager(Fragment.java:2154)
at android.support.v4.app.Fragment.getChildFragmentManager(Fragment.java:704)
at rx_activity_result2.RxActivityResult$Builder.getTargetFragment(RxActivityResult.java:146)
at rx_activity_result2.RxActivityResult$Builder.getTargetFragment(RxActivityResult.java:148)
at rx_activity_result2.RxActivityResult$Builder.access$100(RxActivityResult.java:50)
at rx_activity_result2.RxActivityResult$Builder$3.response(RxActivityResult.java:127)
at rx_activity_result2.HolderActivity.onDestroy(HolderActivity.java:98)
at android.app.Activity.performDestroy(Activity.java:7102)
at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1170)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:5039)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:5084)
at android.app.ActivityThread.access$1700(ActivityThread.java:221)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1853)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
The problem stems from lazy creation of the fragment manager in the new library release.
I had to also address some of my own code which made use of fragment.getChildFragmentManager().getFragments() to check if the fragment isAdded() before requesting a child fragment manager.
Updating the line 137 in RxActivityResult should fix the problem.
if(fragment != null && fragment.getChildFragmentManager() != null) {
to
if(fragment != null && fragment.isAdded() && fragment.getChildFragmentManager() != null) {
Hello, something has gone wrong with jitpack for that version : https://jitpack.io/#victoralbertos/RxActivityResult
Is there a need for the library project to have a higher minSdk
value than 7?
It appears to build fine.
Thanks for the library, its very convenient to be used.
But when windowIsTranslucent is true in theme style, screen will flash once target activity finished. It looks like the HolderActivity cannot handle the transition anim correctly, because when windowIsTranslucent is false, there is no issue.
If you need to apply a theme here, can you name it specific to this project so that it doesn't conflict with other libraries/projects?
...and I really like your lib! :)
Thanks a lot for sharing this lib.
I'm using RxPaparazzo in our app, but the adding picture has severe delays on our Samsung devices, north of 10 seconds.
return RxActivityResult.on(targetUi.activity())
.startIntent(intent)
.map(new Func1<Result<Activity>, Intent>() {
@Override
public Intent call(Result<Activity> result) {
return StartIntent.this.getResponse(result);
}
});
The map function would take 10 seconds since the Observable was started. Attach sources doesn't work for me so I can't debug further than that.
Failing test attached to #14
Currently if a fragment has been instantiated as a child fragment from a parent one, there is no callback call for the subscriber fragment child.
I have a use case, which cannot start the intent with RxActivityResult.on(this).startIntent(myIntent)
and the intent will be fired somewhere else which I cannot control it. How can I listen to the onActivityResult without starting the intent myself?
Hi, just looking at libraries using RC2 and found these issues.
emitted
field is private and generates an accessor:emitted
field is not volatile and possibly read in another thread:liveActivityOrNull
is possibly read in another thread and should be volatile:subject
could be final:clazz
is private and generates an accessor:https://github.com/VictorAlbertos/RxActivityResult/blob/2.x/rx_activity_result/src/main/java/rx_activity_result/RxActivityResult.java#L51
https://github.com/VictorAlbertos/RxActivityResult/blob/2.x/rx_activity_result/src/main/java/rx_activity_result/RxActivityResult.java#L100
https://github.com/VictorAlbertos/RxActivityResult/blob/2.x/rx_activity_result/src/main/java/rx_activity_result/RxActivityResult.java#L138
Seems the library doesn't have static method RxActivityResult.register(...) that mentioned to the README.md
this.activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
ActivitiesLifecycleCallbacks.this.liveActivityOrNull = activity;
}
public void onActivityStarted(Activity activity) {
}
public void onActivityResumed(Activity activity) {
ActivitiesLifecycleCallbacks.this.liveActivityOrNull = activity;
}
public void onActivityPaused(Activity activity) {
ActivitiesLifecycleCallbacks.this.liveActivityOrNull = null;
}
public void onActivityStopped(Activity activity) {
}
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
public void onActivityDestroyed(Activity activity) {
}
};
If I finish an activity inside onCreate
, the method onActivityPaused
won't be called. ActivitiesLifecycleCallbacks.this.liveActivityOrNull
don't free the reference to the activity and causes memory leaks!
in HolderActivity.onCreate(HolderActivity.java:33)
onResult = request.onResult()
The library didn't work with compile version android 26 or 27. It stop working on Samsung Devices.
Any plans to make a library version for usage with RxJava 2?
Btw, great library!
The process of shifting between A and B is no animation
But how to remove animation after using RxActivityResult
RxActivityResult.on(mActivity)
.startIntent(new Intent(mActivity, SearchActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
.putExtra("custom picker", mainActivity.isCustomPicker()))
.subscribe(new Action1<Result<Activity>>() {
@Override
public void call(Result<Activity> result) {
if (result.data() != null) {
mainActivity.onReturnCustomPickerRes(
result.data().getIntExtra("res", 0));
}
}
});
use This
//from public Builder(T t)
Activity activity= (Activity) t;
activity.startActivity(new Intent(activity, HolderActivity.class));
replace
activitiesLifecycle.getOLiveActivity().subscribe(new Action1<Activity>() {
@Override public void call(Activity activity) {
activity.startActivity(new Intent(activity, HolderActivity.class));
}
});
the requestCode always 0;
Intent takePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
RxActivityResult.on(this).startIntent(takePhoto)
.subscribe(result -> {
Intent data = result.data();
int resultCode = result.resultCode();
// the requestCode using which the activity is started can be received here.
int requestCode = result.requestCode();//why always requestCode= 0?
if(requestCode == YourActivity.YOUR_REQUEST_CODE)
{
// Do Something
}
if (resultCode == RESULT_OK) {
result.targetUI().showImage(data);
} else {
result.targetUI().printUserCanceled();
}
});
At first thanks for this lib, but i found that can not use it with overridePendingTransition to animate showing activity. Can you check or suggest decision?
Hello, i'm usin 4.2.0 since 4.2.1 is not "pullable".
Apparently DialogFragment is not getting any result back when using .on(fragmnet).
If i change it with .on(getActivity()) everything works fine.
If you enable don't keep activities on dev settings to simulate such scenario when coming back to MainActivity
you would get redirected once more to the camera app and then after taking another photo you get back to MainActivity
again but it won't display the picture that was taken
Some apis, like IAB (in app billing), requires to call startIntentSenderForResult
instead of calling startActivityForResult
.
That's why this needs to be implemented.
Hi! I'm migrating our app to AndroidX, and I was wondering:
When you create an Activity with a transparent background, display the progress in it, and finish when a certain process is completed, the animation will appear running and it will appear flickering.
thank you.
It would be really useful, as some Android apis require this and often need to be called from a service. To create an invisible Activity for this every time is not as nice, and also would not easily support getting the result in the service... I saw a few solutions out there...:
http://stackoverflow.com/a/38414213
http://stackoverflow.com/a/37754232
http://stackoverflow.com/a/40356400
What do you think? This could be a possible addition to this library?
Thanks for your great work!!
Hi guys, we've been using this library from a while now, and first of all great stuff 👍
Recently we're seeing an error when we start the contacts picker intent on a fragment.
Caused by: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.xyz.xyz/rx_activity_result2.HolderActivity}; have you declared this activity in your AndroidManifest.xml?
We're using the support fragment - android.support.v4.app;
ver - implementation 'com.github.VictorAlbertos:RxActivityResult:0.4.5-2.x'
And we're using v 27.1.1 support libraries.
With thanks, any help will be great!
Hello,
I was in the process of using RxActivityResult to change the bad "code + onActivityResult override" pattern.
In particular, using Intent.ACTION_GET_CONTENT provides a SecurityException when trying to read the result.
Code is the following
Intent pickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
pickerIntent.addCategory(Intent.CATEGORY_OPENABLE);
pickerIntent.setType("image/*");
RxActivityResult.on(this)
.startIntent(Intent.createChooser(pickerIntent, null))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(activityResult -> {
Intent intent = activityResult.data();
int resultCode = activityResult.resultCode();
if (resultCode == Activity.RESULT_OK && intent != null) {
if (intent.getDataString() != null) {
Timber.d("DataString: %s - %s",intent.getDataString(), intent.getData());
InputStream inputStream = getContext().getContentResolver().openInputStream(intent.getData());
FileOutputStream fos = new FileOutputStream(Utils.genCacheFile());
Utils.pipeIOOO(inputStream,fos); // <--- EXCEPTION
}
}
});
The exception is the following:
java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.contentprovider.impl.MediaContentProvider from ProcessRecord{289c731 31097:com.andreabaccega.myprinter/u0a86} (pid=31097, uid=10086) that is not exported from uid 10065
It looks like that when using ACTION_GET_CONTENT the picker automatically allows permission to the requiring context to access the picked images. see http://stackoverflow.com/questions/38301605/reading-com-google-android-apps-photos-contentprovider-mediacontentprovider-requ
and
http://stackoverflow.com/questions/30572261/using-data-from-context-providers-or-requesting-google-photos-read-permission/30909105#30909105
I also tried using .targetUI() to get the context with no luck. (Expected also since both resultUI() and this are the same object).
Steps to reproduce:
Results in a crash:
FATAL EXCEPTION: main
Process: io.victoralbertos.app, PID: 3083
java.lang.RuntimeException: Unable to start activity ComponentInfo{io.victoralbertos.app/rx_activity_result.HolderActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'rx_activity_result.OnResult rx_activity_result.Request.onResult()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2625)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2686)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1440)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:5969)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:801)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:691)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'rx_activity_result.OnResult rx_activity_result.Request.onResult()' on a null object reference
at rx_activity_result.HolderActivity.onCreate(HolderActivity.java:33)
at android.app.Activity.performCreate(Activity.java:6669)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2578)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2686)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1440)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:5969)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:801)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:691)
Buenas tardes Victor! :-)
Sorry, can't do demo project now. But it seems, like when you have complex UI there's NPE in that code:
@Nullable private Fragment getTargetFragment(List<Fragment> fragments) {
if (fragments == null) return null;
for (Fragment fragment : fragments) {
if(fragment != null && fragment.isVisible() && fragment.getClass() == clazz) {
return fragment;
// NPE IS HERE SEE |
// v
} else if (fragment.getChildFragmentManager() != null) { // <------ THAT LINE
List<Fragment> childFragments = fragment.getChildFragmentManager().getFragments();
return getTargetFragment(childFragments);
}
}
return null;
}
(RxActivityResult.java line 139)
It seems, like fragments array have target Fragment, but ALSO has null element inside. So if you just skipped null-element - NPE would dismiss.
In my UI I have fragments (cause of navigation drawer) and nested fragments (in ViewPager). RxPaparazzo code is called from nested fragment.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.