package com.jphonelite;
import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import android.util.*;
import android.net.*;
import android.database.*;
import android.provider.*;
import android.provider.Contacts.*;
import android.content.*;
import java.util.*;
import javaforce.*;
import javaforce.voip.*;
/**
* jPhoneLite for Android : Main Activity
*
* author : Peter Quiring (pquiring at gmail dot com)
*
* website : jphonelite.sourceforge.net
*/
public class Main extends Activity {
private String ICICLE_KEY = "jpl-view";
private TextView dial, status;
private Button l1, l2, l3, l4, l5, l6;
private Button xfr, hld, aa, ac, dnd, cnf;
private Button n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
private Button star, pound;
private Button contacts, callButton, del;
protected static Button spk;
private Button lineButtons[]; //make it easy to access them
private java.util.Timer buttonTimer;
private final int PICK_CONTACT = 0;
private final int VIEW_SETTINGS = 1;
private final int DIALOG_CONTACTS_ID = 0;
private final int DIALOG_ABOUT_ID = 1;
private ArrayList<CharSequence> contactList;
private String ns; //notification service
private NotificationManager mNotificationManager;
private final int NOTIFY_ID = 1;
private boolean pickingContact = false;
public static Handler handler = null;
public boolean exiting = false;
public Engine engine;
public static boolean active = false;
/**
* Called when Activity is first created. Turns off the title bar, sets up
* the content views, and fires up the View.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
JFLog.log( "onCreate()"+this);
super.onCreate(savedInstanceState);
try {
if (handler == null) handler = new Handler();
requestWindowFeature(Window.FEATURE_NO_TITLE); // No Title bar
ns = Context.NOTIFICATION_SERVICE;
mNotificationManager = (NotificationManager) getSystemService(ns);
engine = Engine.getInstance(this, this);
showView();
spk.setBackgroundResource(Settings.current.speakerMode ? R.drawable.spk_green : R.drawable.spk_grey);
} catch (Exception e) {
JFLog.log(e);
}
}
@Override
protected void onStart() {
JFLog.log( "onStart()"+this);
super.onStart();
// The activity is about to become visible.
}
@Override
protected void onResume() {
JFLog.log( "onResume()"+this);
super.onResume();
// The activity has become visible (it is now "resumed").
active = true;
notify(null, false);
startButtonTimer();
updateScreen();
}
@Override
protected void onPause() {
JFLog.log( "onPause()"+this);
super.onPause();
// Pause the app along with the activity
try {
active = false;
stopButtonTimer();
if ((engine.active) && (!pickingContact)) {
if (!exiting) {
if (engine.line == -1) notify("Idle", false); else notify(engine.lines[engine.line].incall ? "Incall" : "Idle", false);
}
if (!isFinishing()) finish(); //BUG : notify() intent still sometimes creates a second instance of this class (so confusing)
}
} catch (Exception e) {
JFLog.log(e);
}
}
@Override
protected void onStop() {
JFLog.log( "onStop()"+this);
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
@Override
protected void onDestroy() {
JFLog.log( "onDestroy()"+this);
super.onDestroy();
// The activity is about to be destroyed.
}
@Override
public void onSaveInstanceState(Bundle outState) {
//Store the game state
outState.putBundle(ICICLE_KEY, saveState());
}
public void notify(String msg, boolean sound) {
try {
if (msg == null) {
mNotificationManager.cancel(NOTIFY_ID);
return;
}
int icon = R.drawable.ic_main;
CharSequence tickerText = msg;
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
Context context = getApplicationContext();
CharSequence contentTitle = "VoIP Phone Status";
CharSequence contentText = msg;
Intent notificationIntent = new Intent(this, Main.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, pendingIntent);
if (sound) {
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;
}
mNotificationManager.notify(NOTIFY_ID, notification);
} catch (Exception e) {
JFLog.log(e);
}
}
/**
* Restore game state if our process is being relaunched
*
* @param icicle a Bundle containing the app state
*/
public void restoreState(Bundle icicle) {
// member = icicle.getX("name");
}
/**
* Saves state if our process is being relaunched
*
* @return a Bundle containing the app state
*/
public Bundle saveState() {
Bundle map = new Bundle();
// map.putX("name", value);
return map;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
try {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
} catch (Exception e) {
JFLog.log(e);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.about:
about();
return true;
case R.id.settings:
showSettings();
return true;
case R.id.exit:
exiting = true;
if (engine.active) {
engine.uninit();
engine.release();
}
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
protected Dialog onCreateDialog(int id) {
try {
Dialog dialog;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
switch(id) {
case DIALOG_CONTACTS_ID:
builder.setTitle("Pick a number");
builder.setItems((CharSequence[])contactList.toArray(new CharSequence[] {}), new DialogInterface.OnClickListener() {
private ArrayList<CharSequence> contactList;
public void onClick(DialogInterface dialog, int item) {
String res[] = contactList.get(item).toString().split(":");
engine.lines[engine.line].dial = res[0].replaceAll("-", "");
updateScreen();
}
public DialogInterface.OnClickListener init(ArrayList<CharSequence> contactList) {
this.contactList = contactList;
return this;
}
}.init(contactList));
dialog = builder.create();
break;
case DIALOG_ABOUT_ID:
builder.setTitle("About")
.setMessage(R.string.main_about_text)
.setCancelable(false)
.setPositiveButton("Ok", null);
dialog = builder.create();
break;
default:
dialog = null;
}
return dialog;
} catch (Exception e) {
JFLog.log(e);
}
return null;
}
protected void onPrepareDialog (int id, Dialog dialog) {
switch (id) {
case DIALOG_CONTACTS_ID:
}
}
private String getType(String type) {
if (type.equals("1")) return "HOME";
if (type.equals("2")) return "MOBILE";
if (type.equals("3")) return "WORK";
return "OTHER";
}
@Override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
super.onActivityResult(reqCode, resultCode, data);
//JFLog.log( "onActivityResult(" + reqCode + "," + resultCode + "," + data);
try {
switch (reqCode) {
case PICK_CONTACT:
pickingContact = false;
// if (resultCode == Activity.RESULT_OK) {
if (data == null) break;
Uri contactData = data.getData();
if (contactData == null) break;
//JFLog.log( "Uri=" + contactData);
ContentResolver cr = getContentResolver();
Cursor c = managedQuery(contactData, null, null, null, null);
//JFLog.log( "Cursor=" + c);
if (c.moveToFirst()) {
//JFLog.log( "moveToFirst = true");
if (Integer.parseInt(c.getString(c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
String id = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));
Cursor pCur = managedQuery(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id},
null);
contactList = new ArrayList<CharSequence>();
while (pCur.moveToNext()) {
String num = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String type = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
if (num != null) {
//JFLog.log( "num=" + num + ",type=" + type);
String ent = num.replaceAll("-", "") + ":" + getType(type);
boolean dup = false;
for(int a=0;a<contactList.size();a++) {
if (contactList.get(a).toString().split(":")[0].equals(ent.split(":")[0])) {dup = true; break;}
}
if (!dup) contactList.add((CharSequence)ent);
}
}
if (contactList.size() > 1) {
//JFLog.log( "contactList.size=" + contactList.size());
removeDialog(DIALOG_CONTACTS_ID); //make sure it's deleted
showDialog(DIALOG_CONTACTS_ID);
} else if (contactList.size() == 1) {
String res[] = contactList.get(0).toString().split(":");
engine.lines[engine.line].dial = res[0].replaceAll("-", "");
updateScreen();
}
}
}
// }
break;
case VIEW_SETTINGS:
//return from ViewSettings
engine.reinit();
updateScreen();
break;
}
} catch (Exception e) {
JFLog.log(e);
}
}
public void showView() {
// Display display = getWindowManager().getDefaultDisplay();
// JFLog.log( "ScreenSize=" + display.getWidth() + "x" + display.getHeight());
try {
setContentView(R.layout.main);
dial = (TextView) findViewById(R.id.main_text1);
status = (TextView) findViewById(R.id.main_text2);
spk = (Button) findViewById(R.id.main_spk);
spk.setBackgroundResource(Settings.current.speakerMode ? R.drawable.spk_green : R.drawable.spk_grey);
l1 = (Button) findViewById(R.id.main_l1);
l2 = (Button) findViewById(R.id.main_l2);
l3 = (Button) findViewById(R.id.main_l3);
l4 = (Button) findViewById(R.id.main_l4);
l5 = (Button) findViewById(R.id.main_l5);
l6 = (Button) findViewById(R.id.main_l6);
lineButtons = new Button[6];
lineButtons[0] = l1;
lineButtons[1] = l2;
lineButtons[2] = l3;
lineButtons[3] = l4;
lineButtons[4] = l5;
lineButtons[5] = l6;
xfr = (Button) findViewById(R.id.main_xfr);
hld = (Button) findViewById(R.id.main_hld);
aa = (Button) findViewById(R.id.main_aa);
ac = (Button) findViewById(R.id.main_ac);
dnd = (Button) findViewById(R.id.main_dnd);
cnf = (Button) findViewById(R.id.main_cnf);
n0 = (Button) findViewById(R.id.main_0);
n0.setBackgroundResource( R.drawable.phone_0 );
n1 = (Button) findViewById(R.id.main_1);
n1.setBackgroundResource( R.drawable.phone_1 );
n2 = (Button) findViewById(R.id.main_2);
n2.setBackgroundResource( R.drawable.phone_2 );
n3 = (Button) findViewById(R.id.main_3);
n3.setBackgroundResource( R.drawable.phone_3 );
n4 = (Button) findViewById(R.id.main_4);
n4.setBackgroundResource( R.drawable.phone_4 );
n5 = (Button) findViewById(R.id.main_5);
n5.setBackgroundResource( R.drawable.phone_5 );
n6 = (Button) findViewById(R.id.main_6);
n6.setBackgroundResource( R.drawable.phone_6 );
n7 = (Button) findViewById(R.id.main_7);
n7.setBackgroundResource( R.drawable.phone_7 );
n8 = (Button) findViewById(R.id.main_8);
n8.setBackgroundResource( R.drawable.phone_8 );
n9 = (Button) findViewById(R.id.main_9);
n9.setBackgroundResource( R.drawable.phone_9 );
star = (Button) findViewById(R.id.main_star);
star.setBackgroundResource( R.drawable.phone_star );
pound = (Button) findViewById(R.id.main_pound);
pound.setBackgroundResource( R.drawable.phone_pound );
contacts = (Button) findViewById(R.id.main_contacts);
contacts.setBackgroundResource( R.drawable.phone_contacts );
callButton = (Button) findViewById(R.id.main_call);
callButton.setBackgroundResource( R.drawable.phone_green );
del = (Button) findViewById(R.id.main_del);
del.setBackgroundResource( R.drawable.phone_del );
spk.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Settings.current.speakerMode = !Settings.current.speakerMode;
spk.setBackgroundResource(Settings.current.speakerMode ? R.drawable.spk_green : R.drawable.spk_grey);
engine.sound.restartSound();
}
});
l1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
engine.selectLine(0);
}
});
l2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
engine.selectLine(1);
}
});
l3.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
engine.selectLine(2);
}
});
l4.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
engine.selectLine(3);
}
});
l5.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
engine.selectLine(4);
}
});
l6.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
engine.selectLine(5);
}
});
xfr.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
do_xfr();
}
});
hld.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
do_hld();
}
});
aa.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
do_aa();
}
});
ac.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
do_ac();
}
});
dnd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
do_dnd();
}
});
cnf.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
do_cnf();
}
});
n0.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('0');
}
});
n1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('1');
}
});
n2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('2');
}
});
n3.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('3');
}
});
n4.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('4');
}
});
n5.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('5');
}
});
n6.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('6');
}
});
n7.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('7');
}
});
n8.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('8');
}
});
n9.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('9');
}
});
star.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('*');
}
});
pound.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addDigit('#');
}
});
contacts.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
do_contacts();
}
});
del.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
do_del();
}
});
del.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
engine.clearDial();
return true;
}
});
callButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
do_call();
}
});
callButton.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
redial();
return true;
}
});
aa.setBackgroundResource( Settings.current.aa ? R.drawable.sel_green : R.drawable.sel_grey );
ac.setBackgroundResource( Settings.current.ac ? R.drawable.sel_green : R.drawable.sel_grey );
} catch (Exception e) {
JFLog.log(e);
}
}
public void setText(TextView tv, String str) {
try {
tv.setText(str.toCharArray(),0,str.length());
} catch (Exception e) {
JFLog.log(e);
}
}
public void startButtonTimer() {
try {
if (buttonTimer == null) {
buttonTimer = new Timer();
buttonTimer.schedule(new ButtonColorUpdater(), 250, 250);
}
} catch (Exception e) {
JFLog.log(e);
}
}
public void stopButtonTimer() {
try {
if (buttonTimer != null) {
buttonTimer.cancel();
buttonTimer = null;
}
} catch (Exception e) {
JFLog.log(e);
}
}
public void do_xfr() {
try {
engine.do_xfr();
updateScreen();
} catch (Exception e) {
JFLog.log(e);
}
}
public void do_hld() {
try {
engine.do_hld();
updateScreen();
} catch (Exception e) {
JFLog.log(e);
}
}
public void do_aa() {
try {
Settings.current.aa = !Settings.current.aa;
aa.setBackgroundResource( Settings.current.aa ? R.drawable.sel_green : R.drawable.sel_grey );
} catch (Exception e) {
JFLog.log(e);
}
}
public void do_ac() {
try {
Settings.current.ac = !Settings.current.ac;
ac.setBackgroundResource( Settings.current.ac ? R.drawable.sel_green : R.drawable.sel_grey );
} catch (Exception e) {
JFLog.log(e);
}
}
public void do_dnd() {
try {
engine.do_dnd();
updateScreen();
call();
} catch (Exception e) {
JFLog.log(e);
}
}
public void do_cnf() {
try {
engine.do_cnf();
updateScreen();
} catch (Exception e) {
JFLog.log(e);
}
}
public void do_call() {
try {
engine.do_call();
} catch (Exception e) {
JFLog.log(e);
}
}
public void do_contacts() {
try {
if (engine.line == -1) return;
if (engine.lines[engine.line].incall) return;
pickingContact = true;
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
startActivityForResult(intent, PICK_CONTACT);
} catch (Exception e) {
JFLog.log(e);
}
}
public void do_del() {
try {
addDigit('x');
} catch (Exception e) {
JFLog.log(e);
}
}
public void addDigit(char digit) {
try {
engine.addDigit(digit);
updateScreen();
} catch (Exception e) {
JFLog.log(e);
}
}
/** Update the number to be dialed, status and buttons for current selected line. */
public void updateScreen() {
//JFLog.log( "updateScreen():line=" + engine.line);
try {
if (engine.line == -1) {
setText(dial, "");
setText(status, "");
xfr.setBackgroundResource( R.drawable.sel_grey );
hld.setBackgroundResource( R.drawable.sel_grey );
dnd.setBackgroundResource( R.drawable.sel_grey );
cnf.setBackgroundResource( R.drawable.sel_grey );
callButton.setBackgroundResource( R.drawable.phone_red );
return;
}
//JFLog.log( "updateScreen():status=" + engine.lines[engine.line].status);
setText(dial, engine.lines[engine.line].dial);
setText(status, engine.lines[engine.line].status);
xfr.setBackgroundResource( engine.lines[engine.line].xfr ? R.drawable.sel_green : R.drawable.sel_grey );
hld.setBackgroundResource( engine.lines[engine.line].hld ? R.drawable.sel_green : R.drawable.sel_grey );
dnd.setBackgroundResource( engine.lines[engine.line].dnd ? R.drawable.sel_green : R.drawable.sel_grey );
cnf.setBackgroundResource( engine.lines[engine.line].cnf ? R.drawable.sel_green : R.drawable.sel_grey );
callButton.setBackgroundResource( engine.lines[engine.line].incall ? R.drawable.phone_red : R.drawable.phone_green );
} catch (Exception e) {
JFLog.log(e);
}
}
/** TimerTask executed every 250ms to change the line lights(icons). */
private class ButtonColorUpdater extends TimerTask {
private boolean odd = false;
public void run() {
//JFLog.log( "ButtonColorUpdater:line=" + engine.line);
try {
int clr = R.drawable.black;
for(int a=0;a<6;a++) {
if ((engine.lines[a].sip != null) && (engine.lines[a].sip.isRegistered())) {
clr = (engine.line == a ? R.drawable.sel_grey : R.drawable.grey);
if (engine.lines[a].msgwaiting) {
if (odd) clr = (engine.line == a ? R.drawable.sel_orange : R.drawable.orange);
}
if (engine.lines[a].incoming) {
if (odd) clr = (engine.line == a ? R.drawable.sel_green : R.drawable.green);
else clr = (engine.line == a ? R.drawable.sel_grey : R.drawable.grey);
} else if (engine.lines[a].incall) clr = (engine.line == a ? R.drawable.sel_green : R.drawable.green);
} else {
if (engine.lines[a].unauth)
clr = (engine.line == a ? R.drawable.sel_red : R.drawable.red);
else
clr = (engine.line == a ? R.drawable.sel_black : R.drawable.black);
}
if (engine.lines[a].clr != clr) {
//JFLog.log( "ButtonColorUpdater:line=" + (a+1) + "=" + clr);
_setBackgroundResource(lineButtons[a], clr);
engine.lines[a].clr = clr;
}
}
odd = !odd;
} catch (Exception e) {
JFLog.log(e);
}
}
}
/** Starts a call or accepts an inbound call. (may!UI thread) */
public void call() {
try {
engine.call();
_updateScreen();
} catch (Exception e) {
JFLog.log(e);
}
}
public void redial() {
try {
engine.redial();
updateScreen();
} catch (Exception e) {
JFLog.log(e);
}
}
public void about() {
try {
showDialog(DIALOG_ABOUT_ID);
} catch (Exception e) {
JFLog.log(e);
}
}
public void showSettings() {
try {
for(int a=0;a<6;a++) {
if (engine.lines[a].incall) return;
}
engine.uninit();
Intent intent = new Intent(this, ViewSettings.class);
startActivityForResult(intent, VIEW_SETTINGS);
} catch (Exception e) {
JFLog.log(e);
}
}
//these members call the same member without the underscore in the UI thread
public void _updateScreen() {
try {
handler.post(new Runnable() {public void run() { updateScreen(); }});
} catch (Exception e) {
JFLog.log(e);
}
}
public static void _setBackgroundResource(Button b, int clr) {
try {
handler.post(new Runnable() {
private Button b;
private int clr;
public void run() { b.setBackgroundResource(clr); }
public Runnable init(Button b, int clr) { this.b = b; this.clr = clr; return this;}
}.init(b, clr));
} catch (Exception e) {
JFLog.log(e);
}
}
}