Turbolinks 5 and Android: Fails when use file upload (webview) - android

Problem
When the user clicks on choose file, I intercept that click natively and I call the native view (screen 3 in the mockup).
After the user select the file he wants to upload, I need to "reload" the view in order to add the name of the file in the form, so the user can get the feedback that he selected the file correctly.
In order to do this, I'm calling onRestart with the following code:
#Override
protected void onRestart() {
super.onRestart();
// mCM is a variable to detect when the user is choosing a file.
if (null == mCM) {
// Since the webView is shared between activities, we need to tell Turbolinks
// to load the location from the previous activity upon restarting
TurbolinksSession.getDefault(this)
.activity(this)
.adapter(this)
.restoreWithCachedSnapshot(true)
.view(turbolinksView)
.visit(location);
}
}
As you can see, in this method when is uploading a file I do NOT reload the view using TurbolinksSession.
But if I don't call TurbolinksSession, Turbolinks never calls visitProposedToLocationWithAction.
Scenario
NOTE: Download the image if you want to see the image bigger.
What am I missing? Is there a way to solve this problem and get the expected result?

In this 2 issues you can find a solution and resolution of the problem (read it in this order):
https://github.com/turbolinks/turbolinks-android/issues/53
https://github.com/turbolinks/turbolinks-android/issues/65
https://github.com/turbolinks/turbolinks/issues/88

Related

Android TV PlaybackControlsRow

So building a new app specifically for the Android TV interface (lollipop leanback) and I'm using the PlaybackOverlayFragment that is provided by the framework which has a PlaybackControlsRow with all the usual controls on it.
The problem is, the default behavior is for the user to have to click the "Play" button to start the video and I want it to start automatically. That part is easy and I have it working but then the Play/Pause icons on the provided control are out of sync (showing play when should be pause) because the item was started outside of the events of clicking on that control.
Documentation is sparse on these framework elements and examining the class I can't find any public method that would allow me to put this control in the proper "mode" or tell it to display the play or pause icon myself.
Anyone with experience with these yet that would know how to do this?
In order to change the state of the button, even after adding your Actions to the Adapter, you'll need to notify the changes to the adapter that has your Action.
mPlayPauseAction.nextIndex(); // next index, if it was pause, it'll be play
notifyChanged(mPlayPauseAction);
// where notifyChanged(Action action) is:
private void notifyChanged(Action action) {
ArrayObjectAdapter adapter = mPrimaryActionsAdapter; // reference to your adapter
if (adapter.indexOf(action) >= 0) {
adapter.notifyArrayItemRangeChanged(adapter.indexOf(action), 1);
return;
}
}
Well, I partially answered my own question.
If I know before the PlaybackControlsRow is created that I want to set it to the pause state (actually, playing state but showing pause button) then if I call setIndex(PlaypauseAction.PAUSE) on the PlayPauseAction before adding it to the controlsrow then it works.
It doesn't appear that I can modify it myself after adding it but that may be something else I'm doing wrong.

Android web view "back" button to load previously loaded div

I will try to explain this as clearly as possible. I have an android app using web view to basically load a webpage as my app. I have everything working great, however the back button seems to be an issue. I have set this page up all on one html page, it will load in a div when certain buttons are clicked to give the feel of a new page without actually having one. I basically want the back button (on the android tablet or smartphone) to load the previously loaded div, but I have no idea where to start with this. Here is what the content switching jquery looks like -
function contentSwitcher(settings){
var settings = {
contentClass : '.contentToLoad',
navigationId : '#sideMenu',
servFront : '#clickHomeHome'
};
//Hide all of the content except the first one on the nav
$(settings.contentClass).not(':first').hide();
$(settings.navigationId).find('li:first').addClass('active');
//onClick set the active state,
//hide the content panels and show the correct one
$(settings.navigationId).find('a').click(function(e){
var contentToShow = $(this).attr('href');
contentToShow = $(contentToShow);
//dissable normal link behaviour
e.preventDefault();
//set the proper active class for active state css
$(settings.navigationId).find('li').removeClass('active');
$(this).parent('li').addClass('active');
//hide the old content and show the new
$(settings.contentClass).hide();
contentToShow.show("slow");
});
}
contentSwitcher();
});
note: I've cropped out a bunch of it just to show how it works on a basic level.
Does anyone have any suggestions as to where to begin. I'd just like the back button function to be able to maybe check a started previous div name stored somewhere and load that.
thanks!
You can try using the History API. There are numerous tutorials on the web e.g. this one is quite good:
http://diveintohtml5.info/history.html
Basically this is how it works. When the user clicks the link for the div to show you push the state to the history stack.
history.pushState({<object with any information about state>}, pageTitle, newUrl);
This will push the state to the history stack meaning that when the user presses the back button on any modern browser like webkit it will take that state into consideration. When back action is taken it will then pop the state from the history stack. This action you have to listen to and handle in any way you see fit:
window.addEventListener("popstate", function(event) {
// event object contains the information from the pushed state
// do whatever needed to load the previous page here
});
The History API requires you to structure your code in a certain way for it to work well. For this I would recommend to use some existing framework that handle the back events for you e.g. Backbone.js. Hope this helps.

How to save cookies for my android web application

lets say I have an application for my University web site. Where user can navigate by pressing on screen button( Actually, what I did, I categorized everything in my main layout,where each button represents each fields, if any one presses myaccountStatus, then he will be directed to that specific link) However, my web site needs user name and password every time. Where I don't want my user to bother about this at all. So my question is, is there any way I can enable auto-log in?
My application has basic core web feature implemented(WebView, zoom, java-script enabled, some back, forward, stop, reload, favorite, save for offline reading) and everything is working fine, please help with the auto-log in problem.
So far I know, I can do this by saving cookies. But I have no Idea, how they look, what are they and how to handle those thing. So, please give me a step by step tutorial for this problem. Thanks in advance.
If your are using a web-view based approach (maybe something like cordova?) you could just use the local storage or the web sql standard for html5 apps: Tutorial for Web-Sql.
If you want to store cookies you have to enable them. I'm doing this in my Phonegap/Cordova application with this small Lines of code:
#Override
public void onCreate(Bundle savedInstanceState) {
// ... do whatever you want...
// this lines allow to set cookies
try {
CookieManager.setAcceptFileSchemeCookies(true);
} catch (Throwable e) {
}
// and the default stuff for phonegap/cordova to show a splashscreen and load the application
super.onCreate(savedInstanceState);
super.setIntegerProperty("splashscreen", R.drawable.splash);
// load the index url from config adding locale support.
super.loadUrl(Config.getStartUrl() + "?locale="
+ Locale.getDefault().getLanguage(), 4000);
}
I hope this helps.

FbDialog doesn't show full content on smaller devices

Steps to repro
Log in to FB with new FB account I can see the webdialog showing me
current goals and other stuff, but I can not see Authorize OK cancel
buttons(probably moved down). I can not scroll to see those buttons
Can any one suggest me quick fix, without necessarily updating FB SDK
I can confirm this is affecting Facebook SDK 2 and 3 in Android. I can't speak to iOS. For some reason, scrollbars are disabled in their WebDialog.java code so I tried enabling scrollbars in setUpWebView. Scrollbars now appear in this prompt but the OK and Cancel buttons aren't there. So, it's not a case of the buttons being off-screen and unreachable but rather the buttons aren't part of the content at all when the Current Goals section is included.
It looks like this is a problem Facebook will need to resolve on their side.
I just posted this workaround to: webDialog "CURRENT GOALS" header but no button to authorize or cancel
In the FaceBookSDK I modified com/facebook/widget/WebDialog.java, so that once the web dialog was loaded it would look for the block that contains "Current Goals" and hide it (if it exists). Once you do that, the buttons are visible again (at least they were for me).
In com/facebook/widget/WebDialog.java:
private class DialogWebViewClient extends WebViewClient {
// ... other methods ...
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!isDetached) {
spinner.dismiss();
}
/*
* Once web view is fully loaded, set the contentFrameLayout background to be transparent
* and make visible the 'x' image.
*/
contentFrameLayout.setBackgroundColor(Color.TRANSPARENT);
webView.setVisibility(View.VISIBLE);
crossImageView.setVisibility(View.VISIBLE);
// I don't know how to highlight in the code block
// So I just add this extra long comment to make it obvious
// Add a javascript call to hide that element, if it exists
webView.loadUrl("javascript:try{ document.getElementById('nux-missions-bar').style.display='none'; } catch (e) {}");
// End changes
}
This should help, at least until FaceBook fixes the API.
I was facing the same problem which is solved. I just changed my app permission which was running in sandbox mode> I just changed it to live mode and suddenly everything started working fine. I think there was a problem with fb sdk which is solved by now.....

Return from Android Gallery in jUnit?

I have an application in which if you click a button, it opens the Android Gallery application. The user can then select an image for my application. The thing is, if I click that button in JUnit, it opens up the Gallery and then just sits there. I have to manually choose a picture. I just want to be able to open the Gallery and then go back or if possible select an image.
I tried several options such as -
sendKeys(KeyEvent.KEYCODE_BACK)
Robotiums goBack(), goBackToActivity(), sendKey() functions
Robotiums clickOnScreen() function to click and select an image
but none of these seem to work. So what do I do?
I had the same problem. You can't do this, as the Android Gallery is another application running in its own sandbox which you cannot reach from your testing code.
However, I came up with the following solution. You can build your own dummy application that provides an Intent filter for opening images. In this application you simply return the intent with an ok.
Now you only have to select your application as the default application when first opening your image from your test application. Afterwards, everything should work automatically.
Once you're done with testing, you can reset the default intent filter in your Android device's settings.
The code for my solution can be found in this discussion: How to provide content for Intent.ACTION_GET_CONTENT
It is possible to simulate response returned from gallery.
The code snippet below do all the work.
final Intent data = new Intent();
data.setData(Uri.parse("content://media/external/images/media/458")); // put here URI that you want select in gallery
Runnable runnable = new Runnable(){
#Override
public void run() {
getActivity().onActivityResult(3333,-1, data);
synchronized(this) {
this.notify();
}
}
};
synchronized(runnable) {
getActivity().runOnUiThread(runnable);
runnable.wait();
}
This method has two drawbacks:
onActivityResult method of your activity should be public which brakes encapsulation.
Test will not actually click button which opens gallery and onClick handler won't be executed.
But the benefit of such approach is that you don't need to build mock application and change any defaults in android settings.

Categories

Resources