Implement Android dialer integration

This commit is contained in:
Jehan Monnier 2010-06-25 11:23:49 +02:00
parent e41ca841fa
commit ac7944f668
11 changed files with 173 additions and 55 deletions

View file

@ -13,6 +13,11 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.CALL" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
</activity>
<activity android:name=".LinphonePreferencesActivity">
@ -24,11 +29,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.CALL" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
</activity>
<activity android:name=".ContactPickerActivity">
<intent-filter>
@ -44,7 +45,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
</activity>
<service android:name=".LinphoneService">
</service>
<receiver android:name="NetworkManager">
@ -55,6 +56,10 @@
<intent-filter android:priority="0"><action android:name="android.intent.action.NEW_OUTGOING_CALL"></action>
</intent-filter>
</receiver>
<receiver android:name="BootReceiver" >
<intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
@ -64,5 +69,8 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"></uses-permission>
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
<uses-permission android:name="android.permission.BOOT_COMPLETED"></uses-permission>
</manifest>

Binary file not shown.

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:padding="6dip" android:layout_height="wrap_content"
android:id="@+id/outcall_chooser_linear_v" android:layout_width="fill_parent"
android:gravity="center">
<LinearLayout android:id="@+id/LinearLayout02"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:layout_weight="0.5" android:gravity="center">
<ImageButton android:layout_width="wrap_content"
android:layout_height="wrap_content" android:src="@drawable/logo_linphone_57x57"
android:id="@+id/outcall_chooser_linphone_button" android:background="@android:color/transparent"></ImageButton>
</LinearLayout>
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_width="fill_parent" android:layout_weight=".5"
android:gravity="center" android:layout_height="fill_parent">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="@string/outcall_chooser_cellular"
android:layout_below="@+id/outcall_text" android:layout_alignRight="@+id/outcall_text"
android:id="@+id/outcall_chooser_cellular_button"></Button>
</LinearLayout>
</LinearLayout>

View file

@ -1,5 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pref_handle_outcall_summarry">If set cellular call are redirected to voip when possible</string>
<string name="pref_handle_outcall">Redirect cellular calls</string>
<string name="pref_handle_outcall_key">pref_handle_outcall_key</string>
<string name="pref_autostart">Start at boot time</string>
<string name="pref_autostart_key">pref_autostart_key</string>
<string name="outcall_chooser_cellular">Cellular</string>
<string name="outcall_chooser_text">Choose application to call %s</string>
<string name="pref_enable_outbound_proxy">Outbound proxy</string>
<string name="pref_enable_outbound_proxy_key">Outbound proxy</string>
<string name="pref_codec_pcma">pcma</string>

View file

@ -25,13 +25,15 @@
android:title="@string/pref_codec_pcmu" android:defaultValue="true"></CheckBoxPreference>
<CheckBoxPreference android:key="@string/pref_codec_pcma_key"
android:title="@string/pref_codec_pcma" android:defaultValue="true"></CheckBoxPreference>
</PreferenceScreen>
<EditTextPreference android:title="@string/pref_prefix"
</PreferenceScreen><CheckBoxPreference android:title="@string/pref_autostart" android:defaultValue="true" android:key="@string/pref_autostart_key"></CheckBoxPreference>
<CheckBoxPreference android:title="@string/pref_handle_outcall" android:key="@string/pref_handle_outcall_key" android:summary="@string/pref_handle_outcall_summarry"></CheckBoxPreference><EditTextPreference android:title="@string/pref_prefix"
android:key="@string/pref_prefix_key"></EditTextPreference>
<CheckBoxPreference android:key="@string/pref_debug_key"
android:title="@string/pref_debug" android:enabled="true"></CheckBoxPreference>
</PreferenceCategory>
</PreferenceScreen>

View file

