You Are Here:

Community: Developer Discussion Boards

Reply « Previous Thread | Next Thread »

#1 Old Question Problem in Obex file pushing - 2008-05-28, 09:03

Join Date: Apr 2008
Posts: 16
Location: Noida
Send a message via Yahoo to madhurahuja
madhurahuja's Avatar
madhurahuja
Offline
Registered User
Purpose:
I want to push a file over bluetooth to any active connection in the vicinity.

Progress:
I am able to search devices and maintain session with them.

Problem:
Although devices remain in session still nothing happens. Session only breaks when I close my application.

Device Specs:
I am using Nokia 3500 Classic Series 40 phone. On analysing many forums I came to know that this phone does not have Obex push profile service in it, so I used btspp protocol for sending file as a stream.

URL that I am using:
Quote:
btConnectionURL = "btspp://" + remoteDevice.getBluetoothAddress() + ":" + channel + ";master=false;encrypt=false;authenticate=false";
Code:
For Searching Devices I am using:
Quote:
UUID[] uuidSet = {new UUID(0x1106)};
// 0x0100 is the attribute for the service name element
// in the service record
int[] attrSet = {0x0100};

public void run() {
String rname = "";
try {

remoteDevice = (RemoteDevice) remoteDevices.elementAt(get_devicesList().getSelectedIndex());
rname = remoteDevice.getFriendlyName(true);
/* Alert a=new Alert("Check1","RemoteDevice Name-"+rname,null,AlertType.ALARM);
Display d=getDisplay();
d.setCurrent(a);*/
discoveryAgent.searchServices(attrSet, uuidSet, remoteDevice, this);

} catch (Exception e) {
Alert a = new Alert("Check1", "ERR-" + e.getMessage() + "," + rname, null, AlertType.ALARM);
Display d = getDisplay();
d.setCurrent(a);
}
}
For Obex I am using following code:

Quote:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.microedition.io.*;
import javax.microedition.lcdui.Display;

public class OBEX {

private DataOutputStream out = null;
private DataInputStream in = null;
private StreamConnection con = null;
private Display display;
public static final int maxFileSize = 0x2000;
private FTMIDlet ftmidlet;

public OBEX() {
super();
}

public void connect(String url) throws IOException {
con = (StreamConnection) Connector.open(url);
out = con.openDataOutputStream();
in = con.openDataInputStream();


byte[] data = {(byte)0x80, 0x00, 0x07, 0x10, 0x00, 0x20, 0x00};

out.write( data );
out.flush();

byte[] indata = new byte[100];
int read = in.read(indata);
if (read < 1) {
throw new IOException("Error connecting, no response from server");
}
int responseCode = indata[0] & 0xff;
if (responseCode != 0xa0) {
throw new IOException("Connec:Connection not accepted " + Integer.toHexString(responseCode));
}
}

public int put(String strFileName, String strType, byte[] data)
throws IOException {
if (data.length > maxFileSize) {
throw new IOException("File too large");
}
if (con == null || out == null || in == null) {
throw new IOException("CONNECT command was not sent properly");
}
int len = 1 + 2 + strFileName.length() * 2 + 5 + strType.length() * 2 + 5 + 1 + 4 + 1 + 2 + data.length;
out.writeByte(0x82); //PUT, Final bit set.
out.writeShort(len);

out.writeByte(0x01); //HI for Name header
int lenName = strFileName.length() * 2 + 5; // 2 for null terminated, and 3 for header
out.writeShort(lenName); // name length
out.writeChars(strFileName);
out.writeShort(0); // string termination

out.writeByte(0xC3); // HI for Length header
out.writeInt(data.length);

out.writeByte(0x48); // HI for Object Body chunk header
out.writeShort(data.length + 3); // body length + header length = 3
out.write(data);
out.flush();

byte[] indata = new byte[100];
int read = in.read(indata);
if (read < 1) {
throw new IOException("Error connecting, no response from server");
}
int responseCode = indata[0] & 0xff;

return responseCode;
}

public void disconnect() throws IOException {
if (con == null || out == null || in == null) {
throw new IOException("CONNECT command was not sent properly");
}
out.writeByte(0x81); //DISCONNECT, Final bit set.
out.writeShort(3); // length
out.flush();
byte[] indata = new byte[100];
int read = in.read(indata);
if (read < 1) {
throw new IOException("Error connecting, no response from server");
}
int responseCode = indata[0] & 0xff;
if (responseCode != 0xa0) {
throw new IOException(
"Connection not accepted " + Integer.toHexString(responseCode));
}
con.close();
out.close();
in.close();
}
}

