Java Question Writing a Library From Scratch

ashchopra

Member
Licensed User
Longtime User
Hi,
This is exactly what I need to do too.
I have an Jar File (Also all the source code, as it is open source). I need to use its functions within B4Abdroid.

Now after seeing the video and reading the tutorials I understand the following:-

1. Start new eclipse project.
2. Add reference to Core.jar, B4Shared.jar, Android.jar and the jar file that I need to use.
3. Now write code to refer each and every function, method, event etc of that jar file.
4. Use javadoc to create the .xml file for the jar file.
5. Put both these files in the library folder of B4Android.
6. Add reference to these two files in the B4Android project.

If I have to write Java Code, (Which I dont know) Does anyone have any jar file and its associated java library code which make the wrapper, that I can study to make my own library wrapper.

I am basically a VB6 programmer and donot know any java. But If I have some examples of how classes and methods may be written in java for a given function/method in a jar file I could probably use that as a template and create the rest. I know the syntax of the jar functions/method etc as the jar file and all its associated code is available as open source.

Can anyone help with some example of a class written in java in eclipse that refers a function/method in some commonly available jar file, so that I could study it.

Please do help.

Thanks
:sign0163::BangHead:
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Here is the code of the analytics library. It is a simple wrapper:
@Version(1.0f)
@ShortName("AnalyticsTracker")
@Permissions(values={"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE"})
public class AnalyticsTracker {
/**
* Initializes the object and starts a new session. Information will be sent automatically.
*AccountId - Your analytics account id (UA-xxxxx-yy).
*DispatchPeriod - The interval measured in seconds to automatically send the collected information.
*/
public void Initialize(String AccountId, int DispatchPeriod) {
GoogleAnalyticsTracker.getInstance().startNewSession(AccountId, DispatchPeriod, BA.applicationContext);
}
/**
* Initializes the object and starts a new session. Information will be sent manually by calling Dispatch.
*AccountId - Your analytics account id (UA-xxxxx-yy).
*/
public void Initialize2(String AccountId) {
GoogleAnalyticsTracker.getInstance().startNewSession(AccountId, BA.applicationContext);
}
/**
* Triggers a pageview.
*Page - The pseudo page that is being viewed.
*/
public void TrackPageView(String Page) {
GoogleAnalyticsTracker.getInstance().trackPageView(Page);
}
/**
* Triggers an event.
*See Google Analytics documentation for more information about Analytics events.
*/
public void TrackEvent(String Category, String Action, String Label, int Value) {
GoogleAnalyticsTracker.getInstance().trackEvent(Category, Action, Label, Value);
}
/**
* Manually sends the collected information.
*Returns true if sending was successful.
*You do not need to handle failures. It will retry to send automatically.
*/
public boolean Dispatch() {
return GoogleAnalyticsTracker.getInstance().dispatch();
}
/**
* Stops sending information and ends the current session.
*/
public void Stop() {
GoogleAnalyticsTracker.getInstance().stopSession();
}
}
 

ashchopra

Member
Licensed User
Longtime User
Great !!

Thanks a ton Erel. This should get me going. While I only know VB6 and not Java, I can read the code and do some copycat work to make the wrapper for the JExcelApi Open Source Library. When that is done I'll post it on the forum for all to use.

Regards, and thanks again:)
 

wl

Well-Known Member
Licensed User
Longtime User
Net library

Hello Erel,

Would it be possible to get the source code of the NET library as well ?

I would like to add the TOP command for POP3 and it seems that you are using an Apache library (did some decompiling :) which does include the TOP, you only did not wrap it.

I could start a new library from scratch but adding a TOP method would be easier and better I suppose ?

Wim
 

wl

Well-Known Member
Licensed User
Longtime User
Erel,

Ok not problem. But would it be able to get the source anyway so I can look at it and learn from it ? I guess I might still be missing some info from the Java decompiler)

I would like my Android device check my POP3 account every few minutes, to keep battery usage as low as possible:

- I would need the number of messages and total mail size (the output of the STAT command): when these values are the same as the ones of the previous check I can close the connection: nothing more to do.

- the TOP command: I'm only interested in the headers not the content itself (TOP 0)

Thanks,

Wim
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Here:
package anywheresoftware.b4a.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.net.pop3.POP3Client;
import org.apache.commons.net.pop3.POP3MessageInfo;

