Streaming bytes from controller, android browser, download fails - android

Grails 1.3.7
I have some code that looks like this...
response.setHeader("Content-disposition", "attachment; filename=${fileName}")
response.contentType = download.contentType
response.contentLength = file.length()
response.outputStream << file.getBytes()
On the desktop and on the iPad, the downloads work just fine. But on android devices it just gives me "Unknown myserver.com In progress". And then eventually fails. A couple of points...
This happens locally, staging, and on production servers
Testing without SSL, everything works fine.
When I try the download in the Dolphin Browser I get the same results
with an added bit of text "Waiting for data connection"
Update #2: Stacktrace that only occurs when downloading from an Android device:
Stacktrace follows:
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at com.sun.net.ssl.internal.ssl.OutputRecord.writeBuffer(OutputRecord.java:297)
at com.sun.net.ssl.internal.ssl.OutputRecord.write(OutputRecord.java:286)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecordInternal(SSLSocketImpl.java:743)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:731)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
at com.wbr.consumer.ProductController$_closure1_closure2.doCall(ProductController.groovy:30)
at com.wbr.consumer.ProductController$_closure1.doCall(ProductController.groovy:28)
at com.wbr.consumer.ProductController$_closure1.doCall(ProductController.groovy)
at java.lang.Thread.run(Thread.java:680)

I realize this is a few months late but I also ran into this issue with the Android browser and a Grails application I was working on.
The issue appears to be how Android handles downloadable content and the android browser integration with download manager.
http://code.google.com/p/android/issues/detail?id=1978
http://code.google.com/p/android/issues/detail?id=18462
I was receiving two requests on the server side for a downloadable file; one from the browser and one from the download manager. The one from the browser ends up getting terminated and the socket closed as soon as the browser determines that it is downloadable content. The browser then hands off the download to the download manager.
I was also having issues with the download failing from download manager but that had to due with me not sending headers as soon as they were ready. I ran into this only with larger APKs, small APKs (under 10-20K) seemed to download just fine.
Some code may help:
response.contentType = 'application/vnd.android.package-archive'
response.addHeader('Content-Disposition', 'attachment; filename=FILENAME.APK')
// output file content
response.setStatus(200)
response.setContentLength("CONTENTSIZE")
// send headers
response.flushBuffer()
try {
response.outputStream << {FILE}.getBytes()
response.outputStream.flush()
} catch (SocketException e) {
log.error(e)
}
return
With this, I always end up with one socket exception. Don't know if thats avoidable, from some quick searching I didn't see a way to determine socket state from servlet without simply trying to write to the socket.

It sounds like there are potentially 2 issues
the browser you are using does not trust the self signed cert.
Do other SSL sites work from this browser?
Can you install your STG
cert into the browser's trusted certs store?
A stupid question is : did you get the request URL correct? https vs http ... i know it's stupid.....
the response is never flushed to the client. Try this:
response.outputStream.flush()

Related

How to change file capabilities on Android? [duplicate]

