RxImagePicker not calling completion if orientation changes when taking image - android

I'm using RxImagePicker to take photos in my portrait-only-forced app:
RxImagePicker.with(getActivity()).requestImage(Sources.CAMERA).subscribe(new Action1<Uri>() {
#Override
public void call(Uri uri) {
RxImageConverters.uriToBitmap(getActivity(), uri).subscribe(new Action1<Bitmap>() {
#Override
public void call(final Bitmap bitmap) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
//i take over here if we ever get here...
}
});
}
});
}
});
If I take a picture without rotating the device, it works (although the image is rotated but that's another issue). However, if I take a picture in landscape orientation, uriToBitmap is never called. It's not my activity or fragment being restarted, as everything's state is preserved inside my app.
What am I doing wrong?

Acording to sources, RxImagePicker uses PublishSubject to communicate uri notifications to the client. Picker starts hidden activity, and that activity issues onCompleted() in it's onDestroy() callback. That callback is called on activity recreation in response to orientation change. Because Subject is Observable, it obeys to Observable contract, which states there should be no further notifications after onCompleted(), hence onNext() notifications following onCompleted() are ignored. There is another issue: onCompleted() is called twice when image is successfully picked. Seems like there is no workaround, possible solutions:
Fork library and fix aforementioned issues on your own
File issue on github so author can address them
Roll out your own solution ( best IMO)

It turned out to be something not-so-extraordinary.
I've simply forgot to update to the latest version and was using a few months old version of the library, which had the fix for the problem that I'm facing.
I've updated to the latest version and the problem went away.

Related

android camera classic API: writing a blocking (synchronous) 'takePicture()'

I'm writing an Android app and I need to take photos. I got it mostly working very quickly using the standard tutorial. But I need to write a blocking version of "takePicture()". I've trying reworking my design so that everything is done asynchronously, but the code just ends up as spaghetti code because so many tasks are dependent on the previous task completing. And I had expected that taking a photo would take less than a second. So I think it's a reasonable goal to have a blocking (synchronous) "takePicture()".
So I created a camera in the UI thread (I'm an Android newbie but I presume that 'onCreate()' et al are called in the UI thread). I also open the camera and release it in the UI thread. I also call "takePicture()" in the UI thread. I tried polling for a "volatile byte[] jpeg;" field to become non-null, with a "while (jpeg != null) sleep(1000);" but it never gets assigned. To my surprise, my callback doesn't get called until I pass out of the "onClick()" function - 'takePicture()' doesn't seem to trigger anything, it merely queues something, as far as I can figure out.
My next attempt involved doing all the camera work (open, takePicture, release) in a "ExecutorService.newSingleThreadExecutor()" but that was also unsuccessful. Even when I did it this way (see below), the callback wasn't called until the app finished the 'onClick()'.
public byte[] takePhoto()
{
if (camera == null)
return null;
cameraThreadService.submit(new Runnable() {
#Override
public void run() {
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
jpeg = data;
}
};
camera.takePicture(null, null, mPicture);
}
});
int n = 0;
while (jpeg == null) {
sleep(1000);
if (n++ > 5)
break;
}
return jpeg;
}
Can anyone tell me how to write a blocking (synchronous) 'camera.takePicture()'?
To my surprise, my callback doesn't get called until I pass out of the "onClick()" function - 'takePicture()' doesn't seem to trigger anything, it merely queues something, as far as I can figure out.
Your onPictureTaken() is called on the main application thread. The main application thread cannot do two things at once. onPictureTaken() cannot be called until after you return from onClick().
Can anyone tell me how to write a blocking (synchronous) 'camera.takePicture()'?
That is not possible, sorry.

How to cancel Picasso fetch requests by tag?

When I enter an activity I'm calling this method:
private void cacheImagesAndLoadToMemory() {
for (City city : cities) {
Picasso.with(this).load(city.getImageUrl()).tag("fetch_images").fetch();
}
}
This fetches around 200 images which equates to around 45MB of data. Then I attach a fragment to this activity but when I leave the fragment I want the requests for the 200 images to be cancelled. So I have this code set up.
#Override
public void onDestroy() {
super.onDestroy();
Picasso.with(getActivity()).cancelTag("fetch_images");
}
But the fetch requests are not being cancelled. I have a bandwidth monitor on my status bar and can see that data keeps being pulled until all 200 images have been cached. Not sure what I'm doing wrong.
Seems to be a well known bug, cf. Github bug #1205.
Unfortunately Picasso project does not seem to move forward lately.

Android Brightcove onVideo does not get called sometimes and hence video does not play

I have integrated Brightcove android-sdk-4.2.7 and trying to play video using videoID.
Here is the code snippet :
Catalog catalog = new Catalog(<**MEDIA_READ_TOKEN**>);
catalog.findVideoByID(videoId, new VideoListener() {
#Override
public void onError(String error) {
Log.e(TAG, "onError : " + error);
}
#Override
public void onVideo(Video video) {
Log.i(TAG, "onVideo called" );
brightcoveVideoView.add(video);
brightcoveVideoView.start();
}
});
When I launch video_player_activity from other activity for the first time video plays perfectly fine, but when I go back to second activity and again try to play the same/other video, It does not play. onVideo does not get called. Sometimes it gets called after a long time.
Following are some more details :
activity is getting destroyed properly when I go back
onError is not getting called
video id is getting set properly
Tried emitter events and READY_TO_PLAY event occurs but DID_PLAY does not
Android version I tested on is 4.4.x
What might be the possible issues? Any help/pointer around this will be really appreciated.
Thanks!
Repeated calls to findVideoByID(), should work fine. For each one, you should see a request in the logcat, something like:
D/HttpService(27297): issuing GET request: http://api.brightcove.com/services/library?command=find_video_by_id&video_id=3603631382001...
and a response, something like:
D/HttpService(27297): response: {"id":36036...
If that is not the case, please file a bug with Brightcove Support. If that is working, there isn't enough information here to debug further. You could try to compare what you are doing with the public sample apps available on Github:
https://github.com/BrightcoveOS/android-player-samples
These apps don't have multiple activities like your scenario, but they do handle the app going into the background and then being brought back to the foreground. Extending the BrightcovePlayer or BrightcovePlayerFragment enables the lifecycle handling. If you don't extend one of those classes, you have to write your own lifecycle handling, as if you were using the Android VideoView. For example, calling pause() in onPause() and calling stopPlayback() in onStop().

Java - Android : Thread being called (run) twice

I would like some help regarding Java - Android MultiThreading
While learning to develop my app in a multi-threading way in order to take advantage of the ever-growing multi-core devices market share (most devices are quad core now, some even octo-core), I ran in a situation where my threads are either being calling twice or running twice.
I just don't why and how.
[EDIT 3]
Alright, I narrowed down the issue : I called the AsyncTask from the onResume() method. Although my app did not lost focus (which would mean a call to onPause() then back to onResume() upon return of focus in which case my threads would be run twice) during the tests, I solved the issue by moving away the call to FetchFriendsList to another place.
So far so good, but since in my tests the app did not loose focus or perhaps it did but I could not witness it (!), I think there is another reason behind so I'd say my problem is not entirely solved ... at least for the moment. It does work though. Perhaps I did solve the issue but I do not know how :(
[end of EDIT 3]
I am implementing last Facebook SDK and I am using it to fetch the end-user friends list, which seems to do the work.
Since I am running this operation in an AsyncTask, I am not using request.executeAsync().
Instead I am using request.executeAndWait(). Facebook JavaDoc does state that this method must only be used if I am not in a the Main UI Thread which is my case otherwise I would get a NetworkOnMainThreadException.
Anyway, this is where the weird behavior is happening.
private final ArrayList<GraphUser> userFriendsList = new ArrayList<GraphUser>();
public final void fetchFriendsList() {
if (this.session != null && this.session.isOpened()) {
final Request requestUserFriendsList = Request.newMyFriendsRequest(
this.session, new Request.GraphUserListCallback()
public final void onCompleted(final List<GraphUser> users, final Response response) {
if (users != null && users.size() > 0) {
Log.v("Retrieved Friends List -> ", String.valueOf(users.size()));
userFriendsList.addAll(users);
}
}
}
);
if (this.asyncFlag)
requestUserFriendsList.executeAsync();
else
requestUserFriendsList.executeAndWait();
}
}
In my case, asyncFlag is set to false because I need to do stuff synchronously in that specific order :
Fetch User Friends List (not on the Main (UI) Thread)
Save friends list on device (separate new thread)
Save friends list on a server (separate new thread)
Following this pattern, the line userFriendsList.addAll(users); is called twice.
In the logcat, the Log.vis showed twice as well, and finally looking with the debugger, the content of the user friends list is made of duplicates.
But that's not all ... step 2 and 3 are indeed two separate threads which are both created and spawned within the same method : public final void asyncSaveFacebookFriendsList().
And guess what, this method is even called twice !
just why ?
At the beginning I was calling the method for step 2 and 3 like this :
[...]
userFriendsList.addAll(users);
asyncSaveFacebookFriendsList(); // it was private before
[...]
This is where the issue started as both line were running twice.
So I thought, alright, I'll call it later like this :
[...]
fetchFriendsList();
asyncSaveFacebookFriendsList(); // it is now public
[...]
But the issue remains still.
If I don't call public final void asyncSaveFacebookFriendsList(), then nothing is run twice.
Why does this issue happen ? Is there something I did not get in Java Threads ?
I do not think this is somehow related to the Facebook SDK because following the same pattern (and doing it also at the same time), I have the same issues when fetching and storing the end-user Twitter friends list.
So I do believe I am doing something wrong. Does someone have any idea in what possible case a thread is called twice ?
Note : all threads are started this way : thread.start(). I am not using any ThreadPool nor the ExecutorService.
In case you need more background context :
Content of AsyncTask : (no need to wonder why Void and Long, I remove the irrelevant code related to it)
private final class FetchFriendsLists extends AsyncTask<Long, Integer, Void> {
protected final Void doInBackground(final Long... params) {
if (params[0] != Long.valueOf(-1)) {
[...]
twitterAPI.fetchUserFriendsList();
publishProgress(1, -1);
}
if (params[1] == Long.valueOf(0)) {
[...]
facebookAPI.fetchFriendsList();
publishProgress(-1, 0);
}
return null;
}
protected final void onProgressUpdate(Integer... flags) {
super.onProgressUpdate(flags);
if (flags[0] != -1)
twitterAPI.asyncSaveFacebookFriendsList();
if (flags[1] == 0)
facebookAPI.asyncSaveFacebookFriendsList();
}
}
As you can see, I start step 2 and 3 in onPublishProgress() which runs on the Main UI Thread. Brefore it was in the doInBackground() method : the issue happens in both cases!
[EDIT]
After further test, it would seem any kind of code is in fact running twice.
I created a simple method called test in which in print a counter. The counter incremente twice as well !
Why you use onProgressUpdate?¿?
onProgressUpdate(Progress...), [...]. This method is used to display any form of progress in the
user interface while the background computation is still executing.
For instance, it can be used to animate a progress bar or show logs in
a text field.
This is used not at the finish of the petition, but when progress increased.
Read this:
http://developer.android.com/reference/android/os/AsyncTask.html
You need to use:
protected void onPostExecute(Long result) {

Android: CalledFromWrongThreadException from WebView's shouldOverrideUrlLoading

I am developing on a library that is somehow getting a CalledFromWrongThread Exception crash on Samsung Galaxy S1 (api v7 - android 2.1). The code is something like this:
class MyWebViewClient extends WebViewClient {
#Override
public void shouldOverrideUrlLoading(WebView view, String url) {
someListener.addToUiView();
}
}
and of course, the method that is actually throwing the error (which implements a listener callback):
View v;
public void addToUiView(){
v.addView(new TextView(context)); //<-- this line is throwing the error on rare occasions
}
I'm skipping some code in between, but i'm not doing anything weird in other places. Also note: this crash only seems to have been happening a very very small % of the time. (not necessarily conclusive, as not everyone reports their data).
has anyone else come across this?? Is WebCore threading messing things up?
Now I haven't actually tested this but I am going to answer to the best of my knowledge. That said, my instinct is telling me that you are only seeing the error intermittently because web requests from a WebView (browser) happen with varying levels of asynchronicity and probably utilize a thread pool to accomplish this. Basically, sometimes it requests resources in parallel and sometimes it doesn't. Worse yet you might be seeing this error on only a single device because OEMs optimize OS level code (like the WebView internals) based on their preferences and opinions (especially Samsung). Either way the real problem is that you are doing something "UI related" in a place that is definitely not guaranteed to be "UI friendly"... That is, anywhere where you are getting a subsystem callback.
The solution to your problem is much more simpler than the explanation: just use your context (that I am assuming is an Activity)..
Activitys have a built in function called runOnUiThread(Runnable) that will guard the code inside the runnable from running on the wrong thread. Basically, your problem is really common and android has a built-in solution. runOnUiThread will only add overhead if required, in other words if your thread is the UI thread, it will just run the Runnable, if it isn't it uses the correct Handler (the one associated with the UI thread) to run the Runnable.
Here is what it should look like:
View v;
public void addToUiView() {
final Activity activity = (Activity) context;
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
v.addView(new TextView(activity));
}
});
}
i coded that up right inside the SO window so my apologies for any egregious errors, I hope that helps, and let me know if you need more info or of this doesn't solve your problem -ck

Categories

Resources