Please some one help me.
I need to know the problem ASAP.


Keep learning,
Madhur Ahuja
Reply With Quote

#2 Old 2008-05-28, 15:49

Join Date: Mar 2003
Posts: 2,617
traud
Offline
Super Contributor
I have a very similar MIDlet like yours, so just some issues I see on the first glance. Not all might be the cause your issue, however, some might be a problem in future.
Quote:
Originally Posted by madhurahuja View Post
new UUID(0x1106)
Make sure your UUID is correct…
Quote:
Originally Posted by madhurahuja View Post
int[] attrSet = {0x0100};
Make sure your attrSet is well chosen…

Furthermore, make sure to honour the maximum byte amount specified (0x0200) and returned by your peer.
Reply With Quote

#3 Old Re: Problem in Obex file pushing - 2008-05-29, 10:10

Join Date: Apr 2008
Posts: 16
Location: Noida
Send a message via Yahoo to madhurahuja
madhurahuja's Avatar
madhurahuja
Offline
Registered User
Thanks for the quick reply TRAUD,

When I change the UUID to Object push profile 0x1105 I get a PRECON ERROR Its hex value is CC.
Can you please share your Midlet with me. I need to resolve connectivity issue ASAP.


Keep learning,
Madhur Ahuja
Reply With Quote

#4 Old 2008-05-29, 16:07

Join Date: Mar 2003
Posts: 2,617
traud
Offline
Super Contributor
When do you get 0xCC exactly? After connect, put or disconnect?
Quote:
Originally Posted by madhurahuja View Post
int len = 1 + 2 + strFileName.length() * 2 + 5 + strType.length() * 2 + 5 + 1 + 4 + 1 + 2 + data.length;
I see no type header being send, is that correct? Furthermore, a type header would ASCII (8-bit for each character and null terminated) and not UTF-16 Big-Endian (16-bit like Java » double null terminated): 3+strType.length()+1.
Quote:
Originally Posted by madhurahuja View Post
byte[] indata = new byte[100];
int read = in.read(indata);
To be honest, I do not understand that part. The great thing about OBEX, everything has a length byte, so all I do is
Code:
out.flush();
responseCode = in.readUnsignedByte();
packetLength = in.readUnsignedShort() - 3;
in.skipBytes(packetLength);
Otherwise data is still on the input stream (and you get bytes from a previous request) or not enough data can be fetched from the stream (and in.read might block infinitely). For the OBEX connect success response, the code (amount of bytes to flush) is a bit different.

By the way, which mobile phone do you use as sender and which one as receiver? Some JSR-82 implementations have problems with their btspp-DataStreams like Nokia, Sony Ericsson and Samsung (which returns 0xffffffA0 for 0xA0; your code avoids that bug already).
Reply With Quote

#5 Old Thumbs up Re: Problem in Obex file pushing - 2008-05-30, 09:21

Join Date: Apr 2008
Posts: 16
Location: Noida
Send a message via Yahoo to madhurahuja
madhurahuja's Avatar
madhurahuja
Offline
Registered User
Hi TRAUD,

Thanks a lot for your replies they really helped.

Response to your questions:

1.I used to get 0xCC after connect.

2.Not sending type header was my mistake. I had included type headers length but was not sending it actually.

3.Even I did not understand this It was not getting used anywhere.
Quote:
byte[] indata = new byte[100];
int read = in.read(indata);

4.I think in.read was getting blocked infinitely. That was causing the phones to remain in session but do nothing.
Quote:
Otherwise data is still on the input stream (and you get bytes from a previous request) or not enough data can be fetched from the stream (and in.read might block infinitely).

Your Code really helped.
Code:
responseCode = in.readUnsignedByte();
packetLength = in.readUnsignedShort() - 3;
in.skipBytes(packetLength);
Can you please explain me what these 3 statements are doing?
I tried to understand them using the documentation but could not relate well in the current context.

