ProjectBook - Networked Software Systems Laboratory

wellofflimpetMobile - Wireless

Dec 14, 2013 (3 years and 6 months ago)

105 views


1

Friend Finder Application


Evgeny Erlihman

jenia.erlihman@gmail.com


Roman Nassimov

roman.nass@gmail.com


Supervisor

Viktor Kulikov

kulik@softlab.technion.ac.il
















Software Systems Lab

Department of Electrical Engineering,

Technion
-

Israel Institute of Technology




2

SHORT DESCRIPTION OF THE PR
OJECT...............................................................3

INTRODUCTION.............................................................................................................4

M
OTIVATION
.....................................................
................................................................4

Android 1.6

..................................................................
....................................
................
4

P
ROJECT
G
OAL
..............................................
....................................................................
5

THE SOLUTION...............................................................................................................
6

I
NTRODUCTION
.................................................
.................................................................
6

R
EQUIREMENTS
L
IST
.........................................................................................................
7

S
ERVER
P
ACKAGE
..................................................
...........................................................9

Architecture Overview ..................................................................................................9

Use case Sscenarios......................................................
..............................................11

Class Diagram............................................................................................................14

U
SER
A
GENT
P
ACKAGE
.................................................................
..................................15

Architecture Overview ................................................................................................15

Main Classes......................................................................................
.........................15

Class Diagram............................................................................................................17






















3

Short description of the project



The project goal is to build a client
-
server appl
ication witch will allow it user to
find each other geographically using GPS
receiver
.


The client application will run on an Andriod OS based cellular device witch will
include at least a GPS receiver and some sort of internet connection (3G or WiFi)
. Th
e
device will transmit it’s own geographical coordinates to a predefined server, according
to
privacy

rules as set by the application user.


The server application will run on a PC machine with an internet connection, it’s
role is to store online user’s co
ordinates and transmit them if requested by other users of
the application.


Both sides of the application are implemented using standard java libraries on the
devices. The Android side is
off course

implemented using the java libraries that are
present on

the
device

(v1.6).



















4


Introduction


Motivation




In the recent time the abilities of the mobile devices are growing and with it the
variety

of applications that they can run. The mobiles have more hardware functions as
other hardware devic
es such as GPS locators. The key
of successful applications

these
days is integration. Why use mobile phone and GPS device if you can use both in a single
device. The device will have the ability to locate yourself on the map, locate your friends
on the ma
p and more important will allow the communication with those friends
according to their location or without it.

This application will provid
e an easy way to find
the
whereabouts

of your friends and the way to get to them.




Android 1.6




Is the platform
on
witch

this applications is developed, what means that the
application will run on any version of android above and including 1.6.

The Android
platform has a quick progress and is being updated each couple of months. Providing the
3
rd

party developers an

user friendly API for developing new applications and a good
solutions for the existing problems of the older versions.









5



Project Goal


The main goals of this project are:



Developing an independent Server witch will answer to request coming from th
e
Android Clients.



Developing Android Client witch will be able to send self
coordinates

to the
server,
receive

coordinates of other users, and display a GUI to the user.


As Educational project further goals are:




Learning to use SQL server in a java prog
ram.
A complicated task

that involves
the learning of the apache SQL server API etc.



Learning the API for 3
rd

party developers for Android based platforms.


















6



The Solution


FFinder application designed to give it’s user a clear whereabouts o
f his friends relatively
to his own, and some direction of gett
ing to them using a certain GUI. The whole project
is written using the java language, the client side uses android java libraries and the
server side uses the standard java .


In the next part

we list the requirements of the project. These requirements will be listed
and described by different scenarios that describe how our application should behave.
Then we shall describe the design of solution to give a good feeling of the system
architectur
e.




















7



Functional Requirements

Server
requirements

1.

Receive XML format data from handsets and store in SQL based Database. We
shall refer to data as to user’s location, his IP address, actual phone number and
online/offline status.

2.

Send appr
opriate data to handset upon request
.

3.

Manage blacklist for each user.

4.

Display logs to screen (incoming/outgoing messages in XML format)

Technology used

Java DB

Java DB's embedded mode makes it simple to develop, deploy, and use applications,
while allowing

easy migration to client/server mode. Java DB is 100% pure Java, so it
fits seamlessly with
any

Java development model.

Java DB supports the standards
we

are already familiar with
--

Java, JDBC, ANSI SQL.
Under development for over a decade, Java DB is ro
bust and stable.

Java DB technology adheres to the JDBC and ANSI/ISO SQL standards. This means
Java DB provides the functionality expected of a sophisticated relational database,
including SQL syntax, transaction management, concurrency, triggers, and back
ups. It
also means that it is easy to migrate an application using Java DB to and from other
standards
-
based databases, such as PostgreSQL, Oracle and DB2.

Java DB is Sun's supported distribution of the open source Apache Derby database. Java
DB is written

in Java, providing "write once, run anywhere" portability. Its ease of use,
standards compliance, full feature set, and small footprint make it the ideal database for
Java developers. It can be embedded in Java applications, requiring zero administration
by the developer or user. It can also be used in client server mode. Java DB is fully
transactional and provides a standard SQL interface as well as a JDBC 4.0 compliant
driver. The Apache Derby project has a strong and growing community that includes

8

deve
lopers from large companies such as Sun Microsystems and IBM as well as
individual contributors.

Java DB is ideal for departmental Java client
-
server applications that need up to 24 x 7
support and the sophistication of a transactional SQL database that pr
otects against data
corruption without requiring a database administrator.

Java DB is extremely easy to use, making it ideal for Java application development and
testing. It can run on a laptop, is available at no cost under the Apache license, and is also

full
-
featured.

You can also use Java DB in embedded applications where there is no need for the
developer or the end
-
user to buy, download, install, administer
-

