Net Communications on iphone device

100 views
Skip to first unread message

Dennis Rogers

unread,
Mar 6, 2021, 4:24:53 PM3/6/21
to CodenameOne Discussions
I have the following code that I use to send an email and password to my server. It works fine on the simulator but fails on an actual iphone (I receive a blank email and password):

try {
    URL url = new URL("server address");
    link = url.openConnection();
    link.setDoOutput(true);
    link.setDoInput(true);
} catch(URISyntaxException e) {
    Log.p("URL error");
    Log.e(e);
}
// Get buffered output stream
os = link.getOutputStream();
BufferedOutputStream bout = new BufferedOutputStream(os);
// Send email and hashed Password
bout.write((nemail + "\n").getBytes());
pwHash = getHash(nemail + npasswd);
bout.write((pwHash + "\n").getBytes());
bout.flush();

Thanks, Dennis

Shai Almog

unread,
Mar 6, 2021, 9:32:02 PM3/6/21
to CodenameOne Discussions
Are you using com.codenameone.io.URL ?
I would recommend avoiding BufferedOutputStream in Codename One as all streams are buffered by default in Codename One.
You also need to fetch the result for the request to finish. It won't happen until you try to get a response from the server.

I would recommend using APIs like the "Rest" API which is simpler to use and doesn't require threading.

Dennis Rogers

unread,
Mar 7, 2021, 11:46:23 AM3/7/21
to CodenameOne Discussions
Sorry but I'm still having problems. I tried using unbuffered IO but with the same result (works on the simulator but not on the device). Also the code I sent you was followed by:

// Get buffered Input stream

is = link.getInputStream();
BufferedInputStream binp = new BufferedInputStream(is);
// Get reply
String ans = readLine(binp);

which I think would qualify as asking for a response from the server. BTW this is all being done on a separate thread.

I'm learning about the REST protocol but think this should work.

-Dennis

Dennis Rogers

unread,
Mar 7, 2021, 12:13:46 PM3/7/21
to CodenameOne Discussions
Yes I'm using codename1.io.URL.

Shai Almog

unread,
Mar 7, 2021, 9:42:05 PM3/7/21
to CodenameOne Discussions
I meant the Rest class.

Sorry I neglected to ask something basic. Is the URL HTTPS?
If not iOS will fail by default. You can use this as a workaround: https://www.codenameone.com/blog/ios-http-urls.html

Dennis Rogers

unread,
Mar 8, 2021, 1:35:52 PM3/8/21
to CodenameOne Discussions
Yes, the site is https. To make sure, I tested it using the Qualys ssl checker and I access it with the https:// prefix.

--Dennis

Shai Almog

unread,
Mar 8, 2021, 9:51:04 PM3/8/21
to CodenameOne Discussions
With valid (not self signed) certificate?
Is it a publicly visible IP accessible from the device?

Dennis Rogers

unread,
Mar 9, 2021, 8:31:25 AM3/9/21
to CodenameOne Discussions
I'm able to access all the websites on that IP from the device. I also tried accessing the reply from the server without the BufferedInputStream with no luck.

The certificate I used was one I bought from bluehost.com who hosts my server.

Shai Almog

unread,
Mar 9, 2021, 10:23:18 PM3/9/21
to CodenameOne Discussions
Can you include the full code after removing the buffers?
Also try replacing flush() with close(). That might help.

Dennis Rogers

unread,
Mar 10, 2021, 10:09:18 AM3/10/21
to CodenameOne Discussions
Replacing flush() with close() didn't make a difference. Here's the code I used without the buffer:

os = link.getOutputStream();
os.write((nemail + "\n").getBytes());
pwHash = getHash(nemail + npasswd);
os.write((pwHash + "\n").getBytes());
os.close();

is = link.getInputStream();
String ans = readLine(is);