Thanks a lot for your help.



Keep learning,
Madhur Ahuja
Last edited by madhurahuja : 2008-05-30 at 09:23. Reason: To make reply presentable
Reply With Quote

#6 Old 2008-05-30, 11:27

Join Date: Mar 2003
Posts: 2,617
traud
Offline
Super Contributor
madhurahuja, have you considered to use an existing javax.obex package? What you are trying to achieve is quite advanced and it looks like you just copied this code which is rather incomplete.

I highly recommend to get a copy of the OBEX specification. Find an emulator which is able to talk to real devices. Alternatively, you could create another MIDlet which uses the javax.obex package of BlueCove for example and then do inter-emulator communication. Alternatively, use BlueCove or a Packet Logger on a computer and analyse the data of your MIDlet on a phone. Reason: You will have to do a lot of, a lot of debugging (on your own) if this MIDlet should get real. Furthermore, you will not be finished very soon with that.

I do not understand/see why you get 0xCC as response to connect from the code provided.

To answer your question, what my code does: You will see after reading the OBEX specification. Every operation response (except the one to connect) starts with a response code (unsigned byte) and then two length bytes (= short). Furthermore, such a response could contain further headers and as you do not handle them, make sure to remove them from your input stream. An example, your (complete unread) input stream looks like:
A0 00 07 10 00 20 00 // answer to your CONNECT command
90 00 03 // answer to your first PUT command, if your file has to be segmented
A0 00 03 // answer to your final PUT command
A0 00 03 // answer to disconnect
After each request, I have to make sure to remove the complete response, to get the correct response code which is important to proceed:
A0 00 07 10 00 20 00

A0 = in.readUnsignedByte();
… // code I leave for your homework; you have to read out the maximum the server sends, too!
in.skipBytes(packetLength);

90 00 03

90 = in.readUnsignedByte(); // continue
00 = in.readUnsignedShort() - 3;
in.skipBytes(00); // does nothing in this case

A0 00 03

A0 = in.readUnsignedByte();
00 = in.readUnsignedShort() - 3;
in.skipBytes(00); // does nothing in this case

A0 00 03

A0 = in.readUnsignedByte();
00 = in.readUnsignedShort() - 3;
in.skipBytes(00); // does nothing in this case

At least, this is my way of doing it. I could be wrong now, anyway, it works for me.
Reply With Quote

#7 Old Re: Problem in Obex file pushing - 2008-05-31, 18:50

Join Date: Apr 2008
Posts: 16
Location: Noida
Send a message via Yahoo to madhurahuja
madhurahuja's Avatar
madhurahuja
Offline
Registered User
Hi TRAUD,
Sorry for replying late.

When I began to achieve my goal I started off with standard OBEX package.
The problem started when I used ClientSession Class. Every time for making a connection I used to use btspp URL.
Code:
Connection connection=Connector.open(btURL);
ClientSession csession=(ClientSession)connection;
Firstly I got Class not found Error. So I compiled obex package and included it in the jar because older series 40 phones don't come with this package.
Then I got ClassCastException during creation of ClientSession.

URL. On using btgoep it always used to say PROTOCOL not supported.


I searched a lot and found that most of the books and examples were doing the same thing. I thought that it might be a device support issue.
In the mean while I saw examples of doing OBEX PUSH using RFCOMM ie. without ClientSession thing.

Currently I have Wireless toolkit of java to test my J2ME Code.
I have just started as a J2ME developer earlier I was into web application development using J2EE.
Your Suggestions are quite valuable. Its quite time consuming to test the application on the real device everytime.

I am ready to do all the debugging that it takes to understand the way devices talk to each other. I will be reading the OBEX specification as soon as I resume Office.

I hope your way of doing it, works for me as well

Will keep posting the understanding updates.
Thanks a lot for replying on those three statements.


Keep learning,
Madhur Ahuja
Reply With Quote

#8 Old 2008-06-02, 14:42

