Codename One - Can't read from socket on real device - ios

I'm developing an iOS app, using Codename One. I extended the SocketConnection class, in order to receive data from a server.
class CustomSocketConnection extends SocketConnection {
private OutputStream os;
private InputStream is;
private InputStreamReader isr;
private String rawMessage;
public CustomSocketConnection(){
os = null;
is = null;
isr = null;
rawMessage = null;
}
public synchronized String getRawMessage(){
return rawMessage;
}
#Override
public void connectionError(int errorCode, String message) {
rawMessage = null;
ToastBar.showErrorMessage("Error Connecting. ErrorCode: " + errorCode + " Message: " + message);
System.out.println(">>>CustomSocketConnection, connectionError. Error Connecting. ErrorCode: " + errorCode + " Message: " + message);
}
#Override
public void connectionEstablished(InputStream is, OutputStream os) {
System.out.println(">>>CustomSocketConnection, connectionEstablished");
char termination = '\n';
int length = 1024;
char[] buffer = new char[length];
byte[] bufferByte = new byte[length];
StringBuilder stringBuilder = new StringBuilder();
System.out.println(">>>CustomSocketConnection, connectionEstablished, prima del while");
try {
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
System.out.println(">>>CustomSocketConnection, connectionEstablished, prima della read");
while(true){
System.out.println(">>>CustomSocketConnection, loop di read, inizio");
int read = isr.read();
System.out.println(">>>CustomSocketConnection, loop di read, subito dopo la read");
char c = (char) read;
if (read == -1) rawMessage = null;
System.out.println(">>>CustomSocketConnection, loop di read, letto: " + c);
while(c != termination){
stringBuilder.append(c);
read = isr.read();
c = (char) read;
if (read == -1) rawMessage = null;
}
rawMessage = stringBuilder.toString();
if(rawMessage != null) doActions(rawMessage);
//System.out.println(">>>CustomSocketConnection, connectionEstablished, ho letto: " + rawMessage + "FINE");
}
}
catch (IOException ex) {
System.out.println(">>>CustomSocketConnection, connectionEstablished, errore: " + ex.getMessage());
}
System.out.println(">>>CustomSocketConnection, connectionEstablished, dopo il while");
}
private void doActions(String msg){
//do something
}
}
In the connectionEstablished method, I read data from server, using the read method of the InputStreamReader class.
If I run the app on the simulator, it works properly and it receives data from server. When I launch the app on real devices (iPad mini, 32-bit device, iOS version 8.1.1 12B435, more details here; iPhone 7s, 64-bit device, iOS version 11.2.5 15D60), the read method doesn't receive data from server. In fact, I can see the string printed by the println before the read method, but I can't see the string printed by the println after the read method.
The issue is not server-side, because I developed an Android app and it receive data from the same server. There aren't firewall restrictions or other network limitations: Android app and the Codename One simulator both receive data when connected on the same local network of the server or from another one.
What's wrong?

Solved using InputStream instead of InputStreamReader.
#Override
public void connectionEstablished(InputStream is, OutputStream os) {
System.out.println(">>>CustomSocketConnection, connectionEstablished");
char termination = '\n';
StringBuilder stringBuilder = new StringBuilder();
System.out.println(">>>CustomSocketConnection, connectionEstablished, prima del while");
try {
System.out.println(">>>CustomSocketConnection, connectionEstablished, prima della read");
while(true){
System.out.println(">>>CustomSocketConnection, loop di read, inizio");
int read = is.read();
System.out.println(">>>CustomSocketConnection, loop di read, subito dopo la read");
char c = (char) read;
if (read == -1) rawMessage = null;
System.out.println(">>>CustomSocketConnection, loop di read, letto: " + c);
while(c != termination){
stringBuilder.append(c);
read = is.read();
c = (char) read;
if (read == -1) rawMessage = null;
}
rawMessage = stringBuilder.toString();
if(rawMessage != null) doActions(rawMessage);
//System.out.println(">>>CustomSocketConnection, connectionEstablished, ho letto: " + rawMessage + "FINE");
}
}
catch (IOException ex) {
System.out.println(">>>CustomSocketConnection, connectionEstablished, errore: " + ex.getMessage());
}
System.out.println(">>>CustomSocketConnection, connectionEstablished, dopo il while");
}
Can anyone explain me why it's working with InputStream?

Related

How to reduce memory when loading image from website?