Is it possible to host a web server within an Android phone itself?
Similar to Apache. I want to access the web server from the mobile
browser itself.
Couldn't find any reference online. Is this possible?
Thanks in advance
Short: yes. If you are looking at code, check out the org.apache.http package. If you are looking at a ready app, check iJetty and kWS.
KSWEB — a suite for web development on the Android platform. It consists of: a web server, PHP programming language and the database MySQL. KSWEB allows you to organize a platform for running and debugging Web applications (sites) in your Android device. Working with the application is very simple. To start the server it is enough to run our application, select, if necessary, port and the root directory.
By default, KSWEB contains a fully functional configuration file of the server, PHP and MySQL. However, if you want something to change them, go to the server options and click on the item «INI Files». Configuration files will be moved to SD-card of your device at «/mnt/sdcard/ksweb/ini/», if available. If repeatedly clicking on the item settings «INI Files» KSWEB will use the internal configuration files.
What's in the plans?
Review the requirements for the Android operating system, in particular
reduce the requirements for the version of Android to run the application to 2.0;
Add the ability to track the flow of errors arising when working with php and mysql;
Move the log files on the server and mysql on sdcard;
Extend the additional PHP libraries. For example, pdo_mysql;
Move the database files to MySQL on sdcard.
https://play.google.com/store/apps/details?id=ru.kslabs.ksweb
http://www.kswebserver.ru/
Atjeews android app server, small footprint, biggest advantage for me was jsp support.
I recently installed BitWeb which I recommend highly. I have a rooted phone with lends me a few more options (and I also recommend rooting if you haven't and plan on doing any server tinkering at all)
BitWeb is nice in that it includes a lighttpd server, a stripped down php engine and a stripped down mysql engine giving you a quick and dirty LAMP system with just one app. I use mine in conjunction with an sshd app to gain a busybox shell, I installed nano and use the ssh connection to do an sshfs share to edit content from my pc.
Bitweb includes the ability to tweak the config settings for all three services, and I've even managed to get multiple Zend servers working on just the one little server with a little tweaking to the re-write rules and the application.ini settings.
https://play.google.com/store/apps/details?id=com.andi.serverweb&hl=en
If you want to see some of the config options I had to customize, I can either post them or respond via email with what I set up as well as some comments on the pitfalls I ran into along the way. (I recently posted one as a self-answered thread on here by the way, although it turned out not to be specific to the android platform but with lighttpd/Zend)
I'm just bummed that t-mobile/HTC appears to have no plans to upgrade my phone beyond Gingerbread as I understand some of the new android OS's have ways you can access some of the hardware (such as the cameras) from scripts or compiled code without a fuss. If I want to do it now, I either need to hard code my own interface to them or get a pre-roll app capable of doing it which really tasks my phone when running side-by-side with the web/mysql/php services.
I might be a last to answer this question but believe me, this is the simplest and latest answer in 2020 for those who need to start a webserver in Android and need to serve multiple clients without implementing any other third-party libraries.
Copy your HTML file into the assets folder of Android as server.html and declare the serverSocket as global in your class.
Run the below code inside a new thread.
try {
serverSocket = new ServerSocket(8080);
while (true) {
final Socket socket = serverSocket.accept();
new Thread(new Runnable() {
#Override
public void run() {
try {
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter os = new PrintWriter(socket.getOutputStream(), true);
String request = is.readLine();
Scanner scanner = new Scanner(getAssets().open("server.html"));
String response = scanner.useDelimiter("\\Z").next();
os.print("HTTP/1.0 200" + "\r\n");
os.print("Content type: text/html" + "\r\n");
os.print("Content length: " + response.length() + "\r\n");
os.print("\r\n");
os.print(response + "\r\n");
os.flush();
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}).start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
That's all your native Android Java (no third-party libraries implemented) webserver is live at port 8080.
If you want to use DB and POST requests, try to implement SQLite and WebSocket connections to make two-way communication.
https://developer.android.com/reference/java/net/ServerSocket
Check KSWEB and Bit Web Server,
both using Lighttpd als server, php and support mysql.
i tried KSWEB, it works wonderfull, but i don't know yet how to use the modrewrite.
but, it should be work. you can try the trial version of KSWEB before purchase it.
KSWEB costs a little bit more than Bit Web Server only 0,XX $.
if you decided to buy it, post your experience here... i want to know too... :)
Bit Web Server
KSWEB
Till now I have seen all those applications are paid . And others doesn't have phpmyadmin. And I found finally one. You can have a look at kickweb server.
Android web server PHP/MySQL/PHPMyAdmin
Requirements
Internal memory should not be less than 50MB!
Minimum Android API 9 (GINGERBREAD)!
Features
Lighttpd 1.4.34
PHP 5.5.9
MySQL 5.1.62
MSMTP 1.4.31
phpMyAdmin 4.1.10
Nginx 1.5.11
Default Document Root (htdocs)
Path : /sdcard/htdocs/
Default URL
Address : localhost:8080
phpMyAdmin Informations
Address : localhost:10000
Username : root
Password :
MySQL Informations
Host : localhost
Port : 3306
Username : root
Password :
If you find trouble to make it working, you can see this video : https://youtu.be/3_m3vNGTp74
Yes, it is possible. May be not so complicated as Apache, but possible.
Look at Moto Phone Portal for example, it has web-server in its base. And there were several applications for this purpose in Market.
Servers Ultimate Pro, just 8 pounds.
Include PHPAdmin, MySQL and ton of other servers. I am currently using it as proxy.

Android APK from Rails Server

I've stored my .apk file in my rails server. I've set up a route that redirects a given url to a method that essentially sends the file
in my routes.rb file
match '/myApk.apk' to: 'upgradeapk#index'
Upgradeapk_controller.rb file
def index
#filename = '/myApk/myApk.apk'
#tmpfile = 'upgradedApk.apk'
send_file(#filename, :disposition => 'inline', :stream => true, :type=> 'application/vnd.android.package-archive', :file_name => #tmpfile)
end
When i type my sever url and add '/myApk.apk' it starts the downloading process as long as i do it on my a computer. However if i try to do it on my android device it doesn't work. Checking the download lists in my android device browser i notice that the download "job" for the apk is created, however its in an endless loop changing between states "in queue" and "downloading". Nothing ever downloads.
Do I have to set the send_file differently when it comes to making it work on android devices?
----EDIT------
Ok so i've decided to store the files in a dropbox location instead of storing it in my server. If i pass the url for the file directly in my android function for the http request, it works well. The file is found, downloaded and the installation is prompted.
class UpgradeapkController < ApplicationController
def index
android_apk = Androidaplicacion.first (Model to access the table in which i store the apk dropbox url)
route = android_apk.url
redirect_to route
end
end
I've set up my controller to redirect to the given url for the dropbox file. If i try the url (same as before, using the "match" url) in my android browser, this time it downloads. However, if I try it from the android app, its the same as before, it just doesnt download.
So, the "send_file" method seems to not be working if its on the android platform. redirecting to my dropbox url from the controller works on android but only from a browser, not using the http request on my android app. The only way to get it to work in my android app is if I use the dropbox direct link.
Also, I first thought this was because my server was running on https and the certificate its not a valid one. I found a way to bypass the https certification encryption/certificate validation thing on my android app but it didnt work either (it appeared to have succeed in avoiding the validation) but the results ended up been the same. I then ran an instance of my server using http and still same results.

Downloading files on website to android devices fails

I have an application in which we have files that are being served from a secure encrypted file system to the user. THe files are decrypted on the fly by the application and then pushed to the client through the response header. This works perfectly fine in all browsers and iOS devices, but fails on all androids. It just simply says the download failed.
I have tried many different solutions that have been suggested around for android devices, as they seem to have a lot of problems with files like this. Nothing has seemed to work.
change file extension to be in all caps in the Content-Disposition header
tried multiple content types (application/octet-stream and specific file types)
Below is the actual code writing the response headers.
strMimeType = objDocument.FileMime
If strMimeType = "" Then
strMimeType = "application/octet-stream"
End If
HttpContext.Current.Response.ContentType = strMimeType
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" & objDocument.Filename)
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.WriteFile(Server.MapPath("/FS/CO/" & objDocument.DocumentID & "/" & objDocument.Filename))
HttpContext.Current.Response.Flush()
HttpContext.Current.Response.Close()
HttpContext.Current.Response.End()
this worked for me - adb logcat DownloadManager:I *:S
that shows in the adb logcat only things from the downloadmanager. i am on a samsung galaxy s4 so if you have something different and you probably do you have to find out the name of your download manager by google, or start the log : use "adb logcat" do that, and then download the file then quickly scroll up to stop the adb from printing more stuff, and then find it.
i got this problem:
I/DownloadManager( 9250): Initiating request for download id = 2011 with mAllowedNetworkTypes = -1 forP2Pbit = 8194
W/DownloadManager( 9250): Aborting request for download 2011: http error 403, mContinuingDownload: false FinalStatus = 403
i think it has something to do with my server but my server works just fine. so im not sure why it is breaking

Why would some HTTPS requests fail to decrypt on Fiddler, while some works ?

Scenario: I am trying to debug an Android app by proxying requests through Fiddler.
I got FiddlerRoot certificate installed on the Android device, and the SSL decryption works for most requests, but for other requests I can only see the HTTPS Connect, and nothing else in the Fiddler log. I think it might be image requests over SSL that fails to decrypt.
I have double-checked that "Hide images" is off, etc. Images retrieved are hosted on another domain than the main API the app talks to.
What could cause this behaviour ? And how do I get the image requests to show in Fiddler ?
I am using the latest Fiddler4.
There are plenty of tutorials on how you can intercept HTTP(s) traffic from Android using Fiddler.
Try this one: http://docs.telerik.com/fiddler/configure-fiddler/tasks/configureforandroid
However, it will fail when you try to intercept and decrypt Android SSL traffic coming from an application, and not from a browser.
It might be that the application uses a certificate pinning – and you are probably cannot decipher this connection. Lost cause!
But more probably, the reason is a bug in the HttpsUrlConnection pipeline implementation.
To solve the issue, please proceed with the following steps:
In Fiddler click "Rules->Customize Rules";
Find function OnBeforeResponse in the script
Add following code to the function body:
if (oSession.oRequest["User-Agent"].indexOf("Dalvik") > -1 &&
oSession.HTTPMethodIs("CONNECT")) {
oSession.oResponse.headers["Connection"] = "Keep-Alive";
}
Save the file and restart Fiddler.

Android WebView full page

I am creating an aplication that involves an WebView. The thing is that I want to load the full page and not the mobile one, so I have changed the User Agent. Nevertheless there are pages that loads the mobile version.
Here are two versions of code that I have tried:
1.webview.getSettings().setUserAgentString("Mozila ");
2.
String DESKTOP_USERAGENT = webview.getSettings().getUserAgentString ();
DESKTOP_USERAGENT = DESKTOP_USERAGENT.replace("Mobile ","");
webview.getSettings().setUserAgentString(DESKTOP_USERAGENT);
This are exemples of webpages that loads the mobile version in any cases:
http://www.jurnalul.ro
http://www.androidzoom.com
1.Does anyone knows how I can trick the server and tell him I am using a desktop and not a mobile?
2.How does a website knows that I am using a mobile version?
Thank you very much,
Razvan
The problem may be that if you are using a device that your carrier is routing all your HTTP requests through a proxy, and that the proxy is changing the User-Agent. Check on the other end, with your own server, using nc -l 80 -vvv that your request is indeed sending the User-Agent that you have modified.
EDIT: Some specific troubleshooting steps
Forward a port 9090 on your router to your desktop machine or laptop.
Download netcat
Run netcat with the command "nc -l 9090 -vvv"
In your Android application's WebView, make an HTTP request with the User-Agent you are injecting to http://your.ip.address:9090
In the terminal you ran netcat, you will see the HTTP request dump in plain text. There you can check the HTTP header User-Agent to see if it has been changed by a proxy server or not.
You cannot test this stuff with Wireshark or Fiddler because it is happening in the WAN. You need to test it on the receiving end, either on a server, or on your own desktop machine.
webview.getSettings().setUserAgent(1);//for desktop 1 or mobil 0.

Categories

Resources