fix list subscription setting not stored and improve background/foreground activity manager by moving it into the LinphoneService.

This commit is contained in:
Simon Morlat 2016-09-13 18:06:23 +02:00
parent a3c681dd0d
commit e7ece223e5
3 changed files with 137 additions and 135 deletions

View file

@ -236,6 +236,7 @@ public class AccountPreferencesFragment extends PreferencesListFragment {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
mPrefs.enabledFriendlistSubscription(value);
LinphoneManager.getInstance().subscribeFriendList(value);
return true;
}

View file

@ -142,112 +142,6 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
private boolean doNotGoToCallActivity = false;
private List<String> sideMenuItems;
private Application.ActivityLifecycleCallbacks activityCallbacks;
private Handler mHandler;
/*Believe me or not, but knowing the application visibility state on Android is a nightmare.
After two days of hard work I ended with the following class, that does the job more or less reliabily.
*/
class ActivityMonitor implements Application.ActivityLifecycleCallbacks {
private ArrayList<Activity> activities = new ArrayList<Activity>();
private boolean mActive = false;
private int mRunningActivities = 0;
class InactivityChecker implements Runnable {
private boolean isCanceled;
public void cancel() {
isCanceled = true;
}
@Override
public void run() {
if (!isCanceled) {
if (ActivityMonitor.this.mRunningActivities == 0) {
mActive = false;
LinphoneActivity.this.onBackgroundMode();
}
}
}
};
private InactivityChecker mLastChecker;
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.i("Activity created:" + activity);
if (!activities.contains(activity))
activities.add(activity);
}
@Override
public void onActivityStarted(Activity activity) {
Log.i("Activity started:" + activity);
}
@Override
public void onActivityResumed(Activity activity) {
Log.i("Activity resumed:" + activity);
if (activities.contains(activity)) {
mRunningActivities++;
Log.i("runningActivities=" + mRunningActivities);
checkActivity();
}
}
@Override
public void onActivityPaused(Activity activity) {
Log.i("Activity paused:" + activity);
if (activities.contains(activity)) {
mRunningActivities--;
Log.i("runningActivities=" + mRunningActivities);
checkActivity();
}
}
@Override
public void onActivityStopped(Activity activity) {
Log.i("Activity stopped:" + activity);
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
Log.i("Activity destroyed:" + activity);
if (activities.contains(activity)) {
activities.remove(activity);
}
}
void startInactivityChecker() {
if (mLastChecker != null) mLastChecker.cancel();
LinphoneActivity.this.mHandler.postDelayed(
(mLastChecker = new InactivityChecker()), 2000);
}
void checkActivity() {
if (mRunningActivities == 0) {
if (mActive) startInactivityChecker();
} else if (mRunningActivities > 0) {
if (!mActive) {
mActive = true;
LinphoneActivity.this.onForegroundMode();
}
if (mLastChecker != null) {
mLastChecker.cancel();
mLastChecker = null;
}
}
}
}
static final boolean isInstanciated() {
return instance != null;
@ -259,33 +153,10 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
throw new RuntimeException("LinphoneActivity not instantiated yet");
}
protected void onBackgroundMode(){
Log.i("App has entered background mode");
if (LinphonePreferences.instance().isFriendlistsubscriptionEnabled()) {
if (LinphoneManager.isInstanciated())
LinphoneManager.getInstance().subscribeFriendList(false);
}
}
protected void onForegroundMode() {
Log.i("App has left background mode");
}
/*the purpose of this method is to monitor activities started after the LinphoneActivity (but including LinphoneActivity)
in order to just be able to determine whether the application is in foreground or not.
Believe me or not, this information is not something provided by the current android apis.
*/
private void setupActivityMonitor(){
if (activityCallbacks != null) return;
getApplication().registerActivityLifecycleCallbacks(activityCallbacks = new ActivityMonitor());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
//This must be done before calling super.onCreate().
setupActivityMonitor();
super.onCreate(savedInstanceState);
mHandler = new Handler();
if (getResources().getBoolean(R.bool.orientation_portrait_only)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
@ -1440,7 +1311,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
protected void onResume() {
super.onResume();
if (!LinphoneService.isReady()) {
if (!LinphoneService.isReady()) {
startService(new Intent(Intent.ACTION_MAIN).setClass(this, LinphoneService.class));
}
@ -1501,11 +1372,6 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
mOrientationHelper = null;
}
if (activityCallbacks != null){
getApplication().unregisterActivityLifecycleCallbacks(activityCallbacks);
activityCallbacks = null;
}
instance = null;
super.onDestroy();

View file

@ -20,6 +20,7 @@ package org.linphone;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.linphone.compatibility.Compatibility;
import org.linphone.core.LinphoneAddress;
@ -40,6 +41,7 @@ import org.linphone.ui.LinphoneOverlay;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -52,6 +54,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
@ -121,6 +124,131 @@ public final class LinphoneService extends Service {
public static int notifcationsPriority = (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41) ? Notification.PRIORITY_MIN : 0);
private WindowManager mWindowManager;
private LinphoneOverlay mOverlay;
private Application.ActivityLifecycleCallbacks activityCallbacks;
/*Believe me or not, but knowing the application visibility state on Android is a nightmare.
After two days of hard work I ended with the following class, that does the job more or less reliabily.
*/
class ActivityMonitor implements Application.ActivityLifecycleCallbacks {
private ArrayList<Activity> activities = new ArrayList<Activity>();
private boolean mActive = false;
private int mRunningActivities = 0;
class InactivityChecker implements Runnable {
private boolean isCanceled;
public void cancel() {
isCanceled = true;
}
@Override
public void run() {
synchronized(LinphoneService.this) {
if (!isCanceled) {
if (ActivityMonitor.this.mRunningActivities == 0 && mActive) {
mActive = false;
LinphoneService.this.onBackgroundMode();
}
}
}
}
};
private InactivityChecker mLastChecker;
@Override
public synchronized void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.i("Activity created:" + activity);
if (!activities.contains(activity))
activities.add(activity);
}
@Override
public void onActivityStarted(Activity activity) {
Log.i("Activity started:" + activity);
}
@Override
public synchronized void onActivityResumed(Activity activity) {
Log.i("Activity resumed:" + activity);
if (activities.contains(activity)) {
mRunningActivities++;
Log.i("runningActivities=" + mRunningActivities);
checkActivity();
}
}
@Override
public synchronized void onActivityPaused(Activity activity) {
Log.i("Activity paused:" + activity);
if (activities.contains(activity)) {
mRunningActivities--;
Log.i("runningActivities=" + mRunningActivities);
checkActivity();
}
}
@Override
public void onActivityStopped(Activity activity) {
Log.i("Activity stopped:" + activity);
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public synchronized void onActivityDestroyed(Activity activity) {
Log.i("Activity destroyed:" + activity);
if (activities.contains(activity)) {
activities.remove(activity);
}
}
void startInactivityChecker() {
if (mLastChecker != null) mLastChecker.cancel();
LinphoneService.this.mHandler.postDelayed(
(mLastChecker = new InactivityChecker()), 2000);
}
void checkActivity() {
if (mRunningActivities == 0) {
if (mActive) startInactivityChecker();
} else if (mRunningActivities > 0) {
if (!mActive) {
mActive = true;
LinphoneService.this.onForegroundMode();
}
if (mLastChecker != null) {
mLastChecker.cancel();
mLastChecker = null;
}
}
}
}
protected void onBackgroundMode(){
Log.i("App has entered background mode");
if (LinphonePreferences.instance() != null && LinphonePreferences.instance().isFriendlistsubscriptionEnabled()) {
if (LinphoneManager.isInstanciated())
LinphoneManager.getInstance().subscribeFriendList(false);
}
}
protected void onForegroundMode() {
Log.i("App has left background mode");
}
private void setupActivityMonitor(){
if (activityCallbacks != null) return;
getApplication().registerActivityLifecycleCallbacks(activityCallbacks = new ActivityMonitor());
}
public int getMessageNotifCount() {
return mMsgNotifCount;
@ -160,6 +288,7 @@ public final class LinphoneService extends Service {
public void onCreate() {
super.onCreate();
setupActivityMonitor();
// In case restart after a crash. Main in LinphoneActivity
mNotificationTitle = getString(R.string.service_name);
@ -629,6 +758,12 @@ public final class LinphoneService extends Service {
@Override
public synchronized void onDestroy() {
if (activityCallbacks != null){
getApplication().unregisterActivityLifecycleCallbacks(activityCallbacks);
activityCallbacks = null;
}
destroyOverlay();
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (lc != null) {