import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.objects.collections.Map;
import anywheresoftware.b4a.objects.streams.File.TextReaderWrapper;
/**
* POP3 object allows you to connect to mail servers and read the mail messages.
*This object returns the raw string of each message, including the headers. Parsing the raw string is currently out of the scope of this library.
*The connection is established when it is first required.
*ListCompleted event passes a parameter named Messages. This is a map with the messages IDs as keys and the messages sizes as values.
*DownloadCompleted event passes the message raw string in the Message parameter.
*Example:<code>
*Sub Process_Globals
* Dim POP As POP3
*End Sub
*Sub Globals
*
*End Sub
*
*Sub Activity_Create(FirstTime As Boolean)
* If FirstTime Then
* POP.Initialize("pop.gmail.com", 995, "[email protected]", "mypassword", "pop")
* POP.UseSSL = True 'Gmail requires SSL.
* End If
* POP.ListMessages
*End Sub
*
*Sub POP_ListCompleted (Success As Boolean, Messages As Map)
* Log("List: " & Success)
* If Success Then
* For i = 0 To Messages.Size - 1
* Pop.DownloadMessage(Messages.GetKeyAt(i), True) 'Download all messages and delete them
* Next
* Else
* Log(LastException.Message)
* End If
* POP.Close 'The connection will be closed after all messages are downloaded
*End Sub
*Sub POP_DownloadCompleted (Success As Boolean, MessageId As Int, Message As String)
* Log("Download: " & Success & ", " & MessageId)
* If Success Then
* Log(Message)
* Log(Message.Length)
* Log(MessageId)
* Else
* Log(LastException.Message)
* End If
*End Sub</code>
*/
@Events(values= {"ListCompleted (Success As Boolean, Messages As Map)",
"DownloadCompleted (Success As Boolean, MessageId As Int, Message As String)"})
@Permissions(values = {"android.permission.INTERNET"})
@ShortName("POP3")
public class POPWrapper {
private String user, password, server;
private int port;
private static int taskId;
private String eventName;
private boolean useSSL;
private POP3Client client;
private volatile int numberOfTasks;
private ReentrantLock lock = new ReentrantLock(true);
/**
* Initializes the object.
*Server - Server address. Host name or Ip.
*Port - Mail server port.
*Username - Account user name.
*Password - Account password.
*EventName - The name of the sub that will handle the MessageSent event.
*/
public void Initialize(String Server, int Port, String Username, String Password, String EventName) {
this.user = Username;
this.password = Password;
this.server = Server;
this.port = Port;
this.eventName = EventName.toLowerCase(BA.cul);
numberOfTasks = 0;
useSSL = false;
client = new POP3Client();

}
/**
* Gets or sets whether the connection should be done with SSL sockets.
*/
public void setUseSSL(boolean b) {
useSSL = b;
}
public boolean getUseSSL() {
return useSSL;
}
private void connectIfNeeded(final BA ba) throws Exception {
if (client == null) {
throw new RuntimeException("POP3 should first be initialized.");
}
if (client.isConnected() == false) {
if (useSSL)
client.setSSL();
client.connect(server, port);
if (client.login(user, password) == false)
throw new RuntimeException("Error during login: " + client.getReplyString());
}
}
/**
* Calls the server and when data is ready raises the ListCompleted event.
*See the example described above.
*/
public void ListMessages(final BA ba) {
final int myTask = taskId++;
numberOfTasks++;
Runnable r = new Runnable() {
@Override
public void run() {
Map m = new Map(); m.Initialize();
lock.lock();
try {
try {
connectIfNeeded(ba);
POP3MessageInfo[] msgs = client.listMessages();
if (msgs == null)
throw new RuntimeException("Error listing messages: " + client.getReplyString());

for (POP3MessageInfo msg : msgs) {
m.Put(msg.number, msg.size);
}
ba.raiseEventFromDifferentThread(null, POPWrapper.this, myTask, eventName + "_listcompleted", false, new Object[] {true, m});
} catch (Exception e) {
ba.setLastException(e);
ba.raiseEventFromDifferentThread(null, POPWrapper.this, myTask, eventName + "_listcompleted", false, new Object[] {false, m});

try {
CloseNow();
} catch (IOException e1) {
e1.printStackTrace();
}
}
} finally {
endOfTask();
}
}
};
BA.submitRunnable(r, POPWrapper.this, myTask);
}
/**
* Calls the server and downloads a message. When the message is ready the DownloadedCompleted event is raised.
*MessageId - The message id which was previously retrieved by calling ListMessages.
*Delete - Whether to delete the message after it is downloaded. Note that the message will only be deleted after the connection is closed.
*/
public void DownloadMessage(final BA ba,final int MessageId,final boolean Delete) {
final int myTask = taskId++;
numberOfTasks++;
Runnable r = new Runnable() {
@Override
public void run() {
lock.lock();
try {
try {
connectIfNeeded(ba);
Reader reader;
if ((reader = client.retrieveMessage(MessageId)) == null)
throw new RuntimeException("Error retrieving message: " + client.getReplyString());
BufferedReader br = (BufferedReader)reader;
TextReaderWrapper t = new TextReaderWrapper();
t.setObject(br);
String msg = t.ReadAll();
if (Delete) {
if (client.deleteMessage(MessageId) == false) {
throw new RuntimeException("Error deleting message: " + client.getReplyString());
}
}
ba.raiseEventFromDifferentThread(null, POPWrapper.this, myTask, eventName + "_downloadcompleted", false, new Object[] {true, MessageId, msg});
} catch (Exception e) {
e.printStackTrace();
ba.setLastException(e);
ba.raiseEventFromDifferentThread(null, POPWrapper.this, myTask, eventName + "_downloadcompleted", false, new Object[] {false, MessageId, ""});
try {
CloseNow();
} catch (IOException e1) {
e1.printStackTrace();
}
}
} finally {
endOfTask();
}
}
};
BA.submitRunnable(r, POPWrapper.this, myTask);
}
private void endOfTask() {
lock.unlock();
numberOfTasks--;
if (client != null && numberOfTasks == 0) {
synchronized (client) {
client.notifyAll();
}
}
}
/**
* Closes the connection after all submitted tasks finish. Note that this method do not block.
*/
public void Close() {
final int myTask = taskId++;
if (client == null) {
return;
}
Runnable runnable = new Runnable() {

@Override
public void run() {
synchronized (client) {
while (numberOfTasks > 0 && client != null) {
try {
client.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
CloseNow();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
BA.submitRunnable(runnable, this, myTask);
}
/**
* Closes the connection immediately without waiting for current tasks to finish.
*/
public synchronized void CloseNow() throws IOException {
if (client == null)
return;
if (client.isConnected()) {
client.logout();
client.disconnect();
}
synchronized (client) {
client.notifyAll();
}
client = null;
}

}
 
Top