Added sample app

This commit is contained in:
Sylvain Berfini 2014-02-20 16:01:25 +01:00
parent 13c0dc14cf
commit faafdb4399
21 changed files with 4521 additions and 0 deletions

13
sample/.classpath Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="submodules/linphone/java/j2se"/>
<classpathentry excluding="org/linphone/mediastream/MediastreamerActivity.java" kind="src" path="submodules/linphone/mediastreamer2/java/src"/>
<classpathentry kind="src" path="submodules/linphone/java/impl"/>
<classpathentry kind="src" path="submodules/linphone/java/common"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

33
sample/.project Normal file
View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>LinphoneMini</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,35 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.linphone.mini"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.CAMERA" />
<!-- Needed to allow Linphone to install on tablets, since android.permission.CAMERA implies android.hardware.camera and android.hardware.camera.autofocus are required -->
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<activity android:name=".LinphoneMiniActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

3
sample/README Normal file
View file

@ -0,0 +1,3 @@
Fist compile linphone libraries using the makefile in the parent folder (with the make command)
Then set the url to your configuration in the res/raw/linphonerc_default file
Finally install and run this app on your device (using eclipse for example)

1
sample/libs Symbolic link
View file

@ -0,0 +1 @@
../libs

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,23 @@
[net]
download_bw=380
upload_bw=380
[sip]
contact=sip:unknown@unknown-host
use_info=0
use_ipv6=0
keepalive_period=30000
[video]
size=qvga
[app]
sharing_server=https://www.linphone.org:444/upload.php
tunnel=disabled
[tunnel]
host=
port=443
[misc]
config-uri=INSERT_URL_TO_CONFIG_TO_TRY_HERE

View file

@ -0,0 +1,30 @@
[net]
mtu=1300
[sip]
guess_hostname=1
inc_timeout=15
register_only_when_network_is_up=1
auto_net_state_mon=0
auto_answer_replacing_calls=1
media_encryption_mandatory=0
ping_with_options=0
[rtp]
audio_rtp_port=7076
video_rtp_port=9078
audio_jitt_comp=60
video_jitt_comp=60
nortp_timeout=30
disable_upnp=1
[sound]
playback_dev_id=
ringer_dev_id=
capture_dev_id=
remote_ring=/data/data/org.linphone.mini/files/ringback.wav
local_ring=/data/data/org.linphone.mini/files/oldphone_mono.wav
dtmf_player_amp=0.1
[misc]
max_calls=10

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.linphone.org/xsds/lpconfig.xsd"
xmlns:tns="http://www.linphone.org/xsds/lpconfig.xsd"
elementFormDefault="qualified">
<xs:element name="config" type="tns:LPConfig"></xs:element>
<xs:complexType name="LPConfig">
<xs:sequence>
<xs:element name="section" type="tns:LPSection" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="LPSection">
<xs:sequence>
<xs:element name="entry" type="tns:LPEntry" maxOccurs="unbounded" minOccurs="0">
</xs:element>
</xs:sequence>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"></xs:minLength>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
<xs:complexType name="LPEntry">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="overwrite" type="xs:boolean"
use="optional" default="false">
</xs:attribute>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"></xs:minLength>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>

Binary file not shown.

BIN
sample/res/raw/ringback.wav Normal file

Binary file not shown.

3895
sample/res/raw/rootca.pem Normal file

File diff suppressed because it is too large Load diff

BIN
sample/res/raw/toy_mono.wav Normal file

Binary file not shown.

View file

@ -0,0 +1,11 @@
<resources>
<!--
Base application theme for API 11+. This theme completely replaces
AppBaseTheme from res/values/styles.xml on API 11+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
<!-- API 11 theme customizations can go here. -->
</style>
</resources>

View file

@ -0,0 +1,12 @@
<resources>
<!--
Base application theme for API 14+. This theme completely replaces
AppBaseTheme from BOTH res/values/styles.xml and
res/values-v11/styles.xml on API 14+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- API 14 theme customizations can go here. -->
</style>
</resources>

View file

@ -0,0 +1,5 @@
<resources>
<string name="app_name">Linphone Mini</string>
</resources>

View file

@ -0,0 +1,20 @@
<resources>
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
</resources>

View file

@ -0,0 +1,53 @@
package org.linphone.mini;
/*
LinphoneMiniActivity.java
Copyright (C) 2014 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.
*/
import android.app.Activity;
import android.os.Bundle;
/**
* @author Sylvain Berfini
*/
public class LinphoneMiniActivity extends Activity {
private LinphoneMiniManager mManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mManager = new LinphoneMiniManager(this);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onDestroy() {
mManager.destroy();
super.onDestroy();
}
}

View file

@ -0,0 +1,290 @@
package org.linphone.mini;
/*
LinphoneMiniManager.java
Copyright (C) 2014 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.
*/
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCallStats;
import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneContent;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
import org.linphone.core.LinphoneCore.GlobalState;
import org.linphone.core.LinphoneCore.RegistrationState;
import org.linphone.core.LinphoneCore.RemoteProvisioningState;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
import org.linphone.core.LinphoneEvent;
import org.linphone.core.LinphoneFriend;
import org.linphone.core.LinphoneInfoMessage;
import org.linphone.core.LinphoneProxyConfig;
import org.linphone.core.PublishState;
import org.linphone.core.SubscriptionState;
import org.linphone.mediastream.Log;
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration.AndroidCamera;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
/**
* @author Sylvain Berfini
*/
public class LinphoneMiniManager implements LinphoneCoreListener {
private static LinphoneMiniManager mInstance;
private Context mContext;
private LinphoneCore mLinphoneCore;
private Timer mTimer;
public LinphoneMiniManager(Context c) {
mContext = c;
LinphoneCoreFactory.instance().setDebugMode(true, "Linphone Mini");
try {
String basePath = mContext.getFilesDir().getAbsolutePath();
copyAssetsFromPackage(basePath);
mLinphoneCore = LinphoneCoreFactory.instance().createLinphoneCore(this, basePath + "/.linphonerc", basePath + "/linphonerc", null, mContext);
initLinphoneCoreValues(basePath);
setUserAgent();
setFrontCamAsDefault();
startIterate();
mInstance = this;
mLinphoneCore.setNetworkReachable(true); // Let's assume it's true
} catch (LinphoneCoreException e) {
} catch (IOException e) {
}
}
public static LinphoneMiniManager getInstance() {
return mInstance;
}
public void destroy() {
try {
mTimer.cancel();
mLinphoneCore.destroy();
}
catch (RuntimeException e) {
}
finally {
mLinphoneCore = null;
mInstance = null;
}
}
private void startIterate() {
TimerTask lTask = new TimerTask() {
@Override
public void run() {
mLinphoneCore.iterate();
}
};
/*use schedule instead of scheduleAtFixedRate to avoid iterate from being call in burst after cpu wake up*/
mTimer = new Timer("LinphoneMini scheduler");
mTimer.schedule(lTask, 0, 20);
}
private void setUserAgent() {
try {
String versionName = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName;
if (versionName == null) {
versionName = String.valueOf(mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionCode);
}
mLinphoneCore.setUserAgent("LinphoneMiniAndroid", versionName);
} catch (NameNotFoundException e) {
}
}
private void setFrontCamAsDefault() {
int camId = 0;
AndroidCamera[] cameras = AndroidCameraConfiguration.retrieveCameras();
for (AndroidCamera androidCamera : cameras) {
if (androidCamera.frontFacing)
camId = androidCamera.id;
}
mLinphoneCore.setVideoDevice(camId);
}
private void copyAssetsFromPackage(String basePath) throws IOException {
LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.oldphone_mono, basePath + "/oldphone_mono.wav");
LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.ringback, basePath + "/ringback.wav");
LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.toy_mono, basePath + "/toy_mono.wav");
LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.linphonerc_default, basePath + "/.linphonerc");
LinphoneMiniUtils.copyFromPackage(mContext, R.raw.linphonerc_factory, new File(basePath + "/linphonerc").getName());
LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.lpconfig, basePath + "/lpconfig.xsd");
LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.rootca, basePath + "/rootca.pem");
}
private void initLinphoneCoreValues(String basePath) {
mLinphoneCore.setContext(mContext);
mLinphoneCore.setRing(null);
mLinphoneCore.setRootCA(basePath + "/rootca.pem");
mLinphoneCore.setPlayFile(basePath + "/toy_mono.wav");
mLinphoneCore.setChatDatabasePath(basePath + "/linphone-history.db");
int availableCores = Runtime.getRuntime().availableProcessors();
mLinphoneCore.setCpuCount(availableCores);
}
@Override
public void authInfoRequested(LinphoneCore lc, String realm, String username) {
}
@Override
public void globalState(LinphoneCore lc, GlobalState state, String message) {
Log.d("Global state: " + state + "(" + message + ")");
}
@Override
public void callState(LinphoneCore lc, LinphoneCall call, State cstate,
String message) {
Log.d("Call state: " + cstate + "(" + message + ")");
}
@Override
public void callStatsUpdated(LinphoneCore lc, LinphoneCall call,
LinphoneCallStats stats) {
}
@Override
public void callEncryptionChanged(LinphoneCore lc, LinphoneCall call,
boolean encrypted, String authenticationToken) {
}
@Override
public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg,
RegistrationState cstate, String smessage) {
Log.d("Registration state: " + cstate + "(" + smessage + ")");
}
@Override
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,
String url) {
}
@Override
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {
}
@Override
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,
LinphoneAddress from, String message) {
}
@Override
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr,
LinphoneChatMessage message) {
Log.d("Message received from " + cr.getPeerAddress().asString() + " : " + message.getText() + "(" + message.getExternalBodyUrl() + ")");
}
@Override
public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
Log.d("Composing received from " + cr.getPeerAddress().asString());
}
@Override
public void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf) {
}
@Override
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,
int delay_ms, Object data) {
}
@Override
public void notifyReceived(LinphoneCore lc, LinphoneCall call,
LinphoneAddress from, byte[] event) {
}
@Override
public void transferState(LinphoneCore lc, LinphoneCall call,
State new_call_state) {
}
@Override
public void infoReceived(LinphoneCore lc, LinphoneCall call,
LinphoneInfoMessage info) {
}
@Override
public void subscriptionStateChanged(LinphoneCore lc, LinphoneEvent ev,
SubscriptionState state) {
}
@Override
public void notifyReceived(LinphoneCore lc, LinphoneEvent ev,
String eventName, LinphoneContent content) {
Log.d("Notify received: " + eventName + " -> " + content.getDataAsString());
}
@Override
public void publishStateChanged(LinphoneCore lc, LinphoneEvent ev,
PublishState state) {
}
@Override
public void configuringStatus(LinphoneCore lc,
RemoteProvisioningState state, String message) {
Log.d("Configuration state: " + state + "(" + message + ")");
}
@Override
public void show(LinphoneCore lc) {
}
@Override
public void displayStatus(LinphoneCore lc, String message) {
}
@Override
public void displayMessage(LinphoneCore lc, String message) {
}
@Override
public void displayWarning(LinphoneCore lc, String message) {
}
}

View file

@ -0,0 +1,51 @@
package org.linphone.mini;
/*
LinphoneMiniUtils.java
Copyright (C) 2014 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.
*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.content.Context;
/**
* @author Sylvain Berfini
*/
public class LinphoneMiniUtils {
public static void copyIfNotExist(Context context, int ressourceId, String target) throws IOException {
File lFileToCopy = new File(target);
if (!lFileToCopy.exists()) {
copyFromPackage(context, ressourceId, lFileToCopy.getName());
}
}
public static void copyFromPackage(Context context, int ressourceId, String target) throws IOException {
FileOutputStream lOutputStream = context.openFileOutput (target, 0);
InputStream lInputStream = context.getResources().openRawResource(ressourceId);
int readByte;
byte[] buff = new byte[8048];
while (( readByte = lInputStream.read(buff)) != -1) {
lOutputStream.write(buff,0, readByte);
}
lOutputStream.flush();
lOutputStream.close();
lInputStream.close();
}
}

1
sample/submodules Symbolic link
View file

@ -0,0 +1 @@
../submodules