LinphoneActivity launcher (synchro service ready)
Due to a bug in tabhost on 1.5 devices (G1 and simulator) it was impossible to have the synchronisation code directly in LinphoneActivity. (NPE on touchmodechanged on mCurrentView). Note that since the synchronisation code rewrite, no special care is taken after a service crash. As a consequence you should always check the root cause of a "Caused by: java.lang.RuntimeException: Linphone Manager should be created before accessed"
This commit is contained in:
parent
c14c020053
commit
ec3b407138
5 changed files with 133 additions and 130 deletions
|
@ -8,8 +8,19 @@
|
|||
|
||||
<!-- Don't remove the space after android:debuggable: it prevents ndk-build to try including gdbserver and crash gcc -->
|
||||
<application android:label="@string/app_name" android:debuggable ="true" android:icon="@drawable/logo_linphone_57x57">
|
||||
|
||||
<activity android:name="org.linphone.LinphoneActivity"
|
||||
|
||||
<activity android:name="org.linphone.LinphoneLauncherActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@android:style/Theme.NoTitleBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
||||
|
||||
<activity android:name="org.linphone.LinphoneActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@android:style/Theme.NoTitleBar"
|
||||
android:launchMode="singleTask"
|
||||
|
@ -17,7 +28,6 @@
|
|||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
|
@ -86,12 +96,12 @@
|
|||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="ContactPickerActivityNew">
|
||||
<activity android:name="ContactPickerActivityNew" android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="ContactPickerActivityOld">
|
||||
<activity android:name="ContactPickerActivityOld" android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<ProgressBar android:layout_height="wrap_content" android:layout_width="wrap_content"/>
|
||||
<TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/wait_dialog_text"/>
|
||||
</LinearLayout>
|
||||
<ImageView android:layout_width="fill_parent" android:layout_height="fill_parent"
|
||||
android:src="@drawable/logo_linphone_57x57" android:scaleType="fitXY" />
|
||||
<ProgressBar android:layout_height="wrap_content" android:layout_width="wrap_content" />
|
||||
</FrameLayout>
|
|
@ -35,7 +35,6 @@ import org.linphone.mediastream.Version;
|
|||
import org.linphone.mediastream.video.AndroidVideoWindowImpl;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.TabActivity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
|
@ -56,7 +55,6 @@ import android.text.Html;
|
|||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TabWidget;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
@ -85,9 +83,6 @@ public class LinphoneActivity extends TabActivity implements
|
|||
|
||||
private Handler mHandler = new Handler();
|
||||
|
||||
private static final int waitDialogId = 1;
|
||||
private ServiceWaitThread thread;
|
||||
|
||||
// Customization
|
||||
private static boolean useFirstLoginActivity;
|
||||
private static boolean useMenuSettings;
|
||||
|
@ -104,15 +99,6 @@ public class LinphoneActivity extends TabActivity implements
|
|||
throw new RuntimeException("LinphoneActivity not instantiated yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(final int id) {
|
||||
if (id == waitDialogId) {
|
||||
View v = getLayoutInflater().inflate((R.layout.wait_service_dialog), null);
|
||||
return new AlertDialog.Builder(this).setView(v).setCancelable(false).create();
|
||||
}
|
||||
return super.onCreateDialog(id);
|
||||
}
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
instance = this;
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -127,15 +113,27 @@ public class LinphoneActivity extends TabActivity implements
|
|||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,Log.TAG+"#"+getClass().getName());
|
||||
|
||||
if (LinphoneService.isReady()) {
|
||||
onCreateWhenServiceReady();
|
||||
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
|
||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
if (!useFirstLoginActivity || pref.getBoolean(getString(R.string.first_launch_suceeded_once_key), false)) {
|
||||
fillTabHost();
|
||||
} else {
|
||||
// start linphone as background
|
||||
startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
|
||||
mDoOnCreateWhenServiceReady = true;
|
||||
thread = new ServiceWaitThread();
|
||||
thread.start();
|
||||
startActivityForResult(new Intent().setClass(this, FirstLoginActivity.class), FIRST_LOGIN_ACTIVITY);
|
||||
}
|
||||
|
||||
if (checkAccount && !useFirstLoginActivity) {
|
||||
if (pref.getBoolean(PREF_FIRST_LAUNCH, true)) {
|
||||
onFirstLaunch();
|
||||
} else if (!pref.getBoolean(PREF_CHECK_CONFIG, false)
|
||||
&& !checkDefined(pref, R.string.pref_username_key, R.string.pref_domain_key)) {
|
||||
onBadSettings(pref);
|
||||
} else {
|
||||
checkAccount = false;
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneManager.addListener(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,8 +199,8 @@ public class LinphoneActivity extends TabActivity implements
|
|||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
if (intent.getData() == null) {
|
||||
Log.e("LinphoneActivity received an intent without data, recreating GUI if needed");
|
||||
if (!LinphoneService.isReady() || !LinphoneManager.getLc().isIncall()) return;
|
||||
Log.i("LinphoneActivity received an intent without data, recreating GUI if needed");
|
||||
if (!LinphoneManager.getLc().isIncall()) return;
|
||||
if(LinphoneManager.getLc().isInComingInvitePending()) {
|
||||
gotToDialer();
|
||||
} else {
|
||||
|
@ -242,7 +240,6 @@ public class LinphoneActivity extends TabActivity implements
|
|||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mDoResumeWhenServiceReady = false;
|
||||
if (isFinishing()) {
|
||||
//restore audio settings
|
||||
LinphoneManager.removeListener(this);
|
||||
|
@ -573,36 +570,9 @@ public class LinphoneActivity extends TabActivity implements
|
|||
}
|
||||
|
||||
|
||||
private boolean mWaitDialogPosted;
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (LinphoneService.isReady()) {
|
||||
onResumeWhenServiceReady();
|
||||
} else {
|
||||
if (!mWaitDialogPosted) {
|
||||
mWaitDialogPosted = true;
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
// Delay to avoid flicker.
|
||||
// Call in onResume to make sure the view (especially the tabhost) is initialized.
|
||||
@Override
|
||||
public void run() {
|
||||
if (!LinphoneService.isReady()) {
|
||||
showDialog(waitDialogId);
|
||||
}
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
mDoResumeWhenServiceReady = true;
|
||||
if (thread == null) {
|
||||
thread = new ServiceWaitThread();
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onResumeWhenServiceReady() {
|
||||
LinphoneCall pendingCall = LinphoneManager.getInstance().getPendingIncomingCall();
|
||||
if (pendingCall != null) {
|
||||
LinphoneActivity.instance().startIncomingCallActivity(pendingCall);
|
||||
|
@ -615,72 +585,6 @@ public class LinphoneActivity extends TabActivity implements
|
|||
// removing is done directly in LinphoneActivity.onPause()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private boolean mDoOnCreateWhenServiceReady;
|
||||
private void onCreateWhenServiceReady() {
|
||||
mDoOnCreateWhenServiceReady = false;
|
||||
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
|
||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
if (!useFirstLoginActivity || pref.getBoolean(getString(R.string.first_launch_suceeded_once_key), false)) {
|
||||
fillTabHost();
|
||||
} else {
|
||||
startActivityForResult(new Intent().setClass(this, FirstLoginActivity.class), FIRST_LOGIN_ACTIVITY);
|
||||
}
|
||||
|
||||
if (checkAccount && !useFirstLoginActivity) {
|
||||
if (pref.getBoolean(PREF_FIRST_LAUNCH, true)) {
|
||||
onFirstLaunch();
|
||||
} else if (!pref.getBoolean(PREF_CHECK_CONFIG, false)
|
||||
&& !checkDefined(pref, R.string.pref_username_key, R.string.pref_domain_key)) {
|
||||
onBadSettings(pref);
|
||||
} else {
|
||||
checkAccount = false;
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneManager.addListener(this);
|
||||
}
|
||||
|
||||
private boolean mDoResumeWhenServiceReady;
|
||||
|
||||
private class ServiceWaitThread extends Thread {
|
||||
public void run() {
|
||||
while (!LinphoneService.isReady()) {
|
||||
try {
|
||||
sleep(30);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("waiting thread sleep() has been interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
dismissDialog(waitDialogId);
|
||||
} catch (Throwable e) {
|
||||
// Discarding exception which may be thrown if the dialog wasn't showing.
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mDoOnCreateWhenServiceReady) {
|
||||
onCreateWhenServiceReady();
|
||||
}
|
||||
if (mDoResumeWhenServiceReady) {
|
||||
onResumeWhenServiceReady();
|
||||
}
|
||||
}
|
||||
});
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ContactPicked {
|
||||
|
|
88
src/org/linphone/LinphoneLauncherActivity.java
Normal file
88
src/org/linphone/LinphoneLauncherActivity.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
LinphoneLauncher.java
|
||||
Copyright (C) 2011 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 static android.content.Intent.ACTION_MAIN;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
*
|
||||
* Launch Linphone main activity when Service is ready.
|
||||
*
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
public class LinphoneLauncherActivity extends Activity {
|
||||
|
||||
private Handler mHandler;
|
||||
private ServiceWaitThread mThread;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.launcher);
|
||||
mHandler = new Handler();
|
||||
|
||||
if (LinphoneService.isReady()) {
|
||||
onServiceReady();
|
||||
} else {
|
||||
// start linphone as background
|
||||
startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
|
||||
mThread = new ServiceWaitThread();
|
||||
mThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void onServiceReady() {
|
||||
startActivity(new Intent()
|
||||
.setClass(this, LinphoneActivity.class)
|
||||
.setData(getIntent().getData()));
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
private class ServiceWaitThread extends Thread {
|
||||
public void run() {
|
||||
while (!LinphoneService.isReady()) {
|
||||
try {
|
||||
sleep(30);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("waiting thread sleep() has been interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onServiceReady();
|
||||
}
|
||||
});
|
||||
mThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ import android.os.Handler;
|
|||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
/***
|
||||
/**
|
||||
*
|
||||
* Linphone service, reacting to Incoming calls, ...<br />
|
||||
*
|
||||
|
@ -69,11 +69,11 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
|
|||
private Handler mHandler = new Handler();
|
||||
private static LinphoneService instance;
|
||||
|
||||
// private static boolean mTestDelayElapsed; // add a timer for testing
|
||||
private static boolean mTestDelayElapsed = true; // no timer
|
||||
// private boolean mTestDelayElapsed; // add a timer for testing
|
||||
private boolean mTestDelayElapsed = true; // no timer
|
||||
|
||||
public static boolean isReady() {
|
||||
return mTestDelayElapsed && instance!=null;
|
||||
return instance!=null && instance.mTestDelayElapsed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue