Professional Documents
Culture Documents
transports, and how to do it. Heres sample code from the BlackBerry development community forums that will show you how to create connections and read/write from them.
class HttpUtils { public static final int CONNECTION_DEFAULT = 0; public static final int CONNECTION_BIS = 1; public static final int CONNECTION_BES = 2; public static final int CONNECTION_TCPIP = 3; public static final int CONNECTION_WIFI = 4;
/** * This method opens a HTTP connection to the given url. The method used is * GET or POST depending on whether postData is null or not. Only the * provided connType is used. For example, if the connType is * CONNECTION_BES, the connection is tried using the BES only. * The only time provided connection type is not used is when the URL * contains ";deviceside=". * * @param url The url to connect to.
* @param requestHeaders The headers in the request. May be null or empty. * @param postData * Data to be posted to the server. If null, the GET method used
for the http connection. The type of transport (BES / BIS / WIFI / Default) to be used
* @param connType *
* * @return Opened HttpConnection object or null if some error occurs. */ public static HttpConnection makeHttpConnection(String url, HttpHeaders requestHeaders, byte[] postData, int connType) { HttpConnection conn = null; OutputStream out = null;
try { if (url.indexOf(";deviceside=") == -1) { switch (connType) { case CONNECTION_BES: url = url + ";deviceside=false"; break; case CONNECTION_BIS: url = url + ";XXXXXXXXXXXXXXXX"; break; case CONNECTION_TCPIP: url = url + ";deviceside=true"; break;
int size = requestHeaders.size(); for (int i = 0; i < size;) { String header = requestHeaders.getPropertyKey(i); // remove header if needed
HttpProtocolConstants.HEADER_CONTENT_LENGTH,
String.valueOf(postData.length)); conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded"); conn.setRequestProperty("User-Agent",
"Profile/MIDP-2.0 Configuration/CLDC-1.0");
out = conn.openOutputStream(); out.write(postData); out.flush(); } } catch (IOException e1) { Log.error("UTIL.HTC " + e1); close(conn, null); // Close the connection
conn = null; } finally { close(null, out); // Close the output, but keep connection open }
return conn; }
private static void close(HttpConnection con, OutputStream out) { if (out != null) { try { out.close(); } catch (IOException e2) { } } if (con != null) { try { con.close(); } catch (IOException e) { } } } } Source code example Here is an BlackBerry client app (NetworkDemo) that connects to a servlet (DataPingServlet) using HTTP and transfers byte[] from client > servlet > client. The client app checks for network coverage first, before trying to connect over cellular (not wifi).
Here is the code for the client app. public class NetworkDemo extends UiApplication { // main method
public MyScreen() {
final TextField ttfUri = new TextField("URL:", "http://nazmul-thinkpad:9090/DataPingServlet/ping" + CellularConnectionDirectives); ButtonField btn = new ButtonField("POST"); final TextField ttfData = new TextField("Data:", "Hello!");
// actually perform POST operation final String uri = ttfUri.getText(); final byte[] data = ttfData.getText().getBytes();
Runnable runnable = new Runnable() { public void run() { checkEDT(); checkCoverage(); try { actuallyConnect(uri, data); } catch (final Exception e) { System.out.println(e.toString()); showToast("Exception: " + e.toString()); } } };
} });
add(vfm);
private void actuallyConnect(String uri, byte[] data) throws Exception { // create the connection... HttpConnection _connection = (HttpConnection) Connector.open(uri, Connector.READ_WRITE, true);
// Set the request method and headers { _connection.setRequestMethod(HttpConnection.POST); _connection.setRequestProperty("If-Modified-Since", "29 Oct 1999 19:43:31 GMT"); _connection.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.0");
_connection.setRequestProperty("Content-Language", "en-US"); }
// Getting the response code will open the connection, send the request, and read the HTTP response headers. // The headers are stored until requested. { int rc = _connection.getResponseCode(); if (rc != HttpConnection.HTTP_OK) { throw new IOException("HTTP response code: " + rc); } }
// Getting the response code will open the connection, send the request, and read the HTTP response headers. // The headers are stored until requested. { int rc = _connection.getResponseCode(); if (rc != HttpConnection.HTTP_OK) { throw new IOException("HTTP response code: " + rc); }
// get the data from the service { InputStream _inputStream = _connection.openInputStream(); final ByteBuffer bb = new ByteBuffer(_inputStream);
// run this in EDT... not BGT! showToast("Got reply from servlet: " + bb.getString());
// close everything out { if (_inputStream != null) try {_inputStream.close();}catch (Exception e) {} if (_outputStream != null) try {_outputStream.close();}catch (Exception e) {} if (_connection != null) try {_connection.close();}catch (Exception e) {}
// /** // // // // // // * Indicates that the coverage status has changed. * Note that a CoverageInfo.COVERAGE_* flag being set in newCoverage is not a guarantee that a * connection of that type will succeed. For example, it is possible for the device to lose coverage * between the time this notification was fired and a subsequent connection is attempted, or for * a destination server to be unresponsive. *
// * @param newCoverage - The new coverage status, consisting of a bitwise OR of one or more CoverageInfo.COVERAGE_* flags. // */
if (!CoverageInfo.isOutOfCoverage()) {
// check to see if the available coverage is of sufficient strength _outOfCoverage = !( CoverageInfo.isCoverageSufficient(RadioInfo.WAF_WLAN) || CoverageInfo.isCoverageSufficient(RadioInfo.WAF_3GPP) || CoverageInfo.isCoverageSufficient(RadioInfo.WAF_CDMA) || CoverageInfo.isCoverageSufficient(RadioInfo.WAF_IDEN) );
if (_outOfCoverage) { showToast("In network coverage, but insufficient strength"); } else { showToast("In network coverage"); }
} else { // definitely out of network coverage _outOfCoverage = true; showToast("Out of network coverage");
public static void showToast(final String msg) { UiApplication.getApplication().invokeLater(new Runnable() { public void run() { Status.show(msg); } }); }
/** this gets appended to the URI before a 3g connection is made */ public static final String CellularConnectionDirectives = DeviceInfo.isSimulator() ? "" : ";deviceside=false;ConnectionType=mds-public";
/** this gets appended to the URI before a WiFi connection is made */ public static final String WiFiConnectionDirectives = DeviceInfo.isSimulator() ? ";interface=wifi" : ";deviceside=true;interface=wifi";
public static final int BUFFER_SIZE = 512; // // jvm constants for string encoding // public static final String ASCII = "US-ASCII"; public static final String UTF8 = "UTF-8"; public static final String DEFAULT_CHAR_ENCODING = UTF8;
public ByteBuffer() { }
/** * this method does not close the InputStream. Simply reads all data on the stream into a byte * buffer. */ public ByteBuffer(InputStream is) throws IOException { byte[] readBuf = new byte[BUFFER_SIZE]; while (true) { int read = is.read(readBuf); if (read == -1) break; append(readBuf, 0, read); } } public ByteBuffer(String s) throws IllegalArgumentException { append(s.getBytes()); }
//
// pure functionality of the class // public ByteBuffer append( byte[] srcBuf, int srcStartIndex, int srcLength) { if (byteRay == null) { //create a new array byteRay = new byte[srcLength]; //copy the src array to the new one /* System.out.println( "byteRay.length="+byteRay.length + ",srcBuf.length="+srcBuf.length + ",srcStartIndex="+srcStartIndex + ",srcLength="+srcLength ); */ arrayCopy( srcBuf, srcStartIndex, byteRay, 0, srcLength); } else { int currentSize = byteRay.length; //create a new array (which is bigger than existing one) byte[] newByteRay = new byte[currentSize + srcLength]; //copy the old (internal) array into the new one arrayCopy(byteRay, 0, newByteRay, 0, currentSize);
//copy the src array into the new one int newByteRayStartIndex = currentSize; arrayCopy( srcBuf, srcStartIndex, newByteRay, newByteRayStartIndex, srcLength); //now blow away the old internal byte array with the bigger one byteRay = newByteRay; }
return this; }
/** * This method simply returns the size of this object in KB. * This is <b>not</b> the same as {@link #getString()}, which should be used if you're trying to encode the bytes to * string form. */ public String toString() { if ((byteRay != null) && (byteRay.length > 0)) { float sizeInKB = byteRay.length / 1024f;
try { return new String(byteRay, enc); } catch (UnsupportedEncodingException e) { //this will never happen, unless the DEFAULT_CHAR_ENCODING //is invalid return "support.ConstantsIF.DEFAULT_CHAR_ENCODING=" + DEFAULT_CHAR_ENCODING + " is invalid!"; } } */
public void setEncoding(String enc) { if (enc == null) { return; } else { //test this encoding string to be valid try { byte[] bytes = {(byte) '0', (byte) '1'}; new String(bytes, enc); this.enc = enc; } catch (UnsupportedEncodingException e) { //don't override the default encoding System.out.println("unsupported encoding"); } } }
/** might return null if encoding fails; unlike {@link #getString()} this does not use system default encoding */ public String getEncodedString() { try { return new String(byteRay, enc); } catch (Exception e) { return null;
} }
/** returns a string representation of the byte[] using system default encoding */ public String getString() { if (byteRay != null) return new String(byteRay); else return ""; }
protected final void arrayCopy(byte[] srcBuf, int srcStartIndex, byte[] destBuf, int destStartIndex, int numberOfBytesToCopy) { System.arraycopy(srcBuf, srcStartIndex, destBuf, destStartIndex, numberOfBytesToCopy); /* System.out.println( "arrayCopy start" ); for( int i=0; i<numberOfBytesToCopy; i++) { destBuf[ destStartIndex + i ] = srcBuf[ srcStartIndex + i ];
// // accessors for internal state // public byte[] getBytes() { if (byteRay == null) { return new byte[0]; } return byteRay; }
return 0; } }
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
public static void selftest() { byte[] br1 = {(byte) '0', (byte) '1'}; byte[] br2 = {(byte) '<', (byte) 'T', (byte) '>'};
System.out.println("::bb1.append( br1 )"); ByteBuffer bb1 = new ByteBuffer().append(br1, 0, 2); bb1.setEncoding(UTF8); System.out.println();
}//end of ByteBuffer Here is the code for the servlet. public class DataPingServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println(":: " + getClass().getSimpleName() + " GET request... ::");
response.getOutputStream().write(sb.toString().getBytes()); response.flushBuffer();
protected void doPost(HttpServletRequest request, HttpServletResponse res) throws ServletException, IOException { System.out.println(":: " + getClass().getSimpleName() + " POST request... ::");
try {
// get input System.out.println("-> got data from client:" + inputBB); if (inputBB.getSize() < 1024) System.out.println(":: request data payload:\n" + inputBB.getString());
outputBB = _getResponse(inputBB);
System.out.println("<- send data to client:" + outputBB); if (outputBB.getSize() < 1024) System.out.println(":: response data payload:\n" + outputBB.getString());
res.setContentLength(inputBB.getSize()); sos.write(inputBB.getBytes()); }
sos.flush(); sos.close();
return resp; }
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
public static final int BUFFER_SIZE = 512; // // jvm constants for string encoding // public static final String ASCII = "US-ASCII"; public static final String UTF8 = "UTF-8"; public static final String DEFAULT_CHAR_ENCODING = UTF8;
public ByteBuffer() {
/** * this method does not close the InputStream. Simply reads all data on the stream into a byte * buffer. */ public ByteBuffer(InputStream is) throws IOException { byte[] readBuf = new byte[BUFFER_SIZE]; while (true) { int read = is.read(readBuf); if (read == -1) break; append(readBuf, 0, read); } } public ByteBuffer(String s) throws IllegalArgumentException { append(s.getBytes()); }
// // pure functionality of the class // public ByteBuffer append( byte[] srcBuf, int srcStartIndex, int srcLength) { if (byteRay == null) { //create a new array byteRay = new byte[srcLength]; //copy the src array to the new one /* System.out.println( "byteRay.length="+byteRay.length + ",srcBuf.length="+srcBuf.length + ",srcStartIndex="+srcStartIndex + ",srcLength="+srcLength ); */ arrayCopy( srcBuf, srcStartIndex, byteRay, 0, srcLength); } else { int currentSize = byteRay.length; //create a new array (which is bigger than existing one) byte[] newByteRay = new byte[currentSize + srcLength];
//copy the old (internal) array into the new one arrayCopy(byteRay, 0, newByteRay, 0, currentSize); //copy the src array into the new one int newByteRayStartIndex = currentSize; arrayCopy( srcBuf, srcStartIndex, newByteRay, newByteRayStartIndex, srcLength); //now blow away the old internal byte array with the bigger one byteRay = newByteRay; }
return this; }
/** * This method simply returns the size of this object in KB. * This is <b>not</b> the same as {@link #getString()}, which should be used if you're trying to encode the bytes to * string form. */ public String toString() {
if ((byteRay != null) && (byteRay.length > 0)) { float sizeInKB = byteRay.length / 1024f; return sizeInKB + " KB"; } else { return "0 KB"; } }
try { return new String(byteRay, enc); } catch (UnsupportedEncodingException e) { //this will never happen, unless the DEFAULT_CHAR_ENCODING //is invalid return "support.ConstantsIF.DEFAULT_CHAR_ENCODING=" + DEFAULT_CHAR_ENCODING + " is invalid!"; } }
*/
public void setEncoding(String enc) { if (enc == null) { return; } else { //test this encoding string to be valid try { byte[] bytes = {(byte) '0', (byte) '1'}; new String(bytes, enc); this.enc = enc; } catch (UnsupportedEncodingException e) { //don't override the default encoding System.out.println("unsupported encoding"); } } }
/** might return null if encoding fails; unlike {@link #getString()} this does not use system default encoding */ public String getEncodedString() { try { return new String(byteRay, enc); }
/** returns a string representation of the byte[] using system default encoding */ public String getString() { if (byteRay != null) return new String(byteRay); else return ""; }
protected final void arrayCopy(byte[] srcBuf, int srcStartIndex, byte[] destBuf, int destStartIndex, int numberOfBytesToCopy) { System.arraycopy(srcBuf, srcStartIndex, destBuf, destStartIndex, numberOfBytesToCopy); /* System.out.println( "arrayCopy start" );
for( int i=0; i<numberOfBytesToCopy; i++) { destBuf[ destStartIndex + i ] = srcBuf[ srcStartIndex + i ]; System.out.println( "\tindex="+i ); } System.out.println( "arrayCopy end" ); */ }
// // accessors for internal state // public byte[] getBytes() { if (byteRay == null) { return new byte[0]; } return byteRay; }
} else { return 0; } }
public static void selftest() { byte[] br1 = {(byte) '0', (byte) '1'}; byte[] br2 = {(byte) '<', (byte) 'T', (byte) '>'};
System.out.println("::bb1.append( br1 )"); ByteBuffer bb1 = new ByteBuffer().append(br1, 0, 2); bb1.setEncoding(UTF8); System.out.println();
}//end of ByteBuffer Sending key/value pairs to forms Instead of using an RPC approach as I have shown above, you might just want to pass some key/value pairs to a form that is hosted in a .php script or Java servlet. In this case, the client code is not much different, but the data that is sent to the server is. Here is some code that shows you how to convert key/value pairs in a Hashtable to a form that can be sent to a web form.
/** converts a given hashtable object to post key/val pair params */ public static byte[] convertToUrlencoded(Hashtable data) {
URLEncodedPostData keyvalpairs = new URLEncodedPostData(URLEncodedPostData.DEFAULT_CHARSET, false); Enumeration enumeration = data.keys(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); keyvalpairs.append(key, (String) data.get(key)); }
return keyvalpairs.getBytes();
The Hashtable contains the key/value pairs to transmit to the web form. This is just like an HTML form would post params to that same web form. You can use this Firefox plugin (UrlParams) to test this out before hand. The table then gets converted toa URLEncodedPostData object, which is then turned into a byte array.
Need more help? developerlife.com offers training courses to empower you, and consulting services to enable you.
Uploading files to forms If you want to send file attachments to web forms, this is doable as well. Please sign up for our training programs to learn how to effectively use networking techniques for your apps and services.
Here is the code to create parameters that you can include a file in, to upload a form:
public HttpMultipartRequest(Hashtable params, String fileField, String fileName, String fileType, byte[] fileBytes) throws IOException {
bos.write(boundaryMessage.getBytes());
bos.write(fileBytes);
bos.write(endBoundary.getBytes());
this.postBytes = bos.toByteArray();
bos.close(); }
return postBytes;
String getBoundaryMessage(String boundary, Hashtable params, String fileField, String fileName, String fileType) { StringBuffer res = new StringBuffer("--").append(boundary).append("\r\n");
while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); String value = (String) params.get(key);
res.append("Content-Disposition: form-data; name=\"").append(key).append("\"\r\n") .append("\r\n").append(value).append("\r\n") .append("--").append(boundary).append("\r\n"); } res.append("Content-Disposition: form-data; name=\"") .append(fileField) .append("\"; filename=\"") .append(fileName) .append("\"\r\n") .append("Content-Type: ") .append(fileType) .append("\r\n\r\n");
return res.toString(); }
} Important thing to note Whether you are using form encoding or multipart form upload, you must set a header to let the server know of your intentions. If you skip this step, then most servers will return an error. Here is the code to set the headers:
if (data instanceof Hashtable) conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); else { HttpMultipartRequest mr = (HttpMultipartRequest) data; conn.setRequestProperty( "Content-Type", "multipart/form-data; boundary=" + mr.getBoundaryString()); }
//////////////////////////////////////////////////////////
package com.connector;
import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject;
import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.LinearLayout; import android.widget.TextView;
public class whitehat extends Activity { /** Called when the activity is first created. */
TextView txt; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Create a crude view - this should really be set via the layout resources
// but since its an example saves declaring them in the XML. LinearLayout rootLayout = new LinearLayout(getApplicationContext()); txt = new TextView(getApplicationContext()); rootLayout.addView(txt); setContentView(rootLayout);
// Set the text and call the connect function. txt.setText("Connecting..."); //call the method to run the data retreival txt.setText(getServerData(KEY_121));
} public static final String KEY_121 = "http://xx.xx.xxx.xxx/hellomysql/mysqlcon.php"; //i use my real ip here
InputStream is = null;
String result = ""; //the year data to send ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("year","1970"));
//http post try{ HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(KEY_121); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); is = entity.getContent();
//convert response to string try{ BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } is.close(); result=sb.toString();
}catch(Exception e){ Log.e("log_tag", "Error converting result "+e.toString()); } //parse json data try{ JSONArray jArray = new JSONArray(result); for(int i=0;i<jArray.length();i++){ JSONObject json_data = jArray.getJSONObject(i); Log.i("log_tag","id: "+json_data.getInt("id")+ ", name: "+json_data.getString("name")+ ", sex: "+json_data.getInt("sex")+ ", birthyear: "+json_data.getInt("birthyear") ); //Get an output to the screen returnString += "\n\t" + jArray.getJSONObject(i); } }catch(JSONException e){ Log.e("log_tag", "Error parsing data "+e.toString()); } return returnString; }
////////////////////////////////////