or even be aware of
-

the
database separately from the application.

Java DB is highly portabl
e. And, because Java DB is fully standards
-
compliant, it is easy
to migrate an application between Java DB and other open standard databases.

Dom XML parser

The DOM is a W3C (World Wide Web Consortium) standard.

The DOM defines a standard for accessing doc
uments like XML and HTML:

"The W3C Document Object Model (DOM) is a platform and language
-
neutral interface
that allows programs and scripts to dynamically access and update the content, structure,
and style of a document."

The DOM is separated into 3 diff
erent parts / levels:



Core DOM
-

standard model for any structured document



XML DOM
-

standard model for XML documents



HTML DOM
-

standard model for HTML documents

The DOM defines the
objects and properties

of all document elements, and the
methods

(interf
ace) to access them.

We used DOM in order to parse incoming and construct outgoing messages.


9

Client Application


The Client application will constantly update the server with it’s current GPS
coordinates, receive updated coordinates of the friend that the
user seeks and display the
calculated information to the user.

The client application will manage the user settings as privacy, blacklist, findebilty etc.


Architecture overview

Server is divided to 2 singleton always working threads (database thread and

communicator thread) and to unlimited number processing threads (called
DataReceivers).

Database thread is the only thread that has access to DB and can perform updates to
tables stored at DB.

Communicator thread listens on socket for user requests to co
nnect and whenever there is
one


DataReceiver thread is opened.

DataReceiver


receives user queries and updates the DB using Database thread. After
update, or data retrievals the DataReceiver thread is clo
s
ed.


Client Package


The client package implemen
ts the client application. Is separated into several threads,
each responsible for a certain aspect of the client functionality.

As the android programming principles dictates, no heavy operations should be
executed
in the GUI thread. Therefore the client
is divided to number of threads that ap
proximately
match the number of

client’s functionalities.



10



















11

Architecture Overview


The Model

The application is divided to two different processes. The GPG process runs
inde
pendently from the others, it’s purpose is to update the GUI process (if it is running)
and the remote server about new coordinates. The process can be turned on and off from
the GUI process. The GUI process has several threads in it to ensure smooth prese
ntation
to the user while commencing network operations and other calculations in the
background.



The following activity is the first activity the user sees when he opens the application.
This activity is designed to give the
User the ability of launching other acivities and
services that the user might need, using the application

public class firstScreen extends Activity {


private LinkedList<Contact> contactsList;


private LinkedList<String> contactsNameList;


private Communi
cator myCommunicator;


private Intent myPathActivity;


private Intent myBlackListActivity;


private String myPhoneNumber;




/** Called when the activity is first created. */


@Override

We create and initialize all the activity’s variables and struct
ures when it is first created.


public void onCreate(Bundle savedInstanceState) {

GUI

GPS

2 threads


1 thread



12


super.onCreate(savedInstanceState);


setContentView(R.layout.main);


contactsList = new LinkedList<Contact>();


contactsNameList = new LinkedL
ist<String>();


myCommunicator = new Communicator(Defenitions.SEND_COM);


myPathActivity = new Intent(this,PathActivity.class);


myBlackListActivity = new Intent(this,BlackListActivity.class);




TelephonyManager telepho
ny = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);


myPhoneNumber = telephony.getLine1Number();


myPhoneNumber = "528027455";




}


/* Creates the menu items */


public boolean onCreateOptionsMenu(Menu menu) {



menu.add(0, Defenitions.MENU_BLACK_LIST, 0, "Manage Black List").setIcon(R.drawable.equalizer);



menu.add(0, Defenitions.MENU_FIND_FRIEND, 0, "Find a Friend ").setIcon(R.drawable.magnet);



menu.add(0, Defenitions.MENU_GO_OFFLINE, 0, "Go Offline").s
etIcon(R.drawable.disc);



menu.add(0, Defenitions.MENU_GO_ONLINE, 0, "Go Online").setIcon(R.drawable.globe);



return true;


}



/* Handles item selections */


public boolean onOptionsItemSelected(MenuItem item) {



switch (item.getItemId()) {




case Defenitions.MENU_FIND_FRIEND:



findFriend();



return true;



case Defenitions.MENU_GO_ONLINE:



goOnline();



return true;



case Defenitions.MENU_GO_OFFLINE:




goOffline();




return true;



case Defen
itions.MENU_BLACK_LIST:




manageBlackList();




return true;



}



return false;


}




public void findFriend(){




Get all friends from local contact list.



// Form an array specifying which columns to return.



String[] projection = new St
ring[] {




People._ID,




People.NAME,




People.NUMBER




};




// Get the base URI for the People table in the Contacts content provider.



Uri
contacts = People.CONTENT_URI;




// Make the query.



Cursor managedCursor = managedQuery(contacts,




projection, // Which columns to return




null, // Which rows to return (all rows)





null, // Selection arguments (none)




// Put the results in ascending order by name




People.NAME + " ASC");


13






if (managedCursor.moveToFirst()) {




String name;



Str
ing phoneNumber;



int nameColumn = managedCursor.getColumnIndex(People.NAME);



int phoneColumn = managedCursor.getColumnIndex(People.NUMBER);






do {



// Get the field values



name = managedCursor.getStr
ing(nameColumn);



phoneNumber = managedCursor.getString(phoneColumn);






// Do something with the values.



contactsList.addLast(new Contact(name,phoneNumber));



contactsNameList.addLast(name);





} while (managedCursor.moveToNext());



}




ListView myListView = (ListView) findViewById(R.id.ContactsList);


ArrayAdapter<String> myArrayAdapter= new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,contactsNameLi
st);


myListView.setAdapter(myArrayAdapter);