I am using this Utility
public class Util_ImageLoader {
public static Bitmap _bmap;
Util_ImageLoader(String url) {
HttpConnection connection = null;
InputStream inputStream = null;
EncodedImage bitmap;
byte[] dataArray = null;
try {
connection = (HttpConnection) Connector.open(url + Util_GetInternet.getConnParam(), Connector.READ,
true);
inputStream = connection.openInputStream();
byte[] responseData = new byte[10000];
int length = 0;
StringBuffer rawResponse = new StringBuffer();
while (-1 != (length = inputStream.read(responseData))) {
rawResponse.append(new String(responseData, 0, length));
}
int responseCode = connection.getResponseCode();
if (responseCode != HttpConnection.HTTP_OK) {
throw new IOException("HTTP response code: " + responseCode);
}
final String result = rawResponse.toString();
dataArray = result.getBytes();
} catch (final Exception ex) {
}
finally {
try {
inputStream.close();
inputStream = null;
connection.close();
connection = null;
} catch (Exception e) {
}
}
bitmap = EncodedImage
.createEncodedImage(dataArray, 0, dataArray.length);
int multH;
int multW;
int currHeight = bitmap.getHeight();
int currWidth = bitmap.getWidth();
multH = Fixed32.div(Fixed32.toFP(currHeight), Fixed32.toFP(currHeight));// height
multW = Fixed32.div(Fixed32.toFP(currWidth), Fixed32.toFP(currWidth));// width
bitmap = bitmap.scaleImage32(multW, multH);
_bmap = bitmap.getBitmap();
}
public Bitmap getbitmap() {
return _bmap;
}
}
When I call it in a listfield which contains 10 childs, then the log keeps saying failed to allocate timer 0: no slots left.
This means the memory is being used up and no more memory to allocate again and as a result my main screen cannot start.
At the same time you have the following objects in memory:
// A buffer of about 10KB
byte[] responseData = new byte[10000];
// A string buffer which will grow up to the total response size
rawResponse.append(new String(responseData, 0, length));
// Another string the same length that string buffer
final String result = rawResponse.toString();
// Now another buffer the same size of the response.
dataArray = result.getBytes();
It total, if you downloaded n ascii chars, you have simultaneously 10KB, plus 2*n bytes in the first unicode string buffer, plus 2*n bytes in the result string, plus n bytes in dataArray. If I'm not wrong, that sums up to 5n + 10k. There's room for optimization.
Some improvements would be:
Check response code first, and then read the stream if response code is HTTP 200. No need to read if server returned an error.
Get rid of strings. No need to convert to string if after that you are converting again to bytes.
If images are large, don't store them in RAM while downloading. Instead, open a FileOutputStream and write to a temporary file as you read from input stream. Then, if temporary images are still large enough to be displayed, downscale them.

Internet issue in blackberry

I am developing a blackberry app for sending messages through internet . i have succesfully completed the project, but now i am getting error "to check the net connection even if the net connection is available.
I have closed my http connection .but still the issue persist .
Sometimes it works alright but after somtime it throws the error ".
In one word it is not getting the internet connection .
Please help me.
this is my code
InputStream in=null;
int rc=0;
HttpConnection http=null;
ConnectionFactory factory = new ConnectionFactory();
try{
String u="my url goes here";deviceside=true";
ConnectionDescriptor descriptor = factory.getConnection(u);
http = (HttpConnection)descriptor.getConnection();
in = http.openDataInputStream();
rc = http.getResponseCode();
if (rc != HttpConnection.HTTP_OK) {
Dialog.inform("Please Check The Internet Connection ");
}
int ch;
while ( (ch = in.read())!= -1){
buff3.append( (char) ch);
}
Dialog.inform(" Your Balance Is \n " +buff3.toString() );
buff3.delete(0,buff3.toString().length());
// buff3=new StringBuffer();
//stringItem.setText(" Your Balance Is \n " +buff.toString());
}
catch(Exception o){
Dialog.inform("Please Check The Internet Connection ");
buff3.delete(0,buff3.toString().length());
}
finally
{
try {
if(in != null)
in.close();
if(http != null)
http.close();
buff3.delete(0,buff3.toString().length());
} catch (IOException ex) {
ex.printStackTrace();
}
}

Unexpected response code:403 when calling image in Blackberry

