blob: a4058ab7a040d9e545547cc26722a55e28fdabf3 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.sip.demo;
import com.android.settings.sip.ProfileUtil;
import com.android.settings.sip.R;
import com.android.settings.sip.SipSettings;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.sip.SipProfile;
import android.net.sip.SipManager;
import android.net.sip.SipRegistrationListener;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
*/
public class SipCallSetup extends Activity implements OnClickListener {
public static final String INCOMING_CALL_ACTION =
SipSettings.INCOMING_CALL_ACTION;
private static final String TAG = SipCallSetup.class.getSimpleName();
private static final String CALLEE_SET_PATH = "/sdcard/teseellacpis";
private TextView mMyIp;
private TextView mCallStatus;
private AutoCompleteTextView mCallee;
private Spinner mCaller;
private Button mCallButton;
private Button mRegisterButton;
private Button mSettingsButton;
private Set<String> mCalleeSet;
private SipManager mSipManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.call_setup);
mCallStatus = (TextView) findViewById(R.id.status);
mMyIp = (TextView) findViewById(R.id.localip);
mCallee = (AutoCompleteTextView) findViewById(R.id.callee);
mCaller = (Spinner) findViewById(R.id.caller);
mCallButton = (Button) findViewById(R.id.call_btn);
mRegisterButton = (Button) findViewById(R.id.register_btn);
mSettingsButton = (Button) findViewById(R.id.settings_btn);
((TextView) findViewById(R.id.localip_title)).setText("Local IP:");
((TextView) findViewById(R.id.status_title)).setText("Status:");
((TextView) findViewById(R.id.caller_title)).setText("Who am I");
((TextView) findViewById(R.id.callee_title)).setText("Who to call");
mCallButton.setText("Call");
mRegisterButton.setText("Register");
mSettingsButton.setText("Settings");
mCallButton.setOnClickListener(this);
mRegisterButton.setOnClickListener(this);
mSettingsButton.setOnClickListener(this);
new Thread(new Runnable() {
public void run() {
setText(mMyIp, getLocalIp());
mSipManager = SipManager.getInstance(SipCallSetup.this);
setRegistrationListener(createRegistrationListener());
setCallerSpinnerListener();
}
}).start();
getCalleeSet();
setupCallees();
}
@Override
protected void onResume() {
super.onResume();
setupCallers();
setCallStatus("...");
setRegistrationListener(createRegistrationListener());
}
@Override
protected void onPause() {
super.onPause();
setRegistrationListener(null);
}
private void setupCallers() {
List<ProfileWrapper> profiles = getSipProfiles();
Log.v(TAG, "profiles read: " + profiles.size());
ArrayAdapter adapter = new ArrayAdapter(
this, android.R.layout.simple_spinner_item, profiles);
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
ProfileWrapper profileWrapper = (ProfileWrapper)
mCaller.getSelectedItem();
mCaller.setAdapter(adapter);
// restore selection
if (profileWrapper == null) return;
SipProfile profile = profileWrapper.mProfile;
for (ProfileWrapper w : profiles) {
if (w.mProfile.getUriString().equals(profile.getUriString())) {
mCaller.setSelection(profiles.indexOf(w));
break;
}
}
}
private void setupCallees() {
String[] callees = new String[mCalleeSet.size()];
Log.v(TAG, "callees: " + callees.length);
mCalleeSet.toArray(callees);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, callees);
mCallee.setAdapter(adapter);
}
private void setCallerSpinnerListener() {
mCaller.setOnItemSelectedListener(
new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
SipProfile profile = getProfile(position);
boolean registered = false;
try {
registered = mSipManager.isRegistered(
profile.getUriString());
} catch (Exception e) {
Log.e(TAG, "OnItemSelected: " + e);
}
setCallStatus(
registered ? "Registered" : "Unregistered");
}
public void onNothingSelected(AdapterView<?> parent) {
// no-op
}
});
}
private List<ProfileWrapper> getSipProfiles() {
List<SipProfile> profiles = ProfileUtil.retrieveSipProfiles(
getFilesDir().getAbsolutePath());
List<ProfileWrapper> wrappers =
new ArrayList<ProfileWrapper>(profiles.size());
for (SipProfile p : profiles) {
wrappers.add(new ProfileWrapper(p));
}
return wrappers;
}
private void setCallStatus(Throwable e) {
setCallStatus(e.toString());
}
private void setCallStatus(String message) {
setText(mCallStatus, message);
}
public synchronized void onClick(View v) {
if (mCallButton == v) {
makeCall();
} else if (mRegisterButton == v) {
register();
} else if (mSettingsButton == v) {
String action = "android.net.sip.NOTIFY";
startActivity(new Intent(action));
}
}
private void makeCall() {
String callee = mCallee.getText().toString();
ProfileWrapper caller = (ProfileWrapper) mCaller.getSelectedItem();
Log.v(TAG, "calling " + callee + " from " + caller);
if (caller == null) {
showToast("Press 'Settings' to set up a SIP profile");
return;
}
if (TextUtils.isEmpty(callee)) {
showToast("No one to call to.");
return;
}
if (!callee.contains("@")) {
callee += "@" + caller.mProfile.getSipDomain();
mCallee.setText(callee);
}
updateCalleeSet(callee);
call(caller.mProfile, callee);
}
private void call(SipProfile caller, String callee) {
Intent intent = new Intent(this, SipCallUi.class);
intent.setAction("call");
intent.putExtra("caller", (Parcelable) caller);
intent.putExtra("callee", callee);
startActivity(intent);
}
private void register() {
ProfileWrapper myself = (ProfileWrapper) mCaller.getSelectedItem();
if (myself == null) return;
try {
if (mSipManager.isOpened(myself.mProfile.getUriString())) {
mSipManager.register(myself.mProfile, 3600,
createRegistrationListener());
} else {
mSipManager.open(myself.mProfile, INCOMING_CALL_ACTION,
createRegistrationListener());
}
} catch (Exception e) {
Log.e(TAG, "register()", e);
setCallStatus(e);
}
}
private synchronized void setRegistrationListener(
SipRegistrationListener listener) {
if (mSipManager == null) return;
SpinnerAdapter adapter = mCaller.getAdapter();
for (int i = 0, count = adapter.getCount(); i < count; i++) {
SipProfile profile = ((ProfileWrapper) adapter.getItem(i)).mProfile;
try {
mSipManager.setRegistrationListener(profile.getUriString(),
listener);
} catch (Exception e) {
Log.e(TAG, "setRegistrationListener()", e);
}
}
}
private SipProfile getProfile(int position) {
return ((ProfileWrapper) mCaller.getAdapter().getItem(position))
.mProfile;
}
private SipRegistrationListener createRegistrationListener() {
return new SipRegistrationListener() {
public void onRegistrationDone(String uri, long expiryTime) {
setCallStatus("Registered");
showToast("Registration done: " + uri);
}
public void onRegistrationFailed(String uri, String className,
String message) {
setCallStatus("failed to register " + uri + ": " + message);
showToast("Registration failed");
}
public void onRegistering(String uri) {
setCallStatus("Registering...");
showToast("Registering " + uri + "...");
}
};
}
private void updateCalleeSet(String callee) {
if (mCalleeSet.contains(callee)) return;
try {
mCalleeSet.add(callee);
setupCallees();
saveCalleeSet();
} catch (IOException e) {
Log.v(TAG, "updateCalleeSet", e);
}
}
private void getCalleeSet() {
File f = new File(CALLEE_SET_PATH);
if (f.exists()) {
try {
mCalleeSet = retrieveCalleeSet(f);
} catch (IOException e) {
Log.v(TAG, "getCalleeSet", e);
}
} else {
mCalleeSet = new HashSet<String>();
}
}
private void saveCalleeSet() throws IOException {
File f = new File(CALLEE_SET_PATH);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
oos.writeObject(mCalleeSet);
oos.close();
}
private Set<String> retrieveCalleeSet(File setFile) throws IOException {
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
setFile));
Set<String> s = (Set<String>) ois.readObject();
ois.close();
return s;
} catch (ClassNotFoundException e) {
Log.d(TAG, "deserialize a profile", e);
return null;
}
}
private void setText(final TextView view, final String text) {
runOnUiThread(new Runnable() {
public void run() {
view.setText(text);
}
});
}
private String getLocalIp() {
try {
DatagramSocket s = new DatagramSocket();
s.connect(InetAddress.getByName("192.168.1.1"), 80);
return s.getLocalAddress().getHostAddress();
} catch (IOException e) {
Log.w(TAG, "getLocalIp(): " + e);
return "127.0.0.1";
}
}
private void showToast(final String message) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(SipCallSetup.this, message, Toast.LENGTH_SHORT)
.show();
}
});
}
private static class ProfileWrapper {
SipProfile mProfile;
ProfileWrapper(SipProfile p) {
mProfile = p;
}
public String toString() {
SipProfile p = mProfile;
String protocol = p.getProtocol();
if (protocol.toUpperCase().equals("UDP")) {
protocol = "";
} else {
protocol = "(" + protocol + ")";
}
return p.getUserName() + "@" + p.getSipDomain() + protocol;
}
}
}