Join Date: Mar 2003
Posts: 2,617
traud
Offline
Super Contributor
If you are new to J2ME, MIDlets and Bluetooth, I recommend to start with a book or tutorials rather than code examples as you will have to debug a lot on your own. There are a lot of bugs, tweaks and lessons to be learnt. Bluetooth is complicated. I started with book about J2ME (probably not the best one), JSR-82 (contains references to other J2ME books; perhaps your library has its previous edition) or read at least the PDF coming with the specification. Then personally I learned a lot from this book about Nokia Series 40. Although all these titles are a bit outdated, many parts are still relevant today and they were a good start for me. Nevertheless, the Developer’s Library of Forum Nokia is a good starting point to. Additionally, if you like to start with tutorials, continue here…

javax.obex is an optional package. One good way to detect whether it is available or not is presented in chapter 8.1 of MSA (JSR-248). However, the following works for me so far.
Code:
try { Class.forName("javax.obex.ResponseCodes"); }
catch (ClassNotFoundException e) { unsupported = true; }
I recommend to start testing your MIDlet in one of the emulators. If the MIDlet has to work on several devices, I would start in the Sun Wireless Toolkit, then move to the S60 Platform SDK (some offer native Bluetooth adapter support; see their documentation!) and then I would go for Series 40 emulator (the latest should support javax.obex). Then go for those which do not support javax.obex and then decide whether to re-use an existing javax.obex implementation. You have to read its documentation as you have to call and start it up differently than a standard javax.obex package. Furthermore, in J2ME land I recommend not to pack JARs into your JAR but the original source code into your source path (if possible) as this will create smaller JARs. I have not understood which package you used and what you did to it: Your btgoep:// and ClassCastException thing, could you please explain that again in more detail?

Using the above code / creating your own OBEX Put operation is not as easy as you might think as there are a lot of, a lot of implementation issues. Why not simply sharing my class implementation avoiding to go through all this? First of all it is my private code, secondly, on a weekly basis I get a new phone or new combination which needs an additional patch. Perhaps my code would not even work in your scenario – I still do not know the partner phone of your Nokia 3500 classic. Anyway, I think a very good understanding for J2ME, JSR-82 and Bluetooth is required to create a quite decent Java MIDlet using those technologies as you will have a lot of debugging sessions as you have to deal with a lot of different virtual machines and the wildest problems you ever envisioned. Memory leaks, threading issues, ServiceRecord.getConnectionURL fails on some devices, InputStream.read(…) and OutputStream.write(…) crash the phone, OutputStream.write(…) do not buffer or use the wrong offset, little-endian data is floating around, … just to name a few problems.

Welcome to J2ME. If you get used to debugging and fighing with these bugs then you will love J2ME as there are many opportunities to learn a new lesson.
Reply With Quote

#9 Old Post Re: Problem in Obex file pushing - 2008-06-04, 07:39

Join Date: Apr 2008
Posts: 16
Location: Noida
Send a message via Yahoo to madhurahuja
madhurahuja's Avatar
madhurahuja
Offline
Registered User
Hi TRAUD,

I am going through the resources provided by you.
They are proving really helpful.

Explanation to your queries are as follows:

Quote:
Furthermore, in J2ME land I recommend not to pack JARs into your JAR but the original source code into your source path (if possible) as this will create smaller JARs.
This is what I did:
I had added jsr82.jar in the libraries using my NetBeans IDE (Mobility Version) Because the phone was not having OBEX classes and interfaces. I did it because it always used to give me Class not found exception.
__________________________________________________________

Following thread talks about the same problem that I had faced:

Link : btgoep & ClassCastException thing


Reason Stated for the problem:
Quote:
Obex is only partially implemented and obex server part btgeop protocol is not implemented in series 40 phones
Thanks.


Keep learning,
Madhur Ahuja
Reply With Quote

#10 Old 2008-06-04, 11:45

Join Date: Mar 2003
Posts: 2,617
traud
Offline
Super Contributor
Better check through my code whether javax.obex (and OBEX) is there or not. For your type of connection, a client connection should be sufficient.

Which ‘jsr82.jar’ have you taken? Please note, many javax.obex implementations are not self-contained, they re-use other components of the current JSR-82 implementation (for example the emulator), probably not available on another JSR-82 implementation (for example the phone). Furthermore, make sure the required classes are within your resulting JAR (for those phones which do not have javax.obex) as just placing them into the library path might not be sufficient for automatic inclusion (for run-time) and might just be for compile time.
Reply With Quote