Right now i am working on Image download from web.For this i set http connection like below code.
HttpConnection connection = (HttpConnection) Connector.open(url, Connector.READ_WRITE);
connection.setRequestMethod(HttpConnection.POST);
I am calling two images from web.for one picture it display image successfully.But for other picture it show error Unexpected response code:403.I am not understand why this problem is occur.How can i download image from web.Is there any change in HttpConnection need to modify.
Please help me.
Have you tested this on a real phone, or just in the emulator?
If you are using the emulator, make sure you've configured it to connect to the internet, it won't be configured to do that by default.
BlackBerry emulator not connecting to internet
Use this function , as we get bytes from the http connection,you need to convert those bytes into image this function will do that for you , just pass the url of the image in arguments:
public static Bitmap connectServerForImage(String url) {
HttpConnection httpConnection = null;
DataOutputStream httpDataOutput = null;
InputStream httpInput = null;
int rc;
Bitmap bitmp = null;
try {
httpConnection = (HttpConnection) Connector.open(url);
rc = httpConnection.getResponseCode();
if (rc != HttpConnection.HTTP_OK) {
throw new IOException("HTTP response code: " + rc);
}
httpInput = httpConnection.openInputStream();
InputStream inp = httpInput;
byte[] b = IOUtilities.streamToBytes(inp);
EncodedImage hai = EncodedImage.createEncodedImage(b, 0, b.length);
int currentWidthFixed32 = Fixed32.toFP(hai.getWidth());
int currentHeightFixed32 = Fixed32.toFP(hai.getHeight());
int reqWidth = 48;
int reqHeight = 35;
int requiredWidthFixed32 = Fixed32.toFP(reqWidth);
int requiredHeightFixed32 = Fixed32.toFP(reqHeight);
int scaleXFixed32 = Fixed32.div(currentWidthFixed32, requiredWidthFixed32);
int scaleYFixed32 = Fixed32.div(currentHeightFixed32, requiredHeightFixed32);
hai = hai.scaleImage32(scaleXFixed32, scaleYFixed32);
return hai.getBitmap();
} catch (Exception ex) {
System.out.println("URL Bitmap Error........" +url+ ex.getMessage());
} finally {
try {
if (httpInput != null)
httpInput.close();
if (httpDataOutput != null)
httpDataOutput.close();
if (httpConnection != null)
httpConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmp;
}

Connection Closed When trying to post over 1.5K of url encoded data on 8900, and maybe others

From the simulator, this all works.
I'm using wifi on the device as i'm assuming it's the most stable.
The problem occurs when i try to post more than 1.5K of urlencoded data.
If i send less then it's fine.
It seems to hang the .flush command();
It works on a physical 9700, so i'm presuming that it's possibly device specific
In the example below i'm using form variables, but i've also tried posting the content type json, but still had the same issue
I've written a small testapp, and using the main thread so i know that it's not threads getting confused
If anyone has any ideas that would be great.
private String PostEventsTest()
{
String returnValue = "Error";
HttpConnection hc = null;
DataInputStream dis = null;
DataOutputStream dos = null;
StringBuffer messagebuffer = new StringBuffer();
URLEncodedPostData postValuePairs;
try
{
postValuePairs = new URLEncodedPostData(null, false);
postValuePairs.append("DATA",postData);// postData);
hc = (HttpConnection) Connector.open(postURL, Connector.READ_WRITE);
hc.setRequestMethod(HttpConnection.POST);
hc.setRequestProperty("User-Agent", "BlackBerry");
hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
hc.setRequestProperty("Content-Length", Integer.toString(postValuePairs.getBytes().length));
//hc.setRequestProperty("Content-Length", Integer.toString(postData.length()));
dos = hc.openDataOutputStream();
dos.write(postValuePairs.getBytes());
dos.flush();
dos.close();
// Retrieve the response back from the servlet
dis = new DataInputStream(hc.openInputStream());
int ch;
// Check the Content-Length first
long len = hc.getLength();
if (len != -1)
{
for (int i = 0; i < len; i++)
if ((ch = dis.read()) != -1)
messagebuffer.append((char) ch);
}
else
{ // if the content-length is not available
while ((ch = dis.read()) != -1)
messagebuffer.append((char) ch);
}
dis.close();
returnValue = "Yahoo";
}
catch (Exception ex)
{
returnValue = ex.toString();
ex.printStackTrace();
}
return returnValue;
}
Instead of data streams you should just use the regular input and output streams. So instead of hc.openDataOutputStream() use hc.openOutputStream(). Data streams are for serializing Java objects to a stream, but you just want to write the raw bytes to the stream -- so a regular outputstream is what you want. Same for reading the response - just use the inputstream returned by hc.openInputStream()

HTTPS connection

i am using the following code for establishing Https connection
HttpsConnection httpConnector = null;
InputStream in = null;
Document doc ;
String content = "";
try
{
httpConnector = (HttpsConnection)Connector.open(url,Connector.READ_WRITE);
httpConnector.setRequestMethod(HttpConnection.GET) ;
in = httpConnector.openInputStream();
byte[] data = new byte[in.available()];
int len = 0;
int size = 0;
StringBuffer raw = new StringBuffer();
while ( -1 != (len = in.read(data)) ) {
raw.append(new String(data, 0, len));
size += len;
}
content = raw.toString().trim();
}
catch(Exception ex)
{
ex.printStackTrace();
return false;
}
try{
in.close();
in =null;
httpConnector.close();
httpConnector =null;
}catch(Exception ex)
{
Dialog.alert("Error:" + ex.getMessage());
return false;
}
}
i think i am able to establish the connection but the values are not coming. i am testing it on Simulator, i have not tested on device
I think your mistake is in the following line:
byte[] data = new byte[in.available()];
The available() method only returns how many bytes are immediately available for reading from the inputstream, but you are using it to initialize the size of the temporary byte array. Since it's possible that available() returns 0, you may be initializing a zero-length array.
It would be better to just initialize "data" with a fixed-length array.

Resources