I want to implement a basic authentication using an Android Client and a Glassfish 4.1.1 Server (communicating through REST-Service).
The Service is working quite well (proven by POSTMAN and another C#-Client) but on Android, it's driven me crazy by now.
It also appears that the object-to-send is received as 'null' on the server side, also an annoying "EOFException" is thrown on the Android Side.
Server side (works fine)
#POST
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public Account validate(Account acc)
{
Account a = null;
a = Database.getInstance().getAccountByUserPw(acc);
return a;
}
Android Client:
public Account postData(String JSONtoSend)
{
URL url;
Account get = new Account();
try {
url = new URL("http://192.xxx.xxx.x:18080/HolidayOutServer/webresources/validateacc");
HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
urlCon.setRequestMethod("POST");
urlCon.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
urlCon.setRequestProperty("Accept", "application/json; charset=UTF-8");
urlCon.setDoOutput(true); // to be able to write.
urlCon.setDoInput(true); // to be able to read.
OutputStreamWriter out = new OutputStreamWriter(urlCon.getOutputStream());
out.write(JSONtoSend);
ObjectInputStream ois = new ObjectInputStream(urlCon.getInputStream());
get = (Account) ois.readObject();
return get;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return get;
}
which is called within this:
class help extends AsyncTask<String, Void, Account>
{
#Override
protected Account doInBackground(String... params) {
return postData(new Gson().toJson(new Account("aleqs", "lexx", -2)));
}
}
Problems in a nutshell:
Jersey Server receives null
Android throws this ridiculous EOFException.
Can somebody help ?
Thanks in advance,
John.
Ok, I managed to find a solution here after hours.
This code works for me:
try( DataOutputStream wr = new DataOutputStream( urlCon.getOutputStream())) {
wr.write(new Gson().toJson(new Account("aleqs", "lexx", -2)).getBytes());
}
Reader in = new BufferedReader(new InputStreamReader(urlCon.getInputStream(), "UTF-8"));
StringBuilder sb = new StringBuilder();
for (int c; (c = in.read()) >= 0;)
sb.append((char)c);
response = sb.toString();
return response;
} catch (IOException e) {
e.printStackTrace();
}
return response;
Change the return type of "donInBackGround" to String and let the helper class extend -String, Void, String-.
MOST IMPORTANT: CHECK IF YOUR ATTRIBUTES ON CLIENT SIDE (eg. id, name, ..) match with those from SERVER SIDE.
Consider cap locks and so on..
Cheers !
I am developing an android app where user logs on to his/her account. After logging in I will receive XSRF token and Laravel Session Id to recognise the specific user. I have to send these tokens for every request I send to the API's to get the appropriate information. But when I am sending the required details as shown in the image, I am getting HTMl file as response instead of getting JSON Object. I was seriously stuck at this problem. Correct Solution may take forward the whole app.
class RegisterConnection extends AsyncTask<String,String,JSONObject> {
protected JSONObject doInBackground(String... arg0) {
JSONObject output = new JSONObject();
DefaultHttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 5000); //Timeout Limit
HttpResponse response = null;
try {
HttpGet get = new HttpGet(statsURL);
get.setHeader("Accept", "application/json");
CookieStore store = new BasicCookieStore();
BasicClientCookie cookie1 = new BasicClientCookie("XSRF-TOKEN", XSRF);
BasicClientCookie cookie2 = new BasicClientCookie("laravel_session", laravel);
store.addCookie(cookie1);
store.addCookie(cookie2);
client.setCookieStore(store);
response = client.execute(get);
if(response!=null){
InputStream in = response.getEntity().getContent();
String resultstring = Utilities.convertStreamToString(in);
Log.i("Result1", resultstring);
output = new JSONObject(resultstring);
Log.i("Result2", output.toString());
}
} catch(Exception e) {
e.printStackTrace();
try {
output.put("sai","error");
Log.i("MainActivity", output.toString());
} catch (JSONException e1) {
e1.printStackTrace();
}
return output;
}
return output;
}
These are the server requirements
http://imgur.com/OY9Q673
This is the Output received
http://imgur.com/IB5AEcT
As far as I can tell, there is nothing wrong with your Android client code.
You are getting HTML from the server so the main reason could be that your Laravel server is rendering the views and sending you back html instead of JSON. Instead of rendering the views on the server, you should send JSON response on your Laravel server side.
Add Jsoup dependency in your gradle file
implementation 'org.jsoup:jsoup:1.11.2'
Document document = Jsoup.parse("http://imgur.com/IB5AEcT");
Elements el = doc.select("button");
Log.i("..........",""+el.attr("data-invite-details"));
Jsoup tutorial
http://jsoup.org/apidocs/org/jsoup/Jsoup.html
Is there a way to send android local HTML forms via ajax to remote php server? (local means the files are in my device) My scenario is this: In my app, I have an html files in my android device and is loaded in a webview, i also have the javascript file in my device. What i want to do is to send the html forms data to a remote server. In my current situation, its not sending any data, I've check the javascript and php and the code is fine, and it's working on iOS version of the app. I've tried other workarounds and what I've observed is that, when i load html file in webview using local files (e.g. webview.loadUrl("file://"+ Environment.getExternalStorageDirectory()+"/android_asset/list.html"), the android is looking for all other related files (e.g. formsprocessor.php) locally, though in javascript/ajax all necessary arguments in it's functions are supplied properly. The errors i've encountered are: FileNotFound: content://packagename.com/formsprocessor.php & Unknown chronium error: -6.
Is there a way or what is the best way to do this?
Thanks, Clint.
This solve my problem:
Used a javascripthandler, and in my javascript i call the function from the handler. So basically, the android handled the upload of data to server using httppost. Here's the codes;
the handler:
final class IJavascriptHandler{
IJavascriptHandler(){}
public void sendJSONToAndroid(String text){
if(!Config.canConnect((ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE), home) && dialogNoConnFlag == false) {
dialogNoConnFlag = true;
Config.notificationMsg(Config.ERRORNOCONN,home, Config.TITLE1 + " " + Config.TITLE6);
return;
}
try {
Log.v("SendToServer","Send JSON to Server");
String url = "";
JSONObject json_data = new JSONObject(text);
JSONArray names= json_data.names();
JSONArray values = json_data.toJSONArray(names);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
for(int i = 0 ; i < values.length(); i++){
Log.v("Good",names.getString(i).toString());
if(names.getString(i).equals("url")) {
url = json_data.getString(names.getString(i)).toString();
}
nameValuePairs.add(new BasicNameValuePair( names.getString(i).toString(), json_data.getString(names.getString(i)).toString()));
}
Config.uploadToServer(nameValuePairs, url);
}
catch (JSONException e)
{
Config.notificationMsg(Config.ERRORMSG + e.getMessage(), (Activity) home, Config.TITLE1 + " " + Config.TITLE6);
}
}
}
the httppost:
public static String uploadToServer(List<NameValuePair> nameValuePairs, String url){
if(Session.isordinaryHost)
{
httpclient = new DefaultHttpClient();
}
else
{
httpclient = new MyHttpClient().getNewHttpClient();
((AbstractHttpClient) httpclient).getCredentialsProvider().setCredentials(
new AuthScope(Session.siteIp, 443),
new UsernamePasswordCredentials(Session.siteUsername, Session.sitePassword));
}
httppost = new HttpPost(url);
try
{
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
EntityUtils.toString(entity);
}
catch (ClientProtocolException e)
{
return e.getMessage();
}
catch (IOException e)
{
return e.getMessage();
}
return null;
}
the javascript:
function CheckCompleteRecords() {
DB.transaction(function(tx) {
tx.executeSql(SelectCompleteForUploadStatement, [], function(tx, result) {
Dataset = result.rows;
for (var i = 0, item = null; i < Dataset.length; i++) {
item = Dataset.item(i);
var a = createJSON(item['FormName'],item['UserID'],item['Image1'],item['Image2'],item['Image3'],item['Image4'],item['Image5'],item['Field1'],item['Field2'],item['Field3'],item['Field4'],item['Field5'],item['Field6'],item['Field7'],item['Field8'],item['Field9'],item['Field10'],item['Field11'],item['Field12'],item['Field13'],item['Field14'],item['Field15'],item['Field16'],item['Field17'],item['Field18'],item['Field19'],item['Field20'],item['Field21'],item['Field22'],item['Field23'],item['Field24'],item['Field25'],item['Field26'],item['Field27'],item['Field28'],item['Field29'],item['Field30'],item['Field31'],item['Field32'],item['Field33'],item['Field34'],item['Field35'],item['Field36'],item['Field37'],item['Field38'],item['Field39'],item['Field40'],item['Field41'],item['Field42'],item['Field43'],item['Field44'],item['Field45'],item['Field46'],item['Field47'],item['Field48'],item['Field49'],item['Field50'],item['Field51'],item['Field52'],item['Field53'],item['Field54'],item['Field55'],item['Field56'],item['Field57'],item['Field58'],item['Field59'],item['Field60'],item['Field61'],item['Field62'],item['Field63'],item['Field64'],item['Field65'],item['Field66'],item['Field67'],item['Field68'],item['Field69'],item['Field70'],item['Field71'],item['Field72'],item['Field73'],item['Field74'],item['Field75'],item['Field76'],item['Field77'],item['Field78'],item['Field79'],item['Field80'],item['Field81'],item['Field82'],item['Field83'],item['Field84'],item['Field85'],item['Field86'],item['Field87'],item['Field88'],item['Field89'],item['Field90'],item['Field91'],item['Field92'],item['Field93'],item['Field94'],item['Field95'],item['Field96'],item['Field97'],item['Field98'],item['Field99'],item['Field100'],item['CurrentDateTime'],item['Geolocation'],item['BarCode']);
window.cpjs.sendJSONToAndroid(a);
showStuff('SendServerBtn');
window.location = "senttoserver://app_action";
}
});
});
}
I have an Android app that successfully uses RequestFactory to manipulate Entities in AppEngine Datastore.
In my AppEngine service, I want to use
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
to get information about the current Android user, but getCurrentUser() returns null.
How does my Android app let RequestFactory know who is logged in?
This question applies to dev mode and production mode.
Thanks.
There is a not-so-obvious answer found in the old AppEngine Connected Android Eclipse wizard code, which is no longer available in the GPE (see Util.java of this wizard generated code). It includes the following:
T requestFactory = RequestFactorySource.create(factoryClass);
requestFactory.initialize(new SimpleEventBus(),
new AndroidRequestTransport(uri, authCookie));
with
public AndroidRequestTransport(URI uri, String cookie) {
this.uri = uri;
this.cookie = cookie;
}
public void send(String payload, TransportReceiver receiver) {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost();
post.setHeader("Content-Type", "application/json;charset=UTF-8");
post.setHeader("Cookie", cookie);
post.setURI(uri);
Throwable ex;
try {
post.setEntity(new StringEntity(payload, "UTF-8"));
HttpResponse response = client.execute(post);
if (200 == response.getStatusLine().getStatusCode()) {
String contents = readStreamAsString(response.getEntity().getContent());
receiver.onTransportSuccess(contents);
} else {
receiver.onTransportFailure(new ServerFailure(response.getStatusLine()
.getReasonPhrase()));
}
return;
} catch (UnsupportedEncodingException e) {
ex = e;
} catch (ClientProtocolException e) {
ex = e;
} catch (IOException e) {
ex = e;
}
receiver.onTransportFailure(new ServerFailure(ex.getMessage()));
}
Using that code from the GPE wizard did the trick for me.
I have big problems with getting the certificates running under android.
I have an android client which connects to a WCF-Service.
I think the problem is, that the certificates are not transfered. I get an error message:
403 forbidden (in the response). I really hope you can help me.
=> in my android client
In internet explorer, it works just fine => status 200
I found this article:
http://android-developers.blogspot.de/2012/03/unifying-key-store-access-in-ics.html
"A common use of the private key is for SSL client authentication. This can be implemented by using an HttpsURLConnection with a custom X509KeyManager that returns the PrivateKey retrieved from the KeyChain API. The open source Email application for ICS uses KeyChain with an X509ExtendedKeyManager. To learn more, have a look at the source code (in SSLUtils.java)."
I have checked out the SSLUtils class and I am trying to use it.
Here is some code:
private void setHttpsAdvanced() {
HostAuth ht = new HostAuth();
ht.mPort = 443;
ht.mClientCertAlias = "jensZert";
HttpParams params = getHttpParams();
MyThreadSafeClientConnManager ccm = MyThreadSafeClientConnManager
.newInstance(params, true, 443);
try {
MyThreadSafeClientConnManager.makeScheme(true, false,
ht.mClientCertAlias);
ccm.registerClientCert(getApplicationContext(), ht);
// checkCertificate(ht.mClientCertAlias);
} catch (CertificateException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
}
this.httpclient = new DefaultHttpClient(ccm, params);
connectionInfo = this.getConnectionInfo();
this.url = String.format("%1$s://%2$s/%3$s/%4$s",
connectionInfo.Protocol, connectionInfo.ServerName,
connectionInfo.WebserviceName, connectionInfo.Path);
httpGet = new HttpGet(url);
}
private String callTheWebserviceCertificate() {
this.setupClient();
String result = "";
HttpResponse response = null;
try {
response = (HttpResponse) this.httpclient.execute(httpGet);
result = EntityUtils.toString(response.getEntity());
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
result = e.getMessage() + "\n";
for (StackTraceElement el : e.getStackTrace()) {
result += el.toString() + "\n";
}
Log.d(TAG, result);
}
return result;
}
greetings,
jens