static String readLine(InputStream stream) {
    byte[] b = new byte[80];
    String s = "";
    int i = 0;
    try {
        b[i] = (byte) stream.read();
        while((b[i] != 10 && (b[i] != 13))) {
            i++;
            b[i] = (byte) stream.read();
        }
        b[i] = 0;
       return new String(b,0,i);
    } catch(IOException e) {
        Log.e(e);
        return null:

Shai Almog

unread,
Mar 10, 2021, 10:28:42 PM3/10/21
to CodenameOne Discussions
Try using String ans = Util.readToString(); which might be better.
Is the code still working on the simulator after the changes?
Is it working on Android?

Dennis Rogers

unread,
Mar 12, 2021, 3:57:24 PM3/12/21
to CodenameOne Discussions
I switched to using Util.readToString() and still no joy on the iphone device.
The code still works ok on the simulator and on also on a real Android device.

Shai Almog

unread,
Mar 12, 2021, 11:45:51 PM3/12/21
to CodenameOne Discussions
Interesting, can you expose the server URL so we can run this test case and see?

Dennis Rogers

unread,
Mar 13, 2021, 7:59:16 AM3/13/21
to CodenameOne Discussions
The server URL is https://www.symdesigns.com. I have a web page at symdesigns.com/ShoppingGenie/index.html and the server php is /symdesigns.com/php/export.php .

Shai Almog

unread,
Mar 13, 2021, 10:03:59 PM3/13/21
to CodenameOne Discussions
Thanks, is it possible to create a dummy username/password combo with no permissions so we can test this?

Dennis Rogers

unread,
Mar 14, 2021, 11:12:37 AM3/14/21
to CodenameOne Discussions
Sure, You can use "te...@x.com" for the email (user id) and "pw2" as the password.

Dennis Rogers

unread,
Mar 14, 2021, 11:18:47 AM3/14/21
to CodenameOne Discussions
I forgot to tell you. The password "pw2" is hashed to "f47ba92cf7".

Shai Almog

unread,
Mar 14, 2021, 10:08:01 PM3/14/21
to CodenameOne Discussions
Thanks!
I'm trying to reproduce it and noticed I'm still missing the code of getHash.

Dennis Rogers

unread,
Mar 15, 2021, 10:04:23 AM3/15/21
to CodenameOne Discussions
"f47ba92cf7" is the hashed password i.e.

"f47ba92cf7" = getHash("test2.xcom"+"pw2")

The following is the getHash code I'm using:

static String getHash(String str) {
return dumpBytes(MD5.computeMD5(str.getBytes())).substring(0,10);
}
public static String dumpBytes(byte[] buffer) {
if (buffer == null) {
return "";
}
StringBuilder sb = new StringBuilder();
sb.setLength(0);
for (int i = 0; i < buffer.length; i++) {
sb.append((char) (HEX_CHAR[(buffer[i] & 0x00F0) >> 4]))
.append((char) (HEX_CHAR[buffer[i] & 0x000F]));
}
return sb.toString();
}

BTW What time zone are you in?

-Dennis

Shai Almog

unread,
Mar 15, 2021, 10:40:12 PM3/15/21
to CodenameOne Discussions
I ran this test case but I'm getting an error from the server in the "success" dialog:

Form hi = new Form("Hi World", BoxLayout.y());
Button test = new Button("Test");
hi.add(test);
test.addActionListener(e -> {
   try {
     URL url = new URL("https://symdesigns.com/symdesigns.com/php/export.php");
     URL.URLConnection link = url.openConnection();
     link.setDoOutput(true);
     link.setDoInput(true);
     OutputStream os = link.getOutputStream();
     os.write(("te...@x.com\n").getBytes());
     os.write(("f47ba92cf7\n").getBytes());
     os.close();

     InputStream is = link.getInputStream();
     String ans = Util.readToString(is);

     Dialog.show("Success", ans, "OK", null);
   } catch(Exception err) {
     Dialog.show("Error", err.toString(), "OK", null);
     Log.p("URL error");
     Log.e(err);
   }
});

hi.show();

Dennis Rogers

unread,
Mar 16, 2021, 5:13:30 PM3/16/21
to CodenameOne Discussions
The URL is wrong. It should be: "https://symdesigns.com/php/export.php". 
With that change your test code seems to work ok on the simulator (returns ok) but
on the device it doesn't (returns nok); When I look at the server logs it still seems to receive 
a blank email and password when run from the device.

Dennis Rogers

unread,
Mar 16, 2021, 5:37:29 PM3/16/21
to CodenameOne Discussions

BTW, It seems to work ok on the android device.

Shai Almog

unread,
Mar 16, 2021, 11:03:16 PM3/16/21
to CodenameOne Discussions
I'll look into it. It works in the simulator but I have a couple of issues with my environment so it will take me. a couple of days to reproduce it on a device.

Dennis Rogers

unread,
Mar 17, 2021, 1:28:48 AM3/17/21
to CodenameOne Discussions
No problem!

Shai Almog

unread,
Mar 17, 2021, 11:05:55 PM3/17/21
to CodenameOne Discussions
I was able to run it and got a NOK from the server. The question is what did the server get?
Can your server deal with chunked requests?
gzip?

Dennis Rogers

unread,
Mar 18, 2021, 2:44:52 PM3/18/21
to CodenameOne Discussions

The server received empty strings for the email and the password from the iphone device (but it received the correct strings from the simulator and the android device). This is very frustrating!

I'm not sure what you mean by "chunked requests". Do you mean requests that have been gziped?

Steve Hannah

unread,
Mar 18, 2021, 4:02:12 PM3/18/21
to codenameone...@googlegroups.com
I just tried building the test:

Form hi = new Form("Hi World", BoxLayout.y());
Button test = new Button("Test");
hi.add(test);
test.addActionListener(e -> {
try {

URL.URLConnection link = url.openConnection();
link.setDoOutput(true);
link.setDoInput(true);
OutputStream os = link.getOutputStream();
os.write(("te...@x.com\n").getBytes());
os.write(("f47ba92cf7\n").getBytes());
os.close();

InputStream is = link.getInputStream();
String ans = Util.readToString(is);

Dialog.show("Success", ans, "OK", null);
} catch(Exception err) {
Dialog.show("Error", err.toString(), "OK", null);
Log.p("URL error");
Log.e(err);
}
});

hi.show();

Codename One Simulator:  Passed
Xcode Simulator (running iPhone 6 - iOS 12.1) : Passed
iPhone 5 - iOS 10.3.3 (actual device) : Passed

By "Passed", I mean I get a dialog that says "Success" in the title and "Nok" in the body.



--
You received this message because you are subscribed to the Google Groups "CodenameOne Discussions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to codenameone-discu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/codenameone-discussions/392fb9f1-3c1d-448e-ab79-447a9e30cbc4n%40googlegroups.com.


--
Steve Hannah
Software Developer
Codename One

Dennis Rogers

unread,
Mar 19, 2021, 12:06:02 PM3/19/21
to CodenameOne Discussions
Thanks for trying the test code. "Success" is just the name of the dialog. "nok" means that the credentials were not correct. Actually, from the server logs, it appears to have received a blank email and password.

Dennis Rogers

unread,
Mar 19, 2021, 12:14:17 PM3/19/21
to CodenameOne Discussions
I don't know if this helps but here's the php server code that reads the credentials

$std = fopen("php://input","r");
if($std==false) logError("Can't open input");
$ln1 = fgets($std);
$reply = sscanf(str_replace(" ","",$ln1),"%s");
$email = trim($reply[0],"\n");
logError(sprintf("line 1 = %s, email = %s",$ln1,$email));
$ln2 = fgets($std);
$reply = sscanf(str_replace(" ","",$ln2),"%s");
$passwd = trim($reply[0],"\n");
logError(sprintf("line 2 = %s, passwd = %s",$ln2,$passwd));

When running on the iphone the strings $ln1,$email, $ln2, and $passwd are blank. I 'm able to view the output from the logError function.
-Dennis

Steve Hannah

unread,
Mar 19, 2021, 12:35:35 PM3/19/21
to codenameone...@googlegroups.com
Have you tried setting the request method to POST?

URL.HttpURLConnection link = (URL.HttpURLConnection)url.openConnection();
link.setRequestMethod("POST");
...


Dennis Rogers

unread,
Mar 20, 2021, 10:29:50 AM3/20/21
to CodenameOne Discussions
Many thanks to you guys for all the help. Using the POST method seems to have solved the problem. -Dennis
Reply all
Reply to author
Forward
0 new messages