#11 Old Re: Problem in Obex file pushing - 2008-06-05, 11:24

Join Date: Apr 2008
Posts: 16
Location: Noida
Send a message via Yahoo to madhurahuja
madhurahuja's Avatar
madhurahuja
Offline
Registered User
Hi TRAUD,

I tried your code.
It did not go in the exception because I had included jsr082.jar.
So it was able to find the javax.obex.ResponseCodes

Then I wrote following code:
Code:
ClientSession cs = (ClientSession) Connector.open(url);
        HeaderSet hs = cs.createHeaderSet();
        cs.connect(hs);

        hs.setHeader(HeaderSet.NAME, filename);
        hs.setHeader(HeaderSet.TYPE, "text");
        hs.setHeader(HeaderSet.LENGTH, new Long(data.length));

        Operation putOperation = cs.put(hs);
        OutputStream outputStream = putOperation.openOutputStream();
        outputStream.write(data);
   
        outputStream.close();
        putOperation.close();

        cs.disconnect(null);

        cs.close();

Exception I got:
Code:
java.lang.ClassCastException

at "ClientSession cs = (ClientSession) Connector.open(url);"


Keep learning,
Madhur Ahuja
Reply With Quote

#12 Old 2008-06-05, 13:58

Join Date: Mar 2003
Posts: 2,617
traud
Offline
Super Contributor
If you supply javax.obex within your JAR, you cannot use Connector.open(). To answer what you have to do, I need the answer to: Where is that jsr082.jar from. Who provided it to you?
Reply With Quote

#13 Old Post Re: Problem in Obex file pushing - 2008-06-06, 06:50

Join Date: Apr 2008
Posts: 16
Location: Noida
Send a message via Yahoo to madhurahuja
madhurahuja's Avatar
madhurahuja
Offline
Registered User
Hi TRAUD,

I got the jsr082.jar from the following location:

C:\Program Files\NetBeans 6.0\mobility8\WTK2.5.2\lib


Keep learning,
Madhur Ahuja
Reply With Quote

#14 Old 2008-06-06, 10:56

Join Date: Mar 2003
Posts: 2,617
traud
Offline
Super Contributor
I do not know that JAR, however, I doubt you can re-use (include) that library in your MIDlet. First of all it might depend on other JARs, furthermore, there might be a licensing issue when distributing your final MIDlet. You have to check that! For the start (again, check its license), please use AvetanaOBEX. This library is designed to be re-used and included in your JAR, however, its license and stability might be a problem.
Reply With Quote

#15 Old Post Re: Problem in Obex file pushing - 2008-06-07, 11:08

Join Date: Apr 2008
Posts: 16
Location: Noida
Send a message via Yahoo to madhurahuja
madhurahuja's Avatar
madhurahuja
Offline
Registered User
Hi TRAUD,

I think there is nothing wrong in using jsr082.jar.
As WTK is open source and I tried to figure out the dependancies but was unable to find some. I had used AvetanaOBEX as well and same ClassCastException was appearing.

Can you tell me why the following Statement:

Code:
ClientSession cs=(ClientSession)Connector.open(btURL);
is giving ClassCastException..

And why I cannot include a jsr082.jar like this.


Keep learning,
Madhur Ahuja
Reply With Quote
Reply « Previous Thread | Next Thread »
Display Modes
Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules

You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Forum Jump
Similar Threads
Thread Thread Starter Forum Replies Last Post
Theme Studio 3.1 not creating themes zemm Themes/Carbide.ui 11 2008-10-18 09:41
Problem with ensymble_python2.5-0.26.py in linux tansualpcan Python 2 2008-04-15 11:12
problem installing sis file lucidness General Symbian C++ 8 2006-04-20 18:51
What is the error in my code here? Unable to Save document to file yuva69 General Symbian C++ 1 2005-05-26 15:22
Looking for help from member......pl...help me in my source code. yuva69 General Symbian C++ 0 2002-06-10 13:24

Rate This

 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2009 Nokia