@ -0,0 +1,39 @@
/*
BootReceiver.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
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.linphone;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.preference.PreferenceManager;
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(context.getString(R.string.pref_autostart_key), true)) {
Intent lLinphoneServiceIntent = new Intent(Intent.ACTION_MAIN);
lLinphoneServiceIntent.setClass(context, LinphoneService.class);
context.startService(lLinphoneServiceIntent);;
}
}
}

View file

@ -115,7 +115,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
try {
mAddress = (TextView) findViewById(R.id.SipUri);
mDisplayNameView = (TextView) findViewById(R.id.DisplayNameView);
@ -158,31 +158,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
}
return;
}
if (lLinphoneCore.isIncall()) {
Toast toast = Toast.makeText(DialerActivity.this, getString(R.string.warning_already_incall), Toast.LENGTH_LONG);
toast.show();
return;
}
LinphoneAddress lAddress;
try {
lAddress = lLinphoneCore.interpretUrl( mAddress.getText().toString());
} catch (LinphoneCoreException e) {
Toast toast = Toast.makeText(DialerActivity.this
,String.format(getString(R.string.warning_wrong_destination_address),mAddress.getText().toString())
, Toast.LENGTH_LONG);
toast.show();
return;
}
lAddress.setDisplayName(mDisplayName);
try {
lLinphoneCore.invite(lAddress);
} catch (LinphoneCoreException e) {
Toast toast = Toast.makeText(DialerActivity.this
,String.format(getString(R.string.error_cannot_invite_address),mAddress.getText().toString())
, Toast.LENGTH_LONG);
toast.show();
return;
}
newOutgoingCall(mAddress.getText().toString(),mDisplayName);
}
});
@ -234,6 +210,10 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
mInCallControlRow.setVisibility(View.GONE);
mInCallAddressLayout.setVisibility(View.GONE);
mDecline.setEnabled(false);
if (LinphoneService.isready() && getIntent().getData() != null) {
newOutgoingCall(getIntent().getData().toString().substring("tel://".length()));
getIntent().setData(null);
}
if (LinphoneService.isready()) {
LinphoneCore lLinphoenCore = LinphoneService.instance().getLinphoneCore();
if (lLinphoenCore.isIncall()) {
@ -411,9 +391,15 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
if (mPref.getBoolean(PREF_CHECK_CONFIG, false) == false) {
builder.create().show();
}
} catch (Exception e ) {
Log.e(LinphoneService.TAG,"Cannot get initial config", e);
}
if (getIntent().getData() != null) {
newOutgoingCall(getIntent().getData().toString().substring("tel://".length()));
getIntent().setData(null);
}
} else if (state == GeneralState.GSTATE_REG_OK) {
//nop
} else if (state == GeneralState.GSTATE_CALL_OUT_INVITE) {
@ -502,5 +488,42 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
mDecline.setEnabled(true);
routeAudioToSpeaker();
}
public void newOutgoingCall(String aTo) {
newOutgoingCall(aTo,null);
}
public void newOutgoingCall(String aTo, String displayName) {
String lto = aTo;
if (aTo.contains(OutgoingCallReceiver.TAG)) {
lto = aTo.replace(OutgoingCallReceiver.TAG, "");
}
mAddress.setText(lto);
mDisplayName = displayName;
LinphoneCore lLinphoneCore = LinphoneService.instance().getLinphoneCore();
if (lLinphoneCore.isIncall()) {
Toast toast = Toast.makeText(DialerActivity.this, getString(R.string.warning_already_incall), Toast.LENGTH_LONG);
toast.show();
return;
}
LinphoneAddress lAddress;
try {
lAddress = lLinphoneCore.interpretUrl(lto);
} catch (LinphoneCoreException e) {
Toast toast = Toast.makeText(DialerActivity.this
,String.format(getString(R.string.warning_wrong_destination_address),mAddress.getText().toString())
, Toast.LENGTH_LONG);
toast.show();
return;
}
lAddress.setDisplayName(mDisplayName);
try {
lLinphoneCore.invite(lAddress);
} catch (LinphoneCoreException e) {
Toast toast = Toast.makeText(DialerActivity.this
,String.format(getString(R.string.error_cannot_invite_address),mAddress.getText().toString())
, Toast.LENGTH_LONG);
toast.show();
return;
}
}
}

View file

@ -100,6 +100,7 @@ public class LinphoneActivity extends TabActivity implements SensorEventListener
// dialer
Intent lDialerIntent = new Intent().setClass(this, DialerActivity.class);
lDialerIntent.setData(getIntent().getData());
// Initialize a TabSpec for each tab and add it to the TabHost
spec = lTabHost.newTabSpec("dialer").setIndicator(getString(R.string.tab_dialer),
@ -120,25 +121,15 @@ public class LinphoneActivity extends TabActivity implements SensorEventListener
hideScreen(true);
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent.getData() != null) {
//incoming call requested
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.place_call_chooser))
.setCancelable(false)
.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
;
}
}).setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
builder.create().show();
DialerActivity.getDialer().newOutgoingCall(intent.getData().toString().substring("tel://".length()));
intent.setData(null);
}
}
@ -266,4 +257,6 @@ public class LinphoneActivity extends TabActivity implements SensorEventListener
}
getWindow().setAttributes(lAttrs);
}
}

View file

@ -43,6 +43,7 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
@ -253,6 +254,7 @@ public class LinphoneService extends Service implements LinphoneCoreListener {
boolean lIsDebug = mPref.getBoolean(getString(R.string.pref_debug_key), false);
LinphoneCoreFactory.instance().setDebugMode(lIsDebug);
//1 read proxy config from preferences
String lUserName = mPref.getString(getString(R.string.pref_username_key), null);
if (lUserName == null || lUserName.length()==0) {

View file

@ -23,18 +23,36 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.preference.PreferenceManager;
public class OutgoingCallReceiver extends BroadcastReceiver {
public static String TAG = ";0000000";
@Override
public void onReceive(Context context, Intent intent) {
String to = intent.getStringExtra("android.intent.extra.PHONE_NUMBER");
setResult(Activity.RESULT_OK,null, null);
Intent lIntent = new Intent();
lIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
lIntent.setClass(context, LinphoneActivity.class);
lIntent.setData(Uri.parse("tel://"+to));
context.startActivity(lIntent);
if (!to.contains(TAG)) {
if (LinphoneService.isready() && LinphoneService.instance().getLinphoneCore().getDefaultProxyConfig()==null) {
//just return
return;
}
setResult(Activity.RESULT_OK,null, null);
Intent lIntent = new Intent();
// 1 check config
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(context.getString(R.string.pref_handle_outcall_key), false)) {
//start linphone directly
lIntent.setClass(context, LinphoneActivity.class);
} else {
//start activity chooser
lIntent.setAction(Intent.ACTION_CALL);
}
lIntent.setData(Uri.parse("tel://"+to+TAG));
lIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(lIntent);
} else {
setResult(Activity.RESULT_OK,to.replace(TAG, ""),null);
}
}
}

@ -1 +1 @@
Subproject commit a17cdb896f3df16b9715ab1a0bc57992857dfa24
Subproject commit d1f0a3cebe43f779e486825fe200c4e51940bfb2