diff --git a/ring-android/app/build.gradle b/ring-android/app/build.gradle index fdf1a766bcd826060543a7a7a8ad2dfeafae4b56..4435669a830ea4da212aaa327e919d191a99452d 100644 --- a/ring-android/app/build.gradle +++ b/ring-android/app/build.gradle @@ -8,11 +8,11 @@ repositories { dependencies { compile fileTree(include: '*.jar', dir: 'libs') - compile 'com.android.support:support-v13:24.2.+' - compile 'com.android.support:design:24.2.+' - compile 'com.android.support:cardview-v7:24.2.+' - compile 'com.android.support:preference-v14:24.2.+' - compile 'com.android.support:recyclerview-v7:24.2.+' + compile 'com.android.support:support-v13:24.2.1' + compile 'com.android.support:design:24.2.1' + compile 'com.android.support:cardview-v7:24.2.1' + compile 'com.android.support:preference-v14:24.2.1' + compile 'com.android.support:recyclerview-v7:24.2.1' compile 'com.jayway.android.robotium:robotium-solo:5.4.1' compile 'com.astuetz:pagerslidingtabstrip:1.0.1' @@ -44,6 +44,12 @@ dependencies { android { compileSdkVersion 24 buildToolsVersion "24.0.2" + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 24 + } + sourceSets { main { aidl.srcDirs = ['src/main/java'] diff --git a/ring-android/app/src/main/AndroidManifest.xml b/ring-android/app/src/main/AndroidManifest.xml index b2c6889184ebe4b8410ad5f78a010c98f5f9a4b1..d11ee57b4f234ed338e11699949ebbdf043536ba 100644 --- a/ring-android/app/src/main/AndroidManifest.xml +++ b/ring-android/app/src/main/AndroidManifest.xml @@ -23,10 +23,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. android:versionCode="52" android:versionName="20160816"> - <uses-sdk - android:minSdkVersion="16" - android:targetSdkVersion="23" /> - <supports-screens android:anyDensity="true" android:largeScreens="true" @@ -71,7 +67,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" - android:supportsRtl="true"> + android:supportsRtl="true" + android:resizeableActivity="true"> <activity android:name=".client.HomeActivity" android:label="@string/title_activity_sflphone_home" @@ -79,7 +76,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. android:windowSoftInputMode="adjustResize" android:screenOrientation="fullUser" android:launchMode="singleTask" - android:configChanges="orientation|screenSize"> + android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> @@ -143,7 +140,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. android:name=".client.AccountWizard" android:theme="@style/AppThemeBase" android:screenOrientation="fullUser" - android:configChanges="orientation|screenSize"> + android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="cx.ring.client.AccountEditionActivity" /> @@ -153,7 +150,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. android:label="@string/app_name" android:theme="@style/AppThemeBase" android:screenOrientation="fullUser" - android:configChanges="orientation|screenSize"/> + android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"/> <activity android:name=".client.NewConversationActivity" android:label="@string/app_name" @@ -177,7 +174,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. android:name=".client.CallActivity" android:label="@string/app_name" android:screenOrientation="fullUser" - android:configChanges="orientation|screenSize" + android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize" android:theme="@style/AppTheme.ActionBar.Transparent" android:windowSoftInputMode="adjustPan|stateHidden"> @@ -245,7 +242,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. android:parentActivityName=".client.HomeActivity" android:theme="@style/AppThemeBase" android:windowSoftInputMode="adjustResize" - android:screenOrientation="fullUser"/> + android:screenOrientation="fullUser" + android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize" + /> <activity android:name=".client.QRCodeScannerActivity" android:screenOrientation="fullUser" android:stateNotNeeded="true" diff --git a/ring-android/app/src/main/java/cx/ring/client/AccountEditionActivity.java b/ring-android/app/src/main/java/cx/ring/client/AccountEditionActivity.java index 6a849881a4294bcf9afcaf13325a5a48e6adb9d7..746004c9a4419594769263db6a6c46f6afe9cb43 100644 --- a/ring-android/app/src/main/java/cx/ring/client/AccountEditionActivity.java +++ b/ring-android/app/src/main/java/cx/ring/client/AccountEditionActivity.java @@ -49,7 +49,6 @@ import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; -import android.util.Pair; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; @@ -75,6 +74,8 @@ import cx.ring.fragments.DeviceAccountFragment; import cx.ring.fragments.GeneralAccountFragment; import cx.ring.fragments.MediaPreferenceFragment; import cx.ring.fragments.SecurityAccountFragment; +import cx.ring.interfaces.AccountCallbacks; +import cx.ring.interfaces.AccountChangedListener; import cx.ring.model.account.Account; import cx.ring.service.IDRingService; import cx.ring.service.LocalService; @@ -96,6 +97,14 @@ public class AccountEditionActivity extends AppCompatActivity implements Account public Account getAccount() { return null; } + + @Override + public void addOnAccountChanged(AccountChangedListener list) { + } + + @Override + public void removeOnAccountChanged(AccountChangedListener list) { + } }; private static final String TAG = AccountEditionActivity.class.getSimpleName(); @@ -107,6 +116,7 @@ public class AccountEditionActivity extends AppCompatActivity implements Account private LocalService mService; private Account mAccSelected = null; + private final ArrayList<AccountChangedListener> listeners = new ArrayList<>(); private Observer mAccountObserver = new Observer() { @@ -159,23 +169,15 @@ public class AccountEditionActivity extends AppCompatActivity implements Account mAccSelected.addObserver(mAccountObserver); getSupportActionBar().setTitle(mAccSelected.getAlias()); - ArrayList<Pair<String, Fragment>> fragments = new ArrayList<>(); - if (mAccSelected.isRing()) { - fragments.add(new Pair<String, Fragment>(getString(R.string.account_preferences_devices_tab), new DeviceAccountFragment())); - } - fragments.add(new Pair<String, Fragment>(getString(R.string.account_preferences_basic_tab), new GeneralAccountFragment())); - fragments.add(new Pair<String, Fragment>(getString(R.string.account_preferences_media_tab), new MediaPreferenceFragment())); - fragments.add(new Pair<String, Fragment>(getString(R.string.account_preferences_advanced_tab), new AdvancedAccountFragment())); - if (mAccSelected.isSip()) { - fragments.add(new Pair<String, Fragment>(getString(R.string.account_preferences_security_tab), new SecurityAccountFragment())); - } - final ViewPager mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setOffscreenPageLimit(4); - mViewPager.setAdapter(new PreferencesPagerAdapter(getFragmentManager(), fragments)); + mViewPager.setAdapter(new PreferencesPagerAdapter(getFragmentManager(), AccountEditionActivity.this, mAccSelected.isRing())); PagerSlidingTabStrip mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.sliding_tabs); mSlidingTabLayout.setViewPager(mViewPager); + + for (AccountChangedListener l : listeners) + l.accountChanged(mAccSelected); } @Override @@ -461,37 +463,93 @@ public class AccountEditionActivity extends AppCompatActivity implements Account return mService; } - @Override - public void onStart() { - super.onStart(); - } - - @Override - public void onStop() { - super.onStop(); - } - private static class PreferencesPagerAdapter extends FragmentPagerAdapter { - private final ArrayList<Pair<String, Fragment>> fragments; + private Context ctx; + boolean isRing = false; - public PreferencesPagerAdapter(FragmentManager fm, ArrayList<Pair<String, Fragment>> items) { + PreferencesPagerAdapter(FragmentManager fm, Context c, boolean ring) { super(fm); - fragments = items; + ctx = c; + isRing = ring; } @Override public int getCount() { - return fragments.size(); + // For now we have 4 panels in each account type (Ring/SIP), but it may change + return isRing ? 4 : 4; } @Override public Fragment getItem(int position) { - return fragments.get(position).second; + return isRing ? getRingPanel(position) : getSIPPanel(position); } @Override public CharSequence getPageTitle(int position) { - return fragments.get(position).first; + int resId = isRing ? getRingPanelTitle(position) : getSIPPanelTitle(position); + return ctx.getString(resId); + } + + private static Fragment getRingPanel(int position) { + Log.i(TAG, "PreferencesPagerAdapter getFragment " + position); + switch (position) { + case 0: + return new DeviceAccountFragment(); + case 1: + return new GeneralAccountFragment(); + case 2: + return new MediaPreferenceFragment(); + case 3: + return new AdvancedAccountFragment(); + default: + return null; + } + } + + private static Fragment getSIPPanel(int position) { + Log.i(TAG, "PreferencesPagerAdapter getFragment " + position); + switch (position) { + case 0: + return new GeneralAccountFragment(); + case 1: + return new MediaPreferenceFragment(); + case 2: + return new AdvancedAccountFragment(); + case 3: + return new SecurityAccountFragment(); + default: + return null; + } + } + + private static int getRingPanelTitle(int position) { + switch (position) { + case 0: + return R.string.account_preferences_basic_tab; + case 1: + return R.string.account_preferences_media_tab; + case 2: + return R.string.account_preferences_advanced_tab; + case 3: + return R.string.account_preferences_security_tab; + default: + return -1; + } + } + + private static int getSIPPanelTitle(int position) { + switch (position) { + case 0: + return R.string.account_preferences_basic_tab; + case 1: + return R.string.account_preferences_media_tab; + case 2: + return R.string.account_preferences_advanced_tab; + case 3: + return R.string.account_preferences_security_tab; + default: + return -1; + } } } @@ -500,5 +558,14 @@ public class AccountEditionActivity extends AppCompatActivity implements Account return mAccSelected; } + @Override + public void addOnAccountChanged(AccountChangedListener list) { + listeners.add(list); + } + + @Override + public void removeOnAccountChanged(AccountChangedListener list) { + listeners.remove(list); + } } diff --git a/ring-android/app/src/main/java/cx/ring/client/AccountWizard.java b/ring-android/app/src/main/java/cx/ring/client/AccountWizard.java index 0926f338a7d540e447feda2a6205a03aa46a63f8..a2c897efcafbac59dfc31ab6081c8ab979912015 100644 --- a/ring-android/app/src/main/java/cx/ring/client/AccountWizard.java +++ b/ring-android/app/src/main/java/cx/ring/client/AccountWizard.java @@ -27,6 +27,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; import android.support.v13.app.FragmentStatePagerAdapter; @@ -38,7 +39,6 @@ import android.util.Log; import android.view.MenuItem; import java.util.ArrayList; -import java.util.Locale; import butterknife.BindView; import butterknife.ButterKnife; @@ -85,7 +85,7 @@ public class AccountWizard extends AppCompatActivity implements LocalService.Cal if (getIntent().getData() != null && !TextUtils.isEmpty(getIntent().getData().getLastPathSegment())) { String accountId = getIntent().getData().getLastPathSegment(); - SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(AccountWizard.this, getFragmentManager(), accountId); + SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager(), accountId); mViewPager.setAdapter(mSectionsPagerAdapter); } else { SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(AccountWizard.this, getFragmentManager()); @@ -100,6 +100,12 @@ public class AccountWizard extends AppCompatActivity implements LocalService.Cal } + @Override + public void onConfigurationChanged(Configuration newConfig) { + Log.i(TAG, "onConfigurationChanged " + newConfig); + super.onConfigurationChanged(newConfig); + } + /* activity finishes itself or is being killed by the system */ @Override protected void onDestroy() { @@ -140,17 +146,15 @@ public class AccountWizard extends AppCompatActivity implements LocalService.Cal } public class SectionsPagerAdapter extends FragmentStatePagerAdapter { - private final Context mContext; private final ArrayList<Fragment> fragments; private final String mAccountId; - public SectionsPagerAdapter(Context c, FragmentManager fm) { - this(c, fm, null); + SectionsPagerAdapter(Context c, FragmentManager fm) { + this(fm, null); } - public SectionsPagerAdapter(Context c, FragmentManager fm, String accountId) { + SectionsPagerAdapter(FragmentManager fm, String accountId) { super(fm); - mContext = c; fragments = new ArrayList<>(); mAccountId = accountId; @@ -171,42 +175,10 @@ public class AccountWizard extends AppCompatActivity implements LocalService.Cal return fragments.get(i); } - public String getClassName(int i) { - String name; - - switch (i) { - case 0: - if (TextUtils.isEmpty(mAccountId)) { - name = AccountCreationFragment.class.getName(); - } else { - name = AccountMigrationFragment.class.getName(); - } - break; - - default: - Log.e(TAG, "getClassName: unknown fragment position " + i); - return null; - } - - return name; - } - @Override public int getCount() { return 1; } - - @Override - public CharSequence getPageTitle(int position) { - switch (position) { - case 0: - return mContext.getString(R.string.title_section0).toUpperCase(Locale.getDefault()); - default: - Log.e(TAG, "getPageTitle: unknown tab position " + position); - break; - } - return null; - } } @Override diff --git a/ring-android/app/src/main/java/cx/ring/fragments/AccountCreationFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/AccountCreationFragment.java index 763a03756f5e2348e3badf053eb958b6bf8daff9..aab3f454a2eca597827fbba825f4319417784618 100644 --- a/ring-android/app/src/main/java/cx/ring/fragments/AccountCreationFragment.java +++ b/ring-android/app/src/main/java/cx/ring/fragments/AccountCreationFragment.java @@ -770,7 +770,9 @@ public class AccountCreationFragment extends Fragment { if (!AccountDetailVolatile.STATE_INITIALIZING.contentEquals(state)) { account.stateListener = null; if (progress != null) { - progress.dismiss(); + if (progress.isShowing()) { + progress.dismiss(); + } progress = null; } AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity()); diff --git a/ring-android/app/src/main/java/cx/ring/fragments/AdvancedAccountFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/AdvancedAccountFragment.java index d85ac1ca292879939f9b5e56d92ea2c603f9522a..699ce296bd093b1bd0420ec25e8748193c43ec1a 100644 --- a/ring-android/app/src/main/java/cx/ring/fragments/AdvancedAccountFragment.java +++ b/ring-android/app/src/main/java/cx/ring/fragments/AdvancedAccountFragment.java @@ -36,7 +36,7 @@ import java.util.ArrayList; import java.util.Enumeration; import cx.ring.R; -import cx.ring.client.AccountCallbacks; +import cx.ring.interfaces.AccountCallbacks; import cx.ring.model.account.Account; import cx.ring.model.account.AccountDetail; import cx.ring.model.account.AccountDetailAdvanced; diff --git a/ring-android/app/src/main/java/cx/ring/fragments/DeviceAccountFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/DeviceAccountFragment.java index 9a2feaff5ef3d727979d2046ba2ea964bccca1a1..0c497e909e040ec3cba44ec69fb5bddeabced49e 100644 --- a/ring-android/app/src/main/java/cx/ring/fragments/DeviceAccountFragment.java +++ b/ring-android/app/src/main/java/cx/ring/fragments/DeviceAccountFragment.java @@ -28,7 +28,6 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.RemoteException; import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -42,20 +41,26 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.Map; +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; import cx.ring.R; -import cx.ring.client.AccountCallbacks; +import cx.ring.interfaces.AccountCallbacks; +import cx.ring.interfaces.AccountChangedListener; import cx.ring.model.account.Account; import static cx.ring.client.AccountEditionActivity.DUMMY_CALLBACKS; -public class DeviceAccountFragment extends Fragment { +public class DeviceAccountFragment extends Fragment implements AccountChangedListener { private static final String TAG = DeviceAccountFragment.class.getSimpleName(); - private static final String DIALOG_FRAGMENT_TAG = "android.support.v14.preference.PreferenceFragment.DIALOG"; private AccountCallbacks mCallbacks = DUMMY_CALLBACKS; private DeviceAdapter adapter; + @BindView(R.id.device_list) + ListView deviceList; + @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -64,28 +69,34 @@ public class DeviceAccountFragment extends Fragment { } mCallbacks = (AccountCallbacks) activity; - Account acc = mCallbacks.getAccount(); - if (acc != null) - acc.devicesListener = new Account.OnDevicesChangedListener() { - @Override - public void devicesChanged(Map<String, String> devices) { - if (adapter != null) { - adapter.setData(devices); - } - } - }; + mCallbacks.addOnAccountChanged(this); } @Override public void onDetach() { super.onDetach(); if (mCallbacks != null) { + mCallbacks.removeOnAccountChanged(this); Account acc = mCallbacks.getAccount(); acc.devicesListener = null; } mCallbacks = DUMMY_CALLBACKS; } + @Override + public void accountChanged(Account acc) { + adapter = new DeviceAdapter(getActivity(), acc.getDevices()); + deviceList.setAdapter(adapter); + acc.devicesListener = new Account.OnDevicesChangedListener() { + @Override + public void devicesChanged(Map<String, String> devices) { + if (adapter != null) { + adapter.setData(devices); + } + } + }; + } + class DeviceAdapter extends BaseAdapter { private final Context mCtx; private final ArrayList<Map.Entry<String, String>> devices = new ArrayList<>(); @@ -189,67 +200,57 @@ public class DeviceAccountFragment extends Fragment { @Nullable @Override public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - if (container == null) return null; + ViewGroup devLayout = (ViewGroup) inflater.inflate(R.layout.frag_device_list, container, false); + + ButterKnife.bind(this, devLayout); Account acc = mCallbacks.getAccount(); - if (acc == null) { - return null; + if (acc != null) { + accountChanged(acc); } - ViewGroup dev_layout = (ViewGroup) inflater.inflate(R.layout.frag_device_list, container, false); + return devLayout; + } - FloatingActionButton newDevBtn = (FloatingActionButton) dev_layout.findViewById(R.id.btn_add_device); - newDevBtn.setOnClickListener(new View.OnClickListener() { + @OnClick(R.id.btn_add_device) + @SuppressWarnings("unused") + public void addDevice() { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + final ViewGroup v = (ViewGroup) LayoutInflater.from(getActivity()).inflate(R.layout.dialog_new_device, null); + final TextView pwd = (TextView) v.findViewById(R.id.pwd_txt); + builder.setMessage(R.string.account_new_device_message) + .setTitle(R.string.account_new_device) + .setPositiveButton(R.string.account_export, null) + .setNegativeButton(android.R.string.cancel, null).setView(v); + final AlertDialog alertDialog = builder.create(); + alertDialog.show(); + pwd.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override - public void onClick(View view) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - final ViewGroup v = (ViewGroup) inflater.inflate(R.layout.dialog_new_device, null); - final TextView pwd = (TextView) v.findViewById(R.id.pwd_txt); - builder.setMessage(R.string.account_new_device_message) - .setTitle(R.string.account_new_device) - .setPositiveButton(R.string.account_export, null) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int whichButton) { - } - }).setView(v); - final AlertDialog alertDialog = builder.create(); - alertDialog.show(); - pwd.setOnEditorActionListener(new TextView.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - Log.i(TAG, "onEditorAction " + actionId + " " + (event == null ? null : event.toString())); - if (actionId == EditorInfo.IME_ACTION_DONE) { - if (pwd.getText().length() == 0) { - pwd.setError(getString(R.string.account_enter_password)); - } else { - alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).callOnClick(); - return true; - } - } - return false; - } - }); - alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - pwd.setError(null); - if (pwd.getText().length() == 0) { - pwd.setError(getString(R.string.account_enter_password)); - } else { - alertDialog.dismiss(); - new ExportOnRingTask().execute(pwd.getText().toString()); - } + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + Log.i(TAG, "onEditorAction " + actionId + " " + (event == null ? null : event.toString())); + if (actionId == EditorInfo.IME_ACTION_DONE) { + if (pwd.getText().length() == 0) { + pwd.setError(getString(R.string.account_enter_password)); + } else { + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).callOnClick(); + return true; } - }); - + } + return false; + } + }); + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + pwd.setError(null); + if (pwd.getText().length() == 0) { + pwd.setError(getString(R.string.account_enter_password)); + } else { + alertDialog.dismiss(); + new ExportOnRingTask().execute(pwd.getText().toString()); + } } }); - - adapter = new DeviceAdapter(getActivity(), acc.getDevices()); - ListView deviceList = (ListView) dev_layout.findViewById(R.id.device_list); - deviceList.setAdapter(adapter); - return dev_layout; } } diff --git a/ring-android/app/src/main/java/cx/ring/fragments/GeneralAccountFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/GeneralAccountFragment.java index 755cabb2884e98f054db9b68bebf15678b9ee94c..5afd2b08fcaca09cc0555283892388a3d7d06f62 100644 --- a/ring-android/app/src/main/java/cx/ring/fragments/GeneralAccountFragment.java +++ b/ring-android/app/src/main/java/cx/ring/fragments/GeneralAccountFragment.java @@ -29,7 +29,8 @@ import android.util.Log; import android.view.inputmethod.EditorInfo; import cx.ring.R; -import cx.ring.client.AccountCallbacks; +import cx.ring.interfaces.AccountCallbacks; +import cx.ring.interfaces.AccountChangedListener; import cx.ring.model.account.Account; import cx.ring.model.account.AccountDetail; import cx.ring.model.account.AccountDetailBasic; @@ -39,11 +40,11 @@ import cx.ring.views.PasswordPreference; import static cx.ring.client.AccountEditionActivity.DUMMY_CALLBACKS; -public class GeneralAccountFragment extends PreferenceFragment { +public class GeneralAccountFragment extends PreferenceFragment implements AccountChangedListener { private static final String TAG = GeneralAccountFragment.class.getSimpleName(); private static final String DIALOG_FRAGMENT_TAG = "android.support.v14.preference.PreferenceFragment.DIALOG"; - + private static final String KEY_IS_RING = "accountIsRing"; private AccountCallbacks mCallbacks = DUMMY_CALLBACKS; @Override @@ -54,16 +55,28 @@ public class GeneralAccountFragment extends PreferenceFragment { } mCallbacks = (AccountCallbacks) activity; + mCallbacks.addOnAccountChanged(this); } @Override public void onDetach() { super.onDetach(); + Log.i(TAG, "onDetach"); + if (mCallbacks != null) { + mCallbacks.removeOnAccountChanged(this); + } mCallbacks = DUMMY_CALLBACKS; } + @Override + public void accountChanged(Account acc) { + setPreferenceDetails(acc.getBasicDetails()); + setPreferenceListener(acc.getBasicDetails(), changeBasicPreferenceListener); + } + @Override public void onCreatePreferences(Bundle bundle, String s) { + Log.i(TAG, "onCreatePreferences " + bundle + " " + s); Account acc = mCallbacks.getAccount(); if (acc != null) { if (acc.isRing()) { @@ -71,8 +84,28 @@ public class GeneralAccountFragment extends PreferenceFragment { } else { addPreferencesFromResource(R.xml.account_general_prefs); } - setPreferenceDetails(acc.getBasicDetails()); - addPreferenceListener(acc.getBasicDetails(), changeBasicPreferenceListener); + accountChanged(acc); + } else { + if (bundle != null) { + Log.w(TAG, "onCreatePreferences: null account, from bundle"); + boolean isRing = bundle.getBoolean(KEY_IS_RING); + if (isRing) { + addPreferencesFromResource(R.xml.account_prefs_ring); + } else { + addPreferencesFromResource(R.xml.account_general_prefs); + } + } else { + Log.w(TAG, "onCreatePreferences: null account"); + } + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + Account acc = mCallbacks.getAccount(); + if (acc != null) { + outState.putBoolean(KEY_IS_RING, acc.isRing()); } } @@ -117,19 +150,16 @@ public class GeneralAccountFragment extends PreferenceFragment { } } - private void addPreferenceListener(AccountDetail details, Preference.OnPreferenceChangeListener listener) { + private void setPreferenceListener(AccountDetail details, Preference.OnPreferenceChangeListener listener) { for (AccountDetail.PreferenceEntry p : details.getDetailValues()) { - //Log.i(TAG, "addPreferenceListener: pref " + p.mKey + " " + p.mValue); Preference pref = findPreference(p.mKey); if (pref != null) { pref.setOnPreferenceChangeListener(listener); - } /*else { - Log.w(TAG, "addPreferenceListener: pref not found"); - }*/ + } } } - Preference.OnPreferenceChangeListener changeBasicPreferenceListener = new Preference.OnPreferenceChangeListener() { + private final Preference.OnPreferenceChangeListener changeBasicPreferenceListener = new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { diff --git a/ring-android/app/src/main/java/cx/ring/fragments/MediaPreferenceFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/MediaPreferenceFragment.java index 404dead8effc36a90a3022481489cc812353dc9b..11a5db917b8e2313e0af1ff9ee49ddf44901c175 100644 --- a/ring-android/app/src/main/java/cx/ring/fragments/MediaPreferenceFragment.java +++ b/ring-android/app/src/main/java/cx/ring/fragments/MediaPreferenceFragment.java @@ -43,7 +43,8 @@ import java.io.File; import java.util.ArrayList; import cx.ring.R; -import cx.ring.client.AccountCallbacks; +import cx.ring.interfaces.AccountCallbacks; +import cx.ring.interfaces.AccountChangedListener; import cx.ring.model.Codec; import cx.ring.model.account.Account; import cx.ring.model.account.AccountDetail; @@ -53,7 +54,9 @@ import cx.ring.service.LocalService; import static cx.ring.client.AccountEditionActivity.DUMMY_CALLBACKS; -public class MediaPreferenceFragment extends PreferenceFragment implements FragmentCompat.OnRequestPermissionsResultCallback { + +public class MediaPreferenceFragment extends PreferenceFragment + implements FragmentCompat.OnRequestPermissionsResultCallback, AccountChangedListener { static final String TAG = MediaPreferenceFragment.class.getSimpleName(); private CodecPreference audioCodecsPref = null; @@ -61,6 +64,15 @@ public class MediaPreferenceFragment extends PreferenceFragment implements Fragm protected AccountCallbacks mCallbacks = DUMMY_CALLBACKS; + private static final int SELECT_RINGTONE_PATH = 40; + private Preference.OnPreferenceClickListener filePickerListener = new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + performFileSearch(SELECT_RINGTONE_PATH); + return true; + } + }; + @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -69,22 +81,43 @@ public class MediaPreferenceFragment extends PreferenceFragment implements Fragm } mCallbacks = (AccountCallbacks) activity; + mCallbacks.addOnAccountChanged(this); } @Override public void onDetach() { super.onDetach(); + if (mCallbacks != null) { + mCallbacks.removeOnAccountChanged(this); + } mCallbacks = DUMMY_CALLBACKS; } - private static final int SELECT_RINGTONE_PATH = 40; - private Preference.OnPreferenceClickListener filePickerListener = new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - performFileSearch(SELECT_RINGTONE_PATH); - return true; + @Override + public void accountChanged(Account acc) { + setPreferenceDetails(acc.getBasicDetails()); + setPreferenceDetails(acc.getAdvancedDetails()); + addPreferenceListener(acc.getAdvancedDetails(), changeAudioPreferenceListener); + final ArrayList<Codec> audioCodec = new ArrayList<>(); + final ArrayList<Codec> videoCodec = new ArrayList<>(); + try { + final ArrayList<Codec> codecList = ((ArrayList<Codec>) mCallbacks.getRemoteService().getCodecList(acc.getAccountID())); + for (Codec codec : codecList) { + if (codec.getType() == Codec.Type.AUDIO) + audioCodec.add(codec); + else if (codec.getType() == Codec.Type.VIDEO) + videoCodec.add(codec); + } + } catch (Exception e) { + Log.e(TAG, "Exception in accountChanged", e); } - }; + + audioCodecsPref.setCodecs(audioCodec); + audioCodecsPref.setOnPreferenceChangeListener(changeCodecListener); + + videoCodecsPref.setCodecs(videoCodec); + videoCodecsPref.setOnPreferenceChangeListener(changeCodecListener); + } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -100,7 +133,6 @@ public class MediaPreferenceFragment extends PreferenceFragment implements Fragm mCallbacks.getAccount().getAdvancedDetails().setDetailString(AccountDetailAdvanced.CONFIG_RINGTONE_PATH, myFile.getAbsolutePath()); mCallbacks.getAccount().notifyObservers(); } - } public void performFileSearch(int requestCodeToSet) { @@ -112,40 +144,17 @@ public class MediaPreferenceFragment extends PreferenceFragment implements Fragm @Override public void onCreatePreferences(Bundle bundle, String s) { - final Account account = mCallbacks.getAccount(); - if (account == null) { - return; - } addPreferencesFromResource(R.xml.account_media_prefs); - setPreferenceDetails(account.getBasicDetails()); - setPreferenceDetails(account.getAdvancedDetails()); + audioCodecsPref = (CodecPreference) findPreference("Account.audioCodecs"); + videoCodecsPref = (CodecPreference) findPreference("Account.videoCodecs"); + findPreference(AccountDetailAdvanced.CONFIG_RINGTONE_PATH).setEnabled( ((TwoStatePreference) findPreference(AccountDetailAdvanced.CONFIG_RINGTONE_ENABLED)).isChecked()); - addPreferenceListener(account.getAdvancedDetails(), changeAudioPreferenceListener); addPreferenceListener(AccountDetailBasic.CONFIG_VIDEO_ENABLED, changeVideoPreferenceListener); - - final ArrayList<Codec> audioCodec = new ArrayList<>(); - final ArrayList<Codec> videoCodec = new ArrayList<>(); - try { - final ArrayList<Codec> codec = ((ArrayList<Codec>) mCallbacks.getRemoteService().getCodecList(account.getAccountID())); - for (Codec c : codec) { - if (c.getType() == Codec.Type.AUDIO) { - audioCodec.add(c); - } else if (c.getType() == Codec.Type.VIDEO) { - videoCodec.add(c); - } - } - } catch (Exception e) { - Log.e(TAG, "Error while retrieving codecs list", e); + final Account acc = mCallbacks.getAccount(); + if (acc != null) { + accountChanged(acc); } - - audioCodecsPref = (CodecPreference) findPreference("Account.audioCodecs"); - audioCodecsPref.setCodecs(audioCodec); - audioCodecsPref.setOnPreferenceChangeListener(changeCodecListener); - - videoCodecsPref = (CodecPreference) findPreference("Account.videoCodecs"); - videoCodecsPref.setCodecs(videoCodec); - videoCodecsPref.setOnPreferenceChangeListener(changeCodecListener); } private final Preference.OnPreferenceChangeListener changeCodecListener = new Preference.OnPreferenceChangeListener() { @@ -154,11 +163,11 @@ public class MediaPreferenceFragment extends PreferenceFragment implements Fragm final Account acc = mCallbacks.getAccount(); ArrayList<Long> audio = audioCodecsPref.getActiveCodecList(); ArrayList<Long> video = videoCodecsPref.getActiveCodecList(); - ArrayList<Long> new_order = new ArrayList<>(audio.size() + video.size()); - new_order.addAll(audio); - new_order.addAll(video); + ArrayList<Long> newOrder = new ArrayList<>(audio.size() + video.size()); + newOrder.addAll(audio); + newOrder.addAll(video); try { - mCallbacks.getRemoteService().setActiveCodecList(new_order, acc.getAccountID()); + mCallbacks.getRemoteService().setActiveCodecList(newOrder, acc.getAccountID()); } catch (RemoteException e) { Log.e(TAG, "Error while setting active codecs", e); } @@ -231,9 +240,9 @@ public class MediaPreferenceFragment extends PreferenceFragment implements Fragm for (int i = 0, n = permissions.length; i < n; i++) { switch (permissions[i]) { case Manifest.permission.CAMERA: - boolean granted = (grantResults[i] == PackageManager.PERMISSION_GRANTED); + boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED; final Account account = mCallbacks.getAccount(); - if (null != account) { + if (account != null) { account.getBasicDetails().setDetailString(AccountDetailBasic.CONFIG_VIDEO_ENABLED, Boolean.toString(granted)); account.notifyObservers(); } diff --git a/ring-android/app/src/main/java/cx/ring/fragments/SecurityAccountFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/SecurityAccountFragment.java index 8df4e5bbe79b242ba305b34131bbc41104738b3a..f7e8da971c6fbc5ed1274b6ac905ce067728e08e 100644 --- a/ring-android/app/src/main/java/cx/ring/fragments/SecurityAccountFragment.java +++ b/ring-android/app/src/main/java/cx/ring/fragments/SecurityAccountFragment.java @@ -37,7 +37,8 @@ import java.io.File; import java.util.ArrayList; import cx.ring.R; -import cx.ring.client.AccountCallbacks; +import cx.ring.interfaces.AccountCallbacks; +import cx.ring.interfaces.AccountChangedListener; import cx.ring.model.account.Account; import cx.ring.model.account.AccountCredentials; import cx.ring.model.account.AccountDetailAdvanced; @@ -47,7 +48,7 @@ import cx.ring.views.CredentialsPreference; import static cx.ring.client.AccountEditionActivity.DUMMY_CALLBACKS; -public class SecurityAccountFragment extends PreferenceFragment { +public class SecurityAccountFragment extends PreferenceFragment implements AccountChangedListener { private static final String DIALOG_FRAGMENT_TAG = "android.support.v14.preference.PreferenceFragment.DIALOG"; private static final int SELECT_CA_LIST_RC = 42; private static final int SELECT_PRIVATE_KEY_RC = 43; @@ -71,14 +72,26 @@ public class SecurityAccountFragment extends PreferenceFragment { } mCallbacks = (AccountCallbacks) activity; + mCallbacks.addOnAccountChanged(this); } @Override public void onDetach() { super.onDetach(); + if (mCallbacks != null) { + mCallbacks.removeOnAccountChanged(this); + } mCallbacks = DUMMY_CALLBACKS; } + @Override + public void accountChanged(Account acc) { + if (acc != null) { + reloadCredentials(); + setDetails(); + } + } + @Override public void onCreatePreferences(Bundle bundle, String s) { addPreferencesFromResource(R.xml.account_security_prefs); @@ -86,10 +99,9 @@ public class SecurityAccountFragment extends PreferenceFragment { credentialsCategory.findPreference("Add.credentials").setOnPreferenceChangeListener(addCredentialListener); tlsCategory = (PreferenceCategory) findPreference("TLS.category"); - Account account = mCallbacks.getAccount(); - if (account != null) { - reloadCredentials(); - setDetails(); + Account acc = mCallbacks.getAccount(); + if (acc != null) { + accountChanged(acc); } } @@ -170,6 +182,7 @@ public class SecurityAccountFragment extends PreferenceFragment { return false; } }; + private Preference.OnPreferenceClickListener filePickerListener = new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { @@ -185,6 +198,7 @@ public class SecurityAccountFragment extends PreferenceFragment { return true; } }; + private Preference.OnPreferenceChangeListener tlsListener = new Preference.OnPreferenceChangeListener() { @Override @@ -216,7 +230,7 @@ public class SecurityAccountFragment extends PreferenceFragment { ArrayList<String> methods = (ArrayList<String>) mCallbacks.getRemoteService().getTlsSupportedMethods(); TLS_METHODS = methods.toArray(new String[methods.size()]); } catch (RemoteException e) { - e.printStackTrace(); + Log.e(TAG, "Exception getting TLS methods", e); } } return TLS_METHODS; @@ -248,11 +262,11 @@ public class SecurityAccountFragment extends PreferenceFragment { } else if (current.getKey().contentEquals(AccountDetailTls.CONFIG_TLS_METHOD)) { String[] values = getTlsMethods(); ListPreference listPreference = (ListPreference) current; - String cur_val = details.getDetailString(current.getKey()); + String curVal = details.getDetailString(current.getKey()); listPreference.setEntries(values); listPreference.setEntryValues(values); - listPreference.setValue(cur_val); - current.setSummary(cur_val); + listPreference.setValue(curVal); + current.setSummary(curVal); } else if (current instanceof EditTextPreference) { String val = details.getDetailString(current.getKey()); ((EditTextPreference) current).setText(val); @@ -351,4 +365,5 @@ public class SecurityAccountFragment extends PreferenceFragment { break; } } + } diff --git a/ring-android/app/src/main/java/cx/ring/client/AccountCallbacks.java b/ring-android/app/src/main/java/cx/ring/interfaces/AccountCallbacks.java similarity index 86% rename from ring-android/app/src/main/java/cx/ring/client/AccountCallbacks.java rename to ring-android/app/src/main/java/cx/ring/interfaces/AccountCallbacks.java index a2d435950fdf0b8f323e952be14c14654dea8e46..f2eaa21b2eaeb78394ea63d0c436ea2056ba1f78 100644 --- a/ring-android/app/src/main/java/cx/ring/client/AccountCallbacks.java +++ b/ring-android/app/src/main/java/cx/ring/interfaces/AccountCallbacks.java @@ -16,11 +16,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package cx.ring.client; +package cx.ring.interfaces; import cx.ring.model.account.Account; import cx.ring.service.LocalService; public interface AccountCallbacks extends LocalService.Callbacks { Account getAccount(); + void addOnAccountChanged(AccountChangedListener list); + void removeOnAccountChanged(AccountChangedListener list); } diff --git a/ring-android/app/src/main/java/cx/ring/interfaces/AccountChangedListener.java b/ring-android/app/src/main/java/cx/ring/interfaces/AccountChangedListener.java new file mode 100644 index 0000000000000000000000000000000000000000..de55b31cfdb137fb6c9032dad59403005e15c21b --- /dev/null +++ b/ring-android/app/src/main/java/cx/ring/interfaces/AccountChangedListener.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016 Savoir-faire Linux Inc. + * + * Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com> + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +package cx.ring.interfaces; + +import cx.ring.model.account.Account; + +public interface AccountChangedListener { + void accountChanged(Account acc); +} diff --git a/ring-android/app/src/main/res/layout/frag_smartlist.xml b/ring-android/app/src/main/res/layout/frag_smartlist.xml index 4e3c8a3ea1313bc71fea48a920a4e7224152efd1..a724c560d19dfb43459ab9d9080f2b3c89810a46 100644 --- a/ring-android/app/src/main/res/layout/frag_smartlist.xml +++ b/ring-android/app/src/main/res/layout/frag_smartlist.xml @@ -36,7 +36,7 @@ along with this program; if not, write to the Free Software android:layout_alignParentTop="true" android:background="@color/error_pane" android:padding="16dp" - android:visibility="visible"> + android:visibility="gone"> <ImageView android:layout_width="28dp" @@ -67,7 +67,8 @@ along with this program; if not, write to the Free Software android:layout_height="wrap_content" android:background="?android:attr/selectableItemBackground" android:orientation="vertical" - android:layout_below="@+id/error_msg_pane"> + android:layout_below="@+id/error_msg_pane" + android:visibility="gone"> <include layout="@layout/item_contact" diff --git a/ring-android/app/src/main/res/layout/item_account_pref.xml b/ring-android/app/src/main/res/layout/item_account_pref.xml index ba28b50599ea12e451d34c0d27f74d74a57f8189..f34faf605915bd39a987763cf8c727d7d2bab2fd 100644 --- a/ring-android/app/src/main/res/layout/item_account_pref.xml +++ b/ring-android/app/src/main/res/layout/item_account_pref.xml @@ -9,18 +9,15 @@ android:id="@+id/drag_handle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_centerVertical="true" android:layout_marginStart="16dp" - android:src="@drawable/ic_reorder_black_24dp" - android:layout_marginLeft="16dp" /> + android:src="@drawable/ic_reorder_black_24dp" /> <TextView android:id="@+id/account_alias" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_marginStart="72dp" @@ -28,21 +25,18 @@ android:textAppearance="@style/ListPrimary" android:layout_toStartOf="@id/error_indicator" android:textAlignment="viewStart" - android:focusable="false" - android:layout_marginLeft="72dp" /> + android:focusable="false" /> <TextView android:id="@+id/account_host" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/account_alias" android:layout_marginStart="72dp" android:ellipsize="middle" android:singleLine="true" android:textAppearance="@style/ListSecondary" - android:layout_marginLeft="72dp" android:layout_toStartOf="@id/error_indicator" android:textAlignment="viewStart" android:focusable="false" /> @@ -67,7 +61,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" - android:layout_marginRight="16dp" + android:layout_marginEnd="16dp" android:layout_toStartOf="@+id/account_checked" android:visibility="gone" /> @@ -77,7 +71,6 @@ android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_centerVertical="true" - android:layout_alignParentRight="true" android:layout_margin="16dp" android:focusable="false" />