summaryrefslogtreecommitdiff
path: root/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MainActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MainActivity.java')
-rw-r--r--pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MainActivity.java497
1 files changed, 497 insertions, 0 deletions
diff --git a/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MainActivity.java b/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MainActivity.java
new file mode 100644
index 00000000..34633f97
--- /dev/null
+++ b/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MainActivity.java
@@ -0,0 +1,497 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package org.pjsip.pjsua2.app;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.pjsip.pjsua2.*;
+
+public class MainActivity extends Activity implements Handler.Callback, MyAppObserver {
+ public static MyApp app = null;
+ public static MyCall currentCall = null;
+ public static MyAccount account = null;
+ public static AccountConfig accCfg = null;
+
+ private ListView buddyListView;
+ private SimpleAdapter buddyListAdapter;
+ private int buddyListSelectedIdx = -1;
+ ArrayList<Map<String, String>> buddyList;
+ private String lastRegStatus = "";
+
+ private final Handler handler = new Handler(this);
+ public class MSG_TYPE {
+ public final static int INCOMING_CALL = 1;
+ public final static int CALL_STATE = 2;
+ public final static int REG_STATE = 3;
+ public final static int BUDDY_STATE = 4;
+ }
+
+ private HashMap<String, String> putData(String uri, String status) {
+ HashMap<String, String> item = new HashMap<String, String>();
+ item.put("uri", uri);
+ item.put("status", status);
+ return item;
+ }
+
+ private void showCallActivity() {
+ Intent intent = new Intent(this, CallActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ if (app == null) {
+ app = new MyApp();
+ /* Wait for GDB to init */
+ if ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {}
+ }
+
+ app.init(this, getFilesDir().getAbsolutePath());
+ }
+
+ if (app.accList.size() == 0) {
+ accCfg = new AccountConfig();
+ accCfg.setIdUri("sip:localhost");
+ account = app.addAcc(accCfg);
+ } else {
+ account = app.accList.get(0);
+ accCfg = account.cfg;
+ }
+
+ buddyList = new ArrayList<Map<String, String>>();
+ for (int i = 0; i < account.buddyList.size(); i++) {
+ buddyList.add(putData(account.buddyList.get(i).cfg.getUri(),
+ account.buddyList.get(i).getStatusText()));
+ }
+
+ String[] from = { "uri", "status" };
+ int[] to = { android.R.id.text1, android.R.id.text2 };
+ buddyListAdapter = new SimpleAdapter(this, buddyList, android.R.layout.simple_list_item_2, from, to);
+
+ buddyListView = (ListView) findViewById(R.id.listViewBuddy);;
+ buddyListView.setAdapter(buddyListAdapter);
+ buddyListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, final View view,
+ int position, long id)
+ {
+ view.setSelected(true);
+ buddyListSelectedIdx = position;
+ }
+ });
+
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_acc_config:
+ dlgAccountSetting();
+ break;
+
+ case R.id.action_quit:
+ Message m = Message.obtain(handler, 0);
+ m.sendToTarget();
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handleMessage(Message m) {
+
+ if (m.what == 0) {
+
+ app.deinit();
+ finish();
+ Runtime.getRuntime().gc();
+ android.os.Process.killProcess(android.os.Process.myPid());
+
+ } else if (m.what == MSG_TYPE.CALL_STATE) {
+
+ CallInfo ci = (CallInfo) m.obj;
+
+ /* Forward the message to CallActivity */
+ if (CallActivity.handler_ != null) {
+ Message m2 = Message.obtain(CallActivity.handler_, MSG_TYPE.CALL_STATE, ci);
+ m2.sendToTarget();
+ }
+
+ if (ci.getState() == pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED)
+ currentCall = null;
+
+ } else if (m.what == MSG_TYPE.BUDDY_STATE) {
+
+ MyBuddy buddy = (MyBuddy) m.obj;
+ int idx = account.buddyList.indexOf(buddy);
+ if (idx >= 0) {
+ buddyList.get(idx).put("status", buddy.getStatusText());
+ buddyListAdapter.notifyDataSetChanged();
+ // TODO: selection color/mark is gone after this,
+ // dont know how to return it back.
+ //buddyListView.setSelection(buddyListSelectedIdx);
+ //buddyListView.performItemClick(buddyListView, buddyListSelectedIdx,
+ // buddyListView.getItemIdAtPosition(buddyListSelectedIdx));
+
+ /* Return back Call activity */
+ notifyCallState(currentCall);
+ }
+
+ } else if (m.what == MSG_TYPE.REG_STATE) {
+
+ String msg_str = (String) m.obj;
+ lastRegStatus = msg_str;
+
+ } else if (m.what == MSG_TYPE.INCOMING_CALL) {
+
+ /* Incoming call */
+ final MyCall call = (MyCall) m.obj;
+ CallOpParam prm = new CallOpParam();
+
+ /* Only one call at anytime */
+ if (currentCall != null) {
+ prm.setStatusCode(pjsip_status_code.PJSIP_SC_BUSY_HERE);
+ try {
+ call.hangup(prm);
+ } catch (Exception e) {}
+ return true;
+ }
+
+ /* Answer with ringing */
+ prm.setStatusCode(pjsip_status_code.PJSIP_SC_RINGING);
+ try {
+ call.answer(prm);
+ } catch (Exception e) {}
+
+ currentCall = call;
+ showCallActivity();
+
+ } else {
+
+ /* Message not handled */
+ return false;
+
+ }
+
+ return true;
+ }
+
+
+ private void dlgAccountSetting() {
+
+ LayoutInflater li = LayoutInflater.from(this);
+ View view = li.inflate(R.layout.dlg_account_config, null);
+
+ if (!lastRegStatus.isEmpty()) {
+ TextView tvInfo = (TextView)view.findViewById(R.id.textViewInfo);
+ tvInfo.setText("Last status: " + lastRegStatus);
+ }
+
+ AlertDialog.Builder adb = new AlertDialog.Builder(this);
+ adb.setView(view);
+ adb.setTitle("Account Settings");
+
+ final EditText etId = (EditText)view.findViewById(R.id.editTextId);
+ final EditText etReg = (EditText)view.findViewById(R.id.editTextRegistrar);
+ final EditText etProxy = (EditText)view.findViewById(R.id.editTextProxy);
+ final EditText etUser = (EditText)view.findViewById(R.id.editTextUsername);
+ final EditText etPass = (EditText)view.findViewById(R.id.editTextPassword);
+
+ etId. setText(accCfg.getIdUri());
+ etReg. setText(accCfg.getRegConfig().getRegistrarUri());
+ StringVector proxies = accCfg.getSipConfig().getProxies();
+ if (proxies.size() > 0)
+ etProxy.setText(proxies.get(0));
+ else
+ etProxy.setText("");
+ AuthCredInfoVector creds = accCfg.getSipConfig().getAuthCreds();
+ if (creds.size() > 0) {
+ etUser. setText(creds.get(0).getUsername());
+ etPass. setText(creds.get(0).getData());
+ } else {
+ etUser. setText("");
+ etPass. setText("");
+ }
+
+ adb.setCancelable(false);
+ adb.setPositiveButton("OK",
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,int id) {
+ String acc_id = etId.getText().toString();
+ String registrar = etReg.getText().toString();
+ String proxy = etProxy.getText().toString();
+ String username = etUser.getText().toString();
+ String password = etPass.getText().toString();
+
+ accCfg.setIdUri(acc_id);
+ accCfg.getRegConfig().setRegistrarUri(registrar);
+ AuthCredInfoVector creds = accCfg.getSipConfig().getAuthCreds();
+ creds.clear();
+ if (!username.isEmpty()) {
+ creds.add(new AuthCredInfo("Digest", "*", username, 0, password));
+ }
+ StringVector proxies = accCfg.getSipConfig().getProxies();
+ proxies.clear();
+ if (!proxy.isEmpty()) {
+ proxies.add(proxy);
+ }
+
+ /* Finally */
+ lastRegStatus = "";
+ try {
+ account.modify(accCfg);
+ } catch (Exception e) {}
+ }
+ });
+ adb.setNegativeButton("Cancel",
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,int id) {
+ dialog.cancel();
+ }
+ });
+
+ AlertDialog ad = adb.create();
+ ad.show();
+ }
+
+
+ public void makeCall(View view) {
+ if (buddyListSelectedIdx == -1)
+ return;
+
+ /* Only one call at anytime */
+ if (currentCall != null) {
+ return;
+ }
+
+ HashMap<String, String> item = (HashMap<String, String>) buddyListView.getItemAtPosition(buddyListSelectedIdx);
+ String buddy_uri = item.get("uri");
+
+ MyCall call = new MyCall(account, -1);
+ CallOpParam prm = new CallOpParam();
+ CallSetting opt = prm.getOpt();
+ opt.setAudioCount(1);
+ opt.setVideoCount(0);
+
+ try {
+ call.makeCall(buddy_uri, prm);
+ } catch (Exception e) {
+ currentCall = null;
+ return;
+ }
+
+ currentCall = call;
+ showCallActivity();
+ }
+
+ private void dlgAddEditBuddy(BuddyConfig initial) {
+ final BuddyConfig cfg = new BuddyConfig();
+ final BuddyConfig old_cfg = initial;
+ final boolean is_add = initial == null;
+
+ LayoutInflater li = LayoutInflater.from(this);
+ View view = li.inflate(R.layout.dlg_add_buddy, null);
+
+ AlertDialog.Builder adb = new AlertDialog.Builder(this);
+ adb.setView(view);
+
+ final EditText etUri = (EditText)view.findViewById(R.id.editTextUri);
+ final CheckBox cbSubs = (CheckBox)view.findViewById(R.id.checkBoxSubscribe);
+
+ if (is_add) {
+ adb.setTitle("Add Buddy");
+ } else {
+ adb.setTitle("Edit Buddy");
+ etUri. setText(initial.getUri());
+ cbSubs.setChecked(initial.getSubscribe());
+ }
+
+ adb.setCancelable(false);
+ adb.setPositiveButton("OK",
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,int id) {
+ cfg.setUri(etUri.getText().toString());
+ cfg.setSubscribe(cbSubs.isChecked());
+
+ if (is_add) {
+ account.addBuddy(cfg);
+ buddyList.add(putData(cfg.getUri(), ""));
+ buddyListAdapter.notifyDataSetChanged();
+ buddyListSelectedIdx = -1;
+ } else {
+ if (!old_cfg.getUri().equals(cfg.getUri())) {
+ account.delBuddy(buddyListSelectedIdx);
+ account.addBuddy(cfg);
+ buddyList.remove(buddyListSelectedIdx);
+ buddyList.add(putData(cfg.getUri(), ""));
+ buddyListAdapter.notifyDataSetChanged();
+ buddyListSelectedIdx = -1;
+ } else if (old_cfg.getSubscribe() != cfg.getSubscribe()) {
+ MyBuddy bud = account.buddyList.get(buddyListSelectedIdx);
+ try {
+ bud.subscribePresence(cfg.getSubscribe());
+ } catch (Exception e) {}
+ }
+ }
+ }
+ });
+ adb.setNegativeButton("Cancel",
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,int id) {
+ dialog.cancel();
+ }
+ });
+
+ AlertDialog ad = adb.create();
+ ad.show();
+ }
+
+ public void addBuddy(View view) {
+ dlgAddEditBuddy(null);
+ }
+
+ public void editBuddy(View view) {
+ if (buddyListSelectedIdx == -1)
+ return;
+
+ BuddyConfig old_cfg = account.buddyList.get(buddyListSelectedIdx).cfg;
+ dlgAddEditBuddy(old_cfg);
+ }
+
+ public void delBuddy(View view) {
+ if (buddyListSelectedIdx == -1)
+ return;
+
+ final HashMap<String, String> item = (HashMap<String, String>) buddyListView.getItemAtPosition(buddyListSelectedIdx);
+ String buddy_uri = item.get("uri");
+
+ DialogInterface.OnClickListener ocl = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ account.delBuddy(buddyListSelectedIdx);
+ buddyList.remove(item);
+ buddyListAdapter.notifyDataSetChanged();
+ buddyListSelectedIdx = -1;
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ break;
+ }
+ }
+ };
+
+ AlertDialog.Builder adb = new AlertDialog.Builder(this);
+ adb.setTitle(buddy_uri);
+ adb.setMessage("\nDelete this buddy?\n");
+ adb.setPositiveButton("Yes", ocl);
+ adb.setNegativeButton("No", ocl);
+ adb.show();
+ }
+
+
+ /*
+ * === MyAppObserver ===
+ *
+ * As we cannot do UI from worker thread, the callbacks mostly just send
+ * a message to UI/main thread.
+ */
+
+ public void notifyIncomingCall(MyCall call) {
+ Message m = Message.obtain(handler, MSG_TYPE.INCOMING_CALL, call);
+ m.sendToTarget();
+ }
+
+ public void notifyRegState(pjsip_status_code code, String reason, int expiration) {
+ String msg_str = "";
+ if (expiration == 0)
+ msg_str += "Unregistration";
+ else
+ msg_str += "Registration";
+
+ if (code.swigValue()/100 == 2)
+ msg_str += " successful";
+ else
+ msg_str += " failed: " + reason;
+
+ Message m = Message.obtain(handler, MSG_TYPE.REG_STATE, msg_str);
+ m.sendToTarget();
+ }
+
+ public void notifyCallState(MyCall call) {
+ if (currentCall == null || call.getId() != currentCall.getId())
+ return;
+
+ CallInfo ci;
+ try {
+ ci = call.getInfo();
+ } catch (Exception e) {
+ ci = null;
+ }
+ Message m = Message.obtain(handler, MSG_TYPE.CALL_STATE, ci);
+ m.sendToTarget();
+ }
+
+ public void notifyBuddyState(MyBuddy buddy) {
+ Message m = Message.obtain(handler, MSG_TYPE.BUDDY_STATE, buddy);
+ m.sendToTarget();
+ }
+
+ /* === end of MyAppObserver ==== */
+
+}