| /* |
| * 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.example.android.sip; |
| |
| import android.app.Activity; |
| import android.app.AlertDialog; |
| import android.app.Dialog; |
| import android.app.PendingIntent; |
| import android.content.DialogInterface; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.content.SharedPreferences; |
| import android.os.Bundle; |
| import android.preference.PreferenceManager; |
| import android.util.Log; |
| import android.view.*; |
| import android.net.sip.*; |
| import android.widget.EditText; |
| import android.widget.TextView; |
| import android.widget.ToggleButton; |
| |
| import java.text.ParseException; |
| |
| /** |
| * Handles all calling, receiving calls, and UI interaction in the WalkieTalkie app. |
| */ |
| public class WalkieTalkieActivity extends Activity implements View.OnTouchListener { |
| |
| public String sipAddress = null; |
| |
| public SipManager manager = null; |
| public SipProfile me = null; |
| public SipAudioCall call = null; |
| public IncomingCallReceiver callReceiver; |
| |
| private static final int CALL_ADDRESS = 1; |
| private static final int SET_AUTH_INFO = 2; |
| private static final int UPDATE_SETTINGS_DIALOG = 3; |
| private static final int HANG_UP = 4; |
| |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.walkietalkie); |
| |
| ToggleButton pushToTalkButton = (ToggleButton) findViewById(R.id.pushToTalk); |
| pushToTalkButton.setOnTouchListener(this); |
| |
| // Set up the intent filter. This will be used to fire an |
| // IncomingCallReceiver when someone calls the SIP address used by this |
| // application. |
| IntentFilter filter = new IntentFilter(); |
| filter.addAction("android.SipDemo.INCOMING_CALL"); |
| callReceiver = new IncomingCallReceiver(); |
| this.registerReceiver(callReceiver, filter); |
| |
| // "Push to talk" can be a serious pain when the screen keeps turning off. |
| // Let's prevent that. |
| getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); |
| |
| initializeManager(); |
| } |
| |
| @Override |
| public void onStart() { |
| super.onStart(); |
| // When we get back from the preference setting Activity, assume |
| // settings have changed, and re-login with new auth info. |
| initializeManager(); |
| } |
| |
| @Override |
| public void onDestroy() { |
| super.onDestroy(); |
| if (call != null) { |
| call.close(); |
| } |
| |
| closeLocalProfile(); |
| |
| if (callReceiver != null) { |
| this.unregisterReceiver(callReceiver); |
| } |
| } |
| |
| public void initializeManager() { |
| if(manager == null) { |
| manager = SipManager.newInstance(this); |
| } |
| |
| initializeLocalProfile(); |
| } |
| |
| /** |
| * Logs you into your SIP provider, registering this device as the location to |
| * send SIP calls to for your SIP address. |
| */ |
| public void initializeLocalProfile() { |
| if (manager == null) { |
| return; |
| } |
| |
| if (me != null) { |
| closeLocalProfile(); |
| } |
| |
| SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); |
| String username = prefs.getString("namePref", ""); |
| String domain = prefs.getString("domainPref", ""); |
| String password = prefs.getString("passPref", ""); |
| |
| if (username.length() == 0 || domain.length() == 0 || password.length() == 0) { |
| showDialog(UPDATE_SETTINGS_DIALOG); |
| return; |
| } |
| |
| try { |
| SipProfile.Builder builder = new SipProfile.Builder(username, domain); |
| builder.setPassword(password); |
| me = builder.build(); |
| |
| Intent i = new Intent(); |
| i.setAction("android.SipDemo.INCOMING_CALL"); |
| PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA); |
| manager.open(me, pi, null); |
| |
| |
| // This listener must be added AFTER manager.open is called, |
| // Otherwise the methods aren't guaranteed to fire. |
| |
| manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() { |
| public void onRegistering(String localProfileUri) { |
| updateStatus("Registering with SIP Server..."); |
| } |
| |
| public void onRegistrationDone(String localProfileUri, long expiryTime) { |
| updateStatus("Ready"); |
| } |
| |
| public void onRegistrationFailed(String localProfileUri, int errorCode, |
| String errorMessage) { |
| updateStatus("Registration failed. Please check settings."); |
| } |
| }); |
| } catch (ParseException pe) { |
| updateStatus("Connection Error."); |
| } catch (SipException se) { |
| updateStatus("Connection error."); |
| } |
| } |
| |
| /** |
| * Closes out your local profile, freeing associated objects into memory |
| * and unregistering your device from the server. |
| */ |
| public void closeLocalProfile() { |
| if (manager == null) { |
| return; |
| } |
| try { |
| if (me != null) { |
| manager.close(me.getUriString()); |
| } |
| } catch (Exception ee) { |
| Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee); |
| } |
| } |
| |
| /** |
| * Make an outgoing call. |
| */ |
| public void initiateCall() { |
| |
| updateStatus(sipAddress); |
| |
| try { |
| SipAudioCall.Listener listener = new SipAudioCall.Listener() { |
| // Much of the client's interaction with the SIP Stack will |
| // happen via listeners. Even making an outgoing call, don't |
| // forget to set up a listener to set things up once the call is established. |
| @Override |
| public void onCallEstablished(SipAudioCall call) { |
| call.startAudio(); |
| call.setSpeakerMode(true); |
| call.toggleMute(); |
| updateStatus(call); |
| } |
| |
| @Override |
| public void onCallEnded(SipAudioCall call) { |
| updateStatus("Ready."); |
| } |
| }; |
| |
| call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30); |
| |
| } |
| catch (Exception e) { |
| Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e); |
| if (me != null) { |
| try { |
| manager.close(me.getUriString()); |
| } catch (Exception ee) { |
| Log.i("WalkieTalkieActivity/InitiateCall", |
| "Error when trying to close manager.", ee); |
| ee.printStackTrace(); |
| } |
| } |
| if (call != null) { |
| call.close(); |
| } |
| } |
| } |
| |
| /** |
| * Updates the status box at the top of the UI with a messege of your choice. |
| * @param status The String to display in the status box. |
| */ |
| public void updateStatus(final String status) { |
| // Be a good citizen. Make sure UI changes fire on the UI thread. |
| this.runOnUiThread(new Runnable() { |
| public void run() { |
| TextView labelView = (TextView) findViewById(R.id.sipLabel); |
| labelView.setText(status); |
| } |
| }); |
| } |
| |
| /** |
| * Updates the status box with the SIP address of the current call. |
| * @param call The current, active call. |
| */ |
| public void updateStatus(SipAudioCall call) { |
| String useName = call.getPeerProfile().getDisplayName(); |
| if(useName == null) { |
| useName = call.getPeerProfile().getUserName(); |
| } |
| updateStatus(useName + "@" + call.getPeerProfile().getSipDomain()); |
| } |
| |
| /** |
| * Updates whether or not the user's voice is muted, depending on whether the button is pressed. |
| * @param v The View where the touch event is being fired. |
| * @param event The motion to act on. |
| * @return boolean Returns false to indicate that the parent view should handle the touch event |
| * as it normally would. |
| */ |
| public boolean onTouch(View v, MotionEvent event) { |
| if (call == null) { |
| return false; |
| } else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) { |
| call.toggleMute(); |
| } else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) { |
| call.toggleMute(); |
| } |
| return false; |
| } |
| |
| public boolean onCreateOptionsMenu(Menu menu) { |
| menu.add(0, CALL_ADDRESS, 0, "Call someone"); |
| menu.add(0, SET_AUTH_INFO, 0, "Edit your SIP Info."); |
| menu.add(0, HANG_UP, 0, "End Current Call."); |
| |
| return true; |
| } |
| |
| public boolean onOptionsItemSelected(MenuItem item) { |
| switch (item.getItemId()) { |
| case CALL_ADDRESS: |
| showDialog(CALL_ADDRESS); |
| break; |
| case SET_AUTH_INFO: |
| updatePreferences(); |
| break; |
| case HANG_UP: |
| if(call != null) { |
| try { |
| call.endCall(); |
| } catch (SipException se) { |
| Log.d("WalkieTalkieActivity/onOptionsItemSelected", |
| "Error ending call.", se); |
| } |
| call.close(); |
| } |
| break; |
| } |
| return true; |
| } |
| |
| @Override |
| protected Dialog onCreateDialog(int id) { |
| switch (id) { |
| case CALL_ADDRESS: |
| |
| LayoutInflater factory = LayoutInflater.from(this); |
| final View textBoxView = factory.inflate(R.layout.call_address_dialog, null); |
| return new AlertDialog.Builder(this) |
| .setTitle("Call Someone.") |
| .setView(textBoxView) |
| .setPositiveButton( |
| android.R.string.ok, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| EditText textField = (EditText) |
| (textBoxView.findViewById(R.id.calladdress_edit)); |
| sipAddress = textField.getText().toString(); |
| initiateCall(); |
| |
| } |
| }) |
| .setNegativeButton( |
| android.R.string.cancel, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| // Noop. |
| } |
| }) |
| .create(); |
| |
| case UPDATE_SETTINGS_DIALOG: |
| return new AlertDialog.Builder(this) |
| .setMessage("Please update your SIP Account Settings.") |
| .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| updatePreferences(); |
| } |
| }) |
| .setNegativeButton( |
| android.R.string.cancel, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| // Noop. |
| } |
| }) |
| .create(); |
| } |
| return null; |
| } |
| |
| public void updatePreferences() { |
| Intent settingsActivity = new Intent(getBaseContext(), |
| SipSettings.class); |
| startActivity(settingsActivity); |
| } |
| } |