myListView.setOnItemClickListener(new OnItemClickListener() {



public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {




Toast toast = Toast.makeText(getApplicationContex
t(), "You chose: " + (String)contactsNameList.get(arg2), oast.LENGTH_LONG);




toast.show();


Check if the wanted user is available to be found.





Contact findy = contactsList.get(arg2);





//if(myCommunicator.checkifOnline(findy.getPhone())){





if(my
Communicator.checkifOnline(myPhoneNumber,"528027455")){






myPathActivity.putExtra("friend_name", findy.getPhone());






//myCommunicator.closeServerSocket();






startActivity(myPathActivity);





}




}


});

}



public void goOnline(){






//
SelfLocationUpdater will send our current location to the server as soon as it starts, so we need not notify the server from
here



Intent i = new Intent();



i.setClassName( "com.FFinder","com.FFinder.SelfLocationUpdater" );



startService(i);





}


public void goOffline(){





Intent i = new Intent();



i.setClassName( "com.FFinder","com.FFinder.SelfLocationUpdater" );



stopService(i);


}


public void manageBlackList(){




startActivity(myBlackListActivity);





}

}



14

The next service is designed
to run in a separate procces, get updates from the GPS and
send them to the server.

public class SelfLocationUpdater extends Service{



final RemoteCallbackList<IRemoteServiceCallback> mCallbacks = new RemoteCallbackList<IRemoteServiceCallback>();




priva
te LocationManager mgr;


private myLocationListenerClass myLocationListener;


private Location myLocation;


private Communicator myCommunicator;


private String myPhoneNumber;

A listener for location changes updates.

It notifies the GUI to make a change.



private class myLocationListenerClass implements LocationListener{



@Override



public void onLocationChanged(Location location) {




Log.v("SelfLocationUpdater", "New Location: " + location.getLatitude() + location.getLongitude());




// Broadcast to al
l clients the new value.



final int N = mCallbacks.beginBroadcast();



for (int i=0; i<N; i++) {



try {



mCallbacks.getBroadcastItem(i).locationChanged(location);



} catch (RemoteException e) {




// The RemoteCallbackList will take care of removing



// the dead object for us.



}



}



mCallbacks.finishBroadcast();



myLocation = location;






// Send new Self Location to the s
erver



myCommunicator.sendNewSelfLocation(location,myPhoneNumber);



}



@Override



public void onProviderDisabled(String provider) {




// TODO Auto
-
generated method stub



}



@Override



public void onProviderEnabled(String provider) {




// TODO Auto
-
generated method stub



}



@Override



public void onStatusChanged(String provider, int status, Bundle extras) {



// TODO Auto
-
generated method stub



}


}

We create and initialize all the activity’s variables and structures when it is fir
st created.

Also, this is where the service notifies the OS that it should receive updates about
location changes.



@Override



public void onCreate() {








Log.v("SelfLocationUpdater", "Launched");








myLocationListener = new myLocationListene
rClass();




myCommunicator = new Communicator(Defenitions.SEND_COM);


15








TelephonyManager telephony = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);




myPhoneNumber = telephony.getLine1Number();




myPhoneNumber = "528027455";









mgr = (LocationManager) getSystemService(LOCATION_SERVICE);






Criteria criteria = new Criteria();




String best = mgr.getBestProvider(criteria, true);




Log.v("SelfLocationUpdater", "Best provider is: " + best);








mgr.requestLocationUp
dates(best, 15000, 1, myLocationListener);








Location location = mgr.getLastKnownLocation(best);




if(location == null) return; //protection in case there is no last known location
-

may be impossible unless emulator








// Send Self Current
Location to the server




myCommunicator.sendNewSelfLocation(location,myPhoneNumber);







Log.v("SelfLocationUpdater", "Locations (starting with last known): " + location.getLatitude() + location.getLongitude());











}


@Override


pu
blic void onStart( Intent intent, int startId ) {



super.onStart(intent, startId);




Log.v("SelfLocationUpdater", "onStart");

For us to be able to actually stop this service, we need the OS to think that it is active
rather then hung on listener events.
So a simple single thread is used for this purpose, it
just sleeps.




Thread t = new Thread() {



public void run() {




for(int i = 0; ; i++)






{





// this is done in order to keep the service "alive" and giv
e us the ability to actually stop it






SystemClock.sleep(500000000);






}



}



};



t.start();


}

@Override


public void onDestroy() {



Log.v("SelfLocationUpdater", "onDestroy");



mgr.removeUpdates(m
yLocationListener);



// Send "we go offline" notification to the server



myCommunicator.sendOffLineNotification(myPhoneNumber);


}






@Override


public IBinder onBind(Intent arg0) {



return mBinder;


}

Next part is for IPC.




private final IRemoteSer
vice.Stub mBinder = new IRemoteService.Stub() {


16



public void registerCallback(IRemoteServiceCallback cb) {



if (cb != null) mCallbacks.register(cb);



}



public void unregisterCallback(IRemoteServiceCallback cb) {




if (cb != null) mCallbacks.unregister(cb);



}




@Override




public Location getCurrentLocation() throws RemoteException {





return myLocation;




}



};


}


The next activity is responsible for showing the user a kind of GUI. It’s inpu
ts are, local
GPS and remote server location updates of the wanted client.


public class PathActivity extends Activity{




IRemoteService mService = null;




private Location myLocation = null;


private Location hisLocation = null;


private Communicator my
Communicator;


private String myPhoneNumber;




// Need handler for callbacks to the UI thread


final Handler mHandler = new Handler();




// Create runnable for posting



final Runnable mUpdateResults = new Runnable() {



public void run() {





updateView(myLocation,hisLocation);



}



};


Upon creation of this activity, it gets some input parameters from the activity that started
it, and creates the GUI object.




@Override


public void onCreate(Bundle savedInstanceState) {



supe
r.onCreate(savedInstanceState);






myCommunicator = new Communicator(Defenitions.GET_COM);



TelephonyManager telephony = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);



myPhoneNumber = telephony.getLine1Number()
;






// ge
t current location of the person we want to find



String findy_phone = getIntent().getStringExtra("friend_name");



Communicator temp_Communicator = new Communicator(Defenitions.SEND_COM);



hisLocation = temp_Communicator.getCurrentLocation(myPhone
Number,findy_phone);





Director mv = new Director(this);


mv.setSelfLocation(myLocation,hisLocation);


setContentView(mv);




}


17

When the activity is actually started it opens an IPC protocol line with the GPS procces in
order
to get updates of location changes.


@Override


protected void onStart() {



super.onStart();






Intent i = new Intent();



i.setClassName( "com.FFinder","com.FFinder.SelfLocationUpdater" );







bindService(i,mConnection, Context.BIND_AUTO_CREATE);






// THe purpose of this thread is to wait for other location updates from the Server



Thread t = new Thread() {



public void run() {





while(true)





{







hisLocation = myCommunicator.waitForNewLocation();






mHandler.post(mUpdateResults);





}



}



};



t.start();


}




public void updateView(Location location1,Location location2){






Director mv = new Director(this);



mv.setSelfLocation(locatio
n1,location2);



setContentView(mv);



Log.v("PathFinder", "New Location: ");


}




private ServiceConnection mConnection = new ServiceConnection() {


public void onServiceConnected(ComponentName className,


IBinder service) {



// This is called when the connection with the service has been


// established, giving us the service object we can use to


// interact with the service. We are communicating with our


// service through an IDL inter
face, so get a client
-
side


// representation of that from the raw service object.


mService = IRemoteService.Stub.asInterface(service);



// We want to monitor the service for as long as we are


// connected to
it.


try {


mService.registerCallback(mCallback);


//myLocation = mService.getCurrentLocation();


} catch (RemoteException e) {


// In this case the service has crashed before we could even


// do anything with it; we can count on soon being


// disconnected (and then reconnected if it can be restarted)


// so there is no need to do anything here.


}




}



publ
ic void onServiceDisconnected(ComponentName className) {


// This is called when the connection with the service has been


// unexpectedly disconnected
--

that is, its process crashed.


mService = null;


18




}


};






/**


* This implementation is used to receive callbacks from the remote


* service.


*/


private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {


/**


* This is called by the remot
e service regularly to tell us about


* new values. Note that IPC calls are dispatched through a thread


* pool running in each process, so the code executing here will


* NOT be running in our main thread like most other things
--

so,


* to update the UI, we need to use a Handler to hop over there.


*/



@Override



public void locationChanged(Location location){




myLocation = location;




mHandler.post(mUpdateResults);




Log.v("PathFinder", "got New Location b")
;


}




@Override



public void currentLocation(Location location) throws RemoteException {




myLocation = location;







};


};


}

The next class is being used in the previous activity for presenting the GUI to the user.

package com.FFinder;


impo
rt android.content.Context;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.location.Location;

import android.util.AttributeSet;

import android.view.View;


public class Director extends View {



private float direction = 45.0f
;




//private Double myLatitude = 32.775812;


//private Double myLongatiude = 35.025063;




//private Double hisLatitude = 32.777752;


//private Double hisLongatiude = 35.021743;




private Location myLocation = null;


private Location hisLocation = null;





public float getDirection() {



return direction;


}


public void setDirection(float direction) {



this.direction = direction;


19



invalidate();


}


public void setSelfLocation(Location location1,Location location2){



if(location1 != null) myLocation
= location1;



if(location2 != null) hisLocation = location2;






if((myLocation != null) & (hisLocation!= null)){




invalidate();



}





}




public Director(Context context) {



super(context);






myLocation = new Location("mock");



myLocation.setL
atitude(Location.convert("32:46:33.17"));



myLocation.setLongitude(Location.convert("35:1:30.28"));






hisLocation = new Location("mock");



hisLocation.setLatitude(Location.convert("32:46:39.82"));



hisLocation.setLongitude(Location.convert("35:1:18.2
4"));









initCompassView();


}


public Director(Context context, AttributeSet attrs, int defStyle) {



super(context, attrs, defStyle);



initCompassView();


}




public Director(Context context, AttributeSet attrs) {



super(context, attrs);



initCo
mpassView();


}




private void initCompassView() {



invalidate();


}




@Override


protected void onDraw(Canvas cv) {






// this is done for the case that we have not obtained the latest location, self or friend



if(myLocation == null) return;



if(hi
sLocation == null) return;






int x = cv.getWidth();



int y = cv.getHeight();



Paint p = new Paint();



p.setColor(android.graphics.Color.MAGENTA);



draw_arrow(cv, p, x, y);



}




/*private void draw_arrow(Canvas canvas, Paint p, int width, int heigh
t) {



p.setColor(android.graphics.Color.BLUE);



p.setStrokeWidth(10);



final float centre_x = width*0.5f;



final float centre_y = height*0.5f;



//canvas.rotate(
-
direction, width * 0.5f, height * 0.5f);



canvas.drawLine(centre_x, centre_y
-
(height*0.3f
), centre_x, centre_y + (height*0.3f), p);



p.setColor(android.graphics.Color.RED);


20



//canvas.drawLine(centre_x
-

width*0.1f, centre_y
-
(height*0.2f), centre_x + width*0.1f, centre_y
-
(height*0.2f), p);



//canvas.drawLine(centre_x
-

width*0.1f, centre_y
-
(
height*0.2f), centre_x, centre_y
-
(height*0.3f), p);



//canvas.drawLine(centre_x + width*0.1f, centre_y
-
(height*0.2f), centre_x, centre_y
-
(height*0.3f), p);


}*/




private void draw_arrow(Canvas canvas, Paint p, int width, int height) {


p.setColor(androi
d.graphics.Color.BLUE);


p.setStrokeWidth(10);


final float centre_x = width*0.5f;


final float centre_y = height*0.5f;






float deg_brng = myLocation.bearingTo(hisLocation);



canvas.drawText("Bearing:" + deg_brng + "
\
u00b0", 32, 32, p);




canvas.rotat
e(deg_brng, width * 0.5f, height * 0.5f);


canvas.drawLine(centre_x, centre_y
-
(height*0.3f), centre_x, centre_y + (height*0.3f), p);


p.setColor(android.graphics.Color.RED);


canvas.drawLine(centre_x
-

width*0.1f, centre_y
-
(height*0.2f), centre_x + width*0
.1f, centre_y
-
(height*0.2f), p);


canvas.drawLine(centre_x
-

width*0.1f, centre_y
-
(height*0.2f), centre_x, centre_y
-
(height*0.3f), p);


canvas.drawLine(centre_x + width*0.1f, centre_y
-
(height*0.2f), centre_x, centre_y
-
(height*0.3f), p);


}

}


The next clas
s is responsible for the communication between the clients and the server.

It offers a kind of abstraction for it’s user that do not need to know how exactly the data
is being transferred, what is the format and the physical link.




public class Communica
tor {



private ServerSocket mySS;


private Socket myCS;


private int myType;


private XMLHandler myXMLHandler;


public Communicator(int ntype){



myXMLHandler = new XMLHandler();



myType = ntype;



try {



switch(myType)



{




case Defenitions.GET_COM:

mySS = new ServerSocket(Defenitions.srcPort);




break;




case Defenitions.SEND_COM:

//myCS = new Socket(Defenitions.dstName,Defenitions.dstPort);




break;




case Defenitions.ALL_COM:

mySS = new ServerSocket(Defenitions.srcPort);











//myCS = new
Socket(Defenitions.dstName,Defenitions.dstPort);




break;




default:



}



} catch (UnknownHostException e) {




// TODO Auto
-
generated catch block




e.printStackTrace();


21



} catch (IOException e) {




// TODO Auto
-
generated catch block




e.printStackT
race();



}


}




public void sendMsg(String msg){


}




public Location waitForNewLocation(){



Socket temp_socket;



byte[] incoming_bytes = new byte[256];






try {




temp_socket = mySS.accept();




temp_socket.getInputStream().read(incoming_bytes);




temp_socket.close();



} catch (IOException e) {




// TODO Auto
-
generated catch block




e.printStackTrace();



} catch (NullPointerException e) {




e.printStackTrace();



}






return myXMLHandler.getLocationFromReply(new String(incoming_bytes));


}



public void sendNewSelfLocation(Location location,String myNumber){



String str = myXMLHandler.newLoactionToString(location,myNumber);





try {




myCS = new Socket(Defenitions.dstName,Defenitions.dstPort);




myCS.getOutputStream().write(str.getBytes(
));




myCS.close();



} catch (IOException e) {




// TODO Auto
-
generated catch block




e.printStackTrace();



}





}




public void sendOffLineNotification(String phone){



String str = myXMLHandler.closureNotification(phone);






try {




myCS = new
Socket(Defenitions.dstName,Defenitions.dstPort);




myCS.getOutputStream().write(str.getBytes());




myCS.close();



} catch (IOException e) {




// TODO Auto
-
generated catch block




e.printStackTrace();



}


}




public boolean checkifOnline(String mphon
e,String phone){



String str = myXMLHandler.isPersonOnlinQuery(mphone,phone);



byte[] incoming_bytes = new byte[256];



try {




myCS = new Socket(Defenitions.dstName,Defenitions.dstPort);




myCS.getOutputStream().write(str.getBytes());




myCS.getInput
Stream().read(incoming_bytes);




myCS.close();


22



} catch (IOException e) {




// TODO Auto
-
generated catch block




e.printStackTrace();



}



str = myXMLHandler.getIsOnlineReply(new String(incoming_bytes));



if(str.equalsIgnoreCase("true")) return true;



return false;


}




public Location getCurrentLocation(String mphone,String phone){



String str = myXMLHandler.getCurrentLocationQuery(mphone,phone);



byte[] incoming_bytes = new byte[256];



try {




myCS = new Socket(Defenitions.dstName,Defenitions.
dstPort);




myCS.getOutputStream().write(str.getBytes());




myCS.getInputStream().read(incoming_bytes);




myCS.close();



} catch (IOException e) {




// TODO Auto
-
generated catch block




e.printStackTrace();



}



return myXMLHandler.getLocationFromRe
ply(new String(incoming_bytes));


}




public LinkedList<String> getBlackListFriends(String mPhone){



String str = myXMLHandler.BlackListRequestString(mPhone);



byte[] incoming_bytes = new byte[256];



try {




myCS = new Socket(Defenitions.dstName,Defen
itions.dstPort);




myCS.getOutputStream().write(str.getBytes());




myCS.getInputStream().read(incoming_bytes);




myCS.close();



} catch (IOException e) {




// TODO Auto
-
generated catch block




e.printStackTrace();



}






// the following is for tes
ting without actually recieve the string



//LinkedList<String> tempList = new LinkedList<String>();



//tempList.add("1
-
545
-
4");



return myXMLHandler.parseBlackList(new String(incoming_bytes));


}




public void addPersonToBlackList(String myPhone,String

hisPhone){



String str = myXMLHandler.addPersonToBlackList(myPhone, hisPhone);






try {




myCS = new Socket(Defenitions.dstName,Defenitions.dstPort);




myCS.getOutputStream().write(str.getBytes());




myCS.close();



} catch (IOException e) {




// T
ODO Auto
-
generated catch block




e.printStackTrace();



}


}




public void removePersonFromBlackList(String myPhone,String hisPhone){



String str = myXMLHandler.removePersonFromBlackList(myPhone, hisPhone);






try {




myCS = new Socket(Defenitions.ds
tName,Defenitions.dstPort);




myCS.getOutputStream().write(str.getBytes());


23




myCS.close();



} catch (IOException e) {




// TODO Auto
-
generated catch block




e.printStackTrace();



}


}


public void closeServerSocket(){



try {




mySS.close();



} ca
tch (IOException e) {




// TODO Auto
-
generated catch block




e.printStackTrace();



}


}

}


The
following class dictates the XML format standard for server client communication. It
is responsible for creating and parsing incoming and outgoing messages.

p
ackage com.FFinder;


import java.io.StringReader;

import java.io.StringWriter;

import java.util.LinkedList;


import org.xmlpull.v1.XmlPullParser;

import org.xmlpull.v1.XmlPullParserFactory;

import org.xmlpull.v1.XmlSerializer;


import android.location.Loca
tion;

import android.util.Xml;


public class XMLHandler {



public XMLHandler(){





}


public String writeXml(String str){



XmlSerializer serializer = Xml.newSerializer();



StringWriter writer = new StringWriter();



try {



serializer.s
etOutput(writer);



serializer.startDocument("UTF
-
8", true);






serializer.startTag("", "message");



serializer.text("updatecoord");



//serializer.attribute("", "cmd", "updatecoord");



//serializer
.attribute("", "dataX", str);



//serializer.attribute("", "dataY", str);



serializer.endTag("", "message");






serializer.endDocument();



return writer.toString();



} catch (Exception e) {



throw
new RuntimeException(e);



}


}




public String readXml(String str) {



String str1 = "<?xml version='1.0' encoding='UTF
-
8' standalone='yes' ?><isOnlineReply>true</isOnlineReply>";



String str2;


24



try {




XmlPullParserFactory factory = XmlPullParser
Factory.newInstance();




factory.setNamespaceAware(true);




XmlPullParser xpp = factory.newPullParser();





xpp.setInput( new StringReader ( str1 ) );




int eventType = xpp.getEventType();




str2 = xpp.getAttributeValue(0);




while (eventType != XmlPullParser.END_DOCUMENT) {




if(eventType == XmlPullParser.START_DOCUMENT) {




System.out.println("Start document");




} else if(eventType == XmlPullParser.END_DOCUMENT) {




System.out.println("End doc
ument");




} else if(eventType == XmlPullParser.START_TAG) {




System.out.println("Start tag "+xpp.getName());




System.out.println("Start tag "+xpp.getText());




//System.out.println("Start tag "+xpp.getAttributeValue("
", "cmd"));




} else if(eventType == XmlPullParser.END_TAG) {




System.out.println("End tag "+xpp.getName());




} else if(eventType == XmlPullParser.TEXT) {




System.out.println("Text "+xpp.getText());




}




even
tType = xpp.next();




}



} catch (Exception e) {



throw new RuntimeException(e);



}




return str2;


}




@SuppressWarnings("static
-
access")


public String newLoactionToString(Location location,String myNumber){



XmlSerializ
er serializer = Xml.newSerializer();



StringWriter writer = new StringWriter();



try {



serializer.setOutput(writer);



serializer.startDocument("UTF
-
8", true);






serializer.startTag("", "NewSelfLocation");








serializer.startTag("", "Phone");




serializer.text(myNumber);




serializer.endTag("", "Phone");





serializer.startTag("", "Lat");



serializer.text(location.convert(location.getLatitude(), Location
.FORMAT_SECONDS));



serializer.endTag("", "Lat");






serializer.startTag("", "Lon");



serializer.text(location.convert(location.getLongitude(), Location.FORMAT_SECONDS));



serializer.endTag("", "L
on");






serializer.endTag("", "NewSelfLocation");



serializer.endDocument();



return writer.toString();



} catch (Exception e) {



throw new RuntimeException(e);



}


}




public String closureNotificatio
n(String phone){


25



XmlSerializer serializer = Xml.newSerializer();



StringWriter writer = new StringWriter();



try {



serializer.setOutput(writer);



serializer.startDocument("UTF
-
8", true);






serializer.startTag("", "Cl
osureNotification");







serializer.startTag("", "Close");




serializer.text(phone);




serializer.endTag("", "Close");






serializer.endTag("", "ClosureNotification");



serializer.endDocument();



return writer.toString();



} catch (Exception e) {



throw new RuntimeException(e);



}


}




public String isPersonOnlinQuery(String mPhone,String nPhone){



XmlSerializer serializer = Xml.newSerializer();



StringWriter writer =

new StringWriter();



try {



serializer.setOutput(writer);



serializer.startDocument("UTF
-
8", true);






serializer.startTag("", "isOnline");







serializer.startTag("", "myPhone");




serializer.text(m
Phone);




serializer.endTag("", "myPhone");








serializer.startTag("", "hisPhone");




serializer.text(nPhone);




serializer.endTag("", "hisPhone");






serializer.endTag("", "isOnline");




serializer.endDocument();



return writer.toString();



} catch (Exception e) {



throw new RuntimeException(e);



}


}




public String getCurrentLocationQuery(String mPhone,String nPhone){



XmlSerializer serializer = Xml.newSeriali
zer();



StringWriter writer = new StringWriter();



try {



serializer.setOutput(writer);



serializer.startDocument("UTF
-
8", true);






serializer.startTag("", "GetLocation");







serializer.startTag("", "my
Phone");




serializer.text(mPhone);




serializer.endTag("", "myPhone");







serializer.startTag("", "hisPhone");




serializer.text(nPhone);




serializer.endTag("", "hisPhone");





26



serializ
er.endTag("", "GetLocation");



serializer.endDocument();



return writer.toString();



} catch (Exception e) {



throw new RuntimeException(e);



}


}


public String getIsOnlineReply(String str) {




String str2 = null;




try
{





XmlPullParserFactory factory = XmlPullParserFactory.newInstance();





factory.setNamespaceAware(true);





XmlPullParser xpp = factory.newPullParser();






xpp.setInput( new StringReader ( str ) );





int eventType = xpp.getEventTy
pe();





while (eventType != XmlPullParser.END_DOCUMENT) {





if(eventType == XmlPullParser.START_DOCUMENT) {





//System.out.println("Start document");





} else if(eventType == XmlPullParser.END_DOCUMENT) {





//Syste
m.out.println("End document");





} else if(eventType == XmlPullParser.START_TAG) {





//System.out.println("Start tag "+xpp.getName());





if(xpp.getName().equalsIgnoreCase("isOnlineReply")){







xpp.next();







str2 = xpp.getText();







return str2;





}












System.out.println("Start tag "+xpp.getText());





//System.out.println("Start tag "+xpp.getAttributeValue("", "cmd"));





} else if(eventType ==

XmlPullParser.END_TAG) {





//System.out.println("End tag "+xpp.getName());





} else if(eventType == XmlPullParser.TEXT) {





//System.out.println("Text "+xpp.getText());





}





eventType = xpp.next();





}




} catch (Exception e) {




throw new RuntimeException(e);




}






return str2;



}




public Location getLocationFromReply(String str) {



String Lat = null;



String Lon = null;



try {




XmlPullParserFactory factory = XmlPullParser
Factory.newInstance();




factory.setNamespaceAware(true);




XmlPullParser xpp = factory.newPullParser();





xpp.setInput( new StringReader ( str ) );




int eventType = xpp.getEventType();




while (eventType != XmlPullParser.END_DOC
UMENT) {




if(eventType == XmlPullParser.START_DOCUMENT) {




//System.out.println("Start document");




} else if(eventType == XmlPullParser.END_DOCUMENT) {




// System.out.println("End document");




} else if(eventType
== XmlPullParser.START_TAG) {




//System.out.println("Start tag "+xpp.getName());


27




if(xpp.getName().equalsIgnoreCase("Lat")){






xpp.next();






Lat = xpp.getText();




}else




if(xpp.getName().equ
alsIgnoreCase("Lon")){






xpp.next();






Lon = xpp.getText();





}




System.out.println("Start tag "+xpp.getText());




//System.out.println("Start tag "+xpp.getAttributeValue("", "cmd"));




} else if(ev
entType == XmlPullParser.END_TAG) {




//System.out.println("End tag "+xpp.getName());




} else if(eventType == XmlPullParser.TEXT) {




//System.out.println("Text "+xpp.getText());




}




eventType = xpp.next();




}



} catch (Exception e) {



throw new RuntimeException(e);



}


Location t = new Location("mock");


t.setLatitude(Location.convert(Lat));


t.setLongitude(Location.convert(Lon));





return t;


}


public String addPersonToBlackList(String m
Phone,String nPhone){



XmlSerializer serializer = Xml.newSerializer();



StringWriter writer = new StringWriter();



try {



serializer.setOutput(writer);



serializer.startDocument("UTF
-
8", true);






serializer.startTag(""
, "AddToBlackList");







serializer.startTag("", "myPhone");




serializer.text(mPhone);




serializer.endTag("", "myPhone");







serializer.startTag("", "hisPhone");




serializer.text(nPhone);





serializer.endTag("", "hisPhone");






serializer.endTag("", "AddToBlackList");



serializer.endDocument();



return writer.toString();



} catch (Exception e) {



throw new RuntimeException(e);



}


}


publ
ic String removePersonFromBlackList(String mPhone,String nPhone){



XmlSerializer serializer = Xml.newSerializer();



StringWriter writer = new StringWriter();



try {



serializer.setOutput(writer);



serializer.startDocument("UTF
-
8",
true);






serializer.startTag("", "RemoveFromBlackList");







serializer.startTag("", "myPhone");




serializer.text(mPhone);




serializer.endTag("", "myPhone");


28







serializer.startTag("", "hisPho
ne");




serializer.text(nPhone);




serializer.endTag("", "hisPhone");






serializer.endTag("", "RemoveFromBlackList");



serializer.endDocument();



return writer.toString();



} catch (Exception e) {




throw new RuntimeException(e);



}


}


public String BlackListRequestString(String mPhone){



XmlSerializer serializer = Xml.newSerializer();



StringWriter writer = new StringWriter();



try {



serializer.setOutput(writer);




serializer.startDocument("UTF
-
8", true);






serializer.startTag("", "BlackListRequest");







serializer.startTag("", "myPhone");




serializer.text(mPhone);




serializer.endTag("", "myPhone");







serializer.endTag("", "BlackListRequest");



serializer.endDocument();



return writer.toString();



} catch (Exception e) {



throw new RuntimeException(e);



}


}


public LinkedList<String> parseBlackList(String str) {



LinkedList<String> tmpList = new LinkedList<String>();



String tmpName = null;



try {




XmlPullParserFactory factory = XmlPullParserFactory.newInstance();




factory.setNamespaceAware(true);




XmlPullParser xpp = factory.newPullParser();






xpp.setInput( new StringReader ( str ) );




int eventType = xpp.getEventType();




while (eventType != XmlPullParser.END_DOCUMENT) {




if(eventType == XmlPullParser.START_DOCUMENT) {




//System.out.println("Start document");





} else if(eventType == XmlPullParser.END_DOCUMENT) {




// System.out.println("End document");




} else if(eventType == XmlPullParser.START_TAG) {




//System.out.println("Start tag "+xpp.getName());




if(xpp.getName()
.equalsIgnoreCase("BadMan")){






xpp.next();






tmpName = xpp.getText();






tmpList.add(tmpName);




}




System.out.println("Start tag "+xpp.getText());




//System.out.println("Start tag "+xpp.get
AttributeValue("", "cmd"));




} else if(eventType == XmlPullParser.END_TAG) {




//System.out.println("End tag "+xpp.getName());




} else if(eventType == XmlPullParser.TEXT) {




//System.out.println("Text "+xpp.getText());




}




eventType = xpp.next();


29




}



} catch (Exception e) {



throw new RuntimeException(e);



}


return tmpList;


}


}

The ext activity enables the user to manage his black list, it can choose any person from
his contact list

and mark it as a person that he want him to see himself or not.

package com.FFinder;


import java.util.LinkedList;


import com.iconList.IconifiedText;

import com.iconList.IconifiedTextListAdapter;


import android.app.AlertDialog;

import android.app.Dialog
;

import android.app.Activity;

import android.content.Context;

import android.content.DialogInterface;

import android.database.Cursor;

import android.net.Uri;

import android.os.Bundle;

import android.provider.Contacts.People;

import android.telephony.Telep
honyManager;

import android.view.View;

import android.widget.AdapterView;

import android.widget.ListView;

import android.widget.AdapterView.OnItemClickListener;


public class BlackListActivity extends Activity{




private LinkedList<Contact> contactsList;


private LinkedList<String> contactsNameList;


private Communicator myCommunicator;


private String myPhoneNumber;


private IconifiedTextListAdapter myArrayAdapter;


private ListView myListView;




@Override



protected Dialog onCreateDialog(final int id)
{




return new AlertDialog.Builder(this).setTitle(R.string.select_dialog).setItems(R.array.select_dialog_items, new DialogInterfa
ce.OnClickListener() {


public void onClick(DialogInterface dialog, int which) {





/* User clicked so

do some stuff */


//String[] items = getResources().getStringArray(R.array.select_dialog_items);


if(which == 0){




myArrayAdapter.replaceItem(id, new IconifiedText(contactsNameList.get(id), getResources().g
etDrawable(R.drawable.vidoop)));




myListView.setAdapter(myArrayAdapter);




myCommunicator.addPersonToBlackList(myPhoneNumber,(String)contactsList.get(id).getPhone());


}else{




myArrayAdapter
.replaceItem(id, new IconifiedText(contactsNameList.get(id), getResources().getDrawable(R.drawable.favicon)));




myListView.setAdapter(myArrayAdapter);




myCommunicator.removePersonFromBlackList(myPhoneNumber,(String)contact
sList.get(id).getPhone());


}


//new AlertDialog.Builder(BlackListActivity.this).setMessage("You selected: " + which + " , " + items[which]).show();


}


}).create();


30



}



@Override



protected void onCre
ate(Bundle savedInstanceState) {



super.onCreate(savedInstanceState);



setContentView(R.layout.main);






contactsList = new LinkedList<Contact>();



contactsNameList = new LinkedList<String>();



myCommunicator

= new Communicator(Defenitions.SEND_COM);






TelephonyManager telephony = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);





myPhoneNumber = telephony.getLine1Number();






// Form an array specifying which c
olumns to return.




String[] projection = new String[] {





People._ID,





People.NAME,





People.NUMBER





};





// Get the base URI for th
e People table in the Contacts content provider.




Uri contacts = People.CONTENT_URI;





// Make the query.




Cursor managedCursor = managedQuery(contacts,





projection, // Which columns to return






null, // Which rows to return (all rows)





null, // Selection arguments (none)





// Put the results in ascending order by name





People.NAME + " ASC");




// create
a linked list for display




myArrayAdapter = new IconifiedTextListAdapter(this);








if (managedCursor.moveToFirst()) {





String name;




String phoneNumber;




int nameColumn = managedCursor.getColumnIndex(People.NAME);





int phoneColumn = managedCursor.getColumnIndex(People.NUMBER);








LinkedList<String> tempList = myCommunicator.getBlackListFriends(myPhoneNumber);








do {




// Get the field values




name = manage
dCursor.getString(nameColumn);




phoneNumber = managedCursor.getString(phoneColumn);








if(tempList.contains(phoneNumber)){






myArrayAdapter.addItem(new IconifiedText(name, getResources().getDrawable(R.dra
wable.vidoop)));




}else{





myArrayAdapter.addItem(new IconifiedText(name, getResources().getDrawable(R.drawable.favicon)));




}








contactsList.addLast(new Contact(name,phoneNumber));





contactsNameList.addLast(name);





} while (managedCursor.moveToNext());





}







myListView = (ListView) findViewById(R.id.ContactsList);


31




// Display it



myListView.setAdapter(myArrayAdapter);







myListView.setOnItemClickListener(new OnItemClickListener() {





public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {






//Toast toast = Toast.makeText(getApplicationContext(), "You chose: " +
(String)contactsNameList.get(arg2)
, Toast.LENGTH_LONG);






//toast.show();






showDialog(arg2);





}



});









}

}








Use case scenarios


The application includes several client server sessions:


1.

Self location Update. The Client changes position
physical
ly

and sends it’s new
whereabouts

to the server


XML formatted.

One way transmition.

2.

Black List:

a.

Get current Black List. The Client request the current black list as it is
stored on the server. The Server transmits the list back to the client.

b.

Add a perso
n to a black list. The Client sends a contact details to the
server, that should be added to the Client’s Black List.

c.

Remove a person to a black list. The Client sends a contact details to the
server, that should be Removed to the Client’s Black List.



32

3.

Req
uest another Client whereabouts. The client requests from the server the
whereabouts of another client, if the requesting client is not in a black list of the
requested

Client, it gets his last location.

4.

Go On/Off Line. The Client notifies the server if it

can be found or not for other
Clients not in his black list.