1
0
mirror of https://github.com/etesync/android synced 2024-11-29 11:28:19 +00:00

Minor UI changes

* always notify user on SSL/TLS exceptions (closes #447)
* re-organize UI classes to separate ui package
* re-organize layout and menu resources
* make MANAGE_NETWORK_USAGE intent filter work
This commit is contained in:
Ricki Hirner 2015-03-11 14:34:13 +01:00
parent 23dba581e1
commit 1acd2e1a55
26 changed files with 51 additions and 35 deletions

View File

@ -71,7 +71,7 @@
</service> </service>
<activity <activity
android:name=".MainActivity" android:name=".ui.MainActivity"
android:label="@string/app_name" > android:label="@string/app_name" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -79,7 +79,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".syncadapter.AddAccountActivity" android:name=".ui.setup.AddAccountActivity"
android:excludeFromRecents="true" > android:excludeFromRecents="true" >
</activity> </activity>
<activity <activity
@ -87,6 +87,7 @@
android:label="@string/settings_title" > android:label="@string/settings_title" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE" /> <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity

View File

@ -18,6 +18,8 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import at.bitfire.davdroid.ui.setup.AddAccountActivity;
public class AccountAuthenticatorService extends Service { public class AccountAuthenticatorService extends Service {
private static AccountAuthenticator accountAuthenticator; private static AccountAuthenticator accountAuthenticator;

View File

@ -46,6 +46,7 @@ import at.bitfire.davdroid.R;
import at.bitfire.davdroid.resource.LocalCollection; import at.bitfire.davdroid.resource.LocalCollection;
import at.bitfire.davdroid.resource.LocalStorageException; import at.bitfire.davdroid.resource.LocalStorageException;
import at.bitfire.davdroid.resource.RemoteCollection; import at.bitfire.davdroid.resource.RemoteCollection;
import at.bitfire.davdroid.ui.settings.AccountActivity;
import at.bitfire.davdroid.webdav.DavException; import at.bitfire.davdroid.webdav.DavException;
import at.bitfire.davdroid.webdav.DavHttpClient; import at.bitfire.davdroid.webdav.DavHttpClient;
import at.bitfire.davdroid.webdav.HttpException; import at.bitfire.davdroid.webdav.HttpException;
@ -133,6 +134,7 @@ public abstract class DavSyncAdapter extends AbstractThreadedSyncAdapter impleme
Log.d(TAG, "Server supports VCard version " + accountSettings.getAddressBookVCardVersion()); Log.d(TAG, "Server supports VCard version " + accountSettings.getAddressBookVCardVersion());
Exception exceptionToShow = null; // exception to show notification for Exception exceptionToShow = null; // exception to show notification for
Intent exceptionIntent = null; // what shall happen when clicking on the exception notification
try { try {
// get local <-> remote collection pairs // get local <-> remote collection pairs
Map<LocalCollection<?>, RemoteCollection<?>> syncCollections = getSyncPairs(account, provider); Map<LocalCollection<?>, RemoteCollection<?>> syncCollections = getSyncPairs(account, provider);
@ -142,34 +144,41 @@ public abstract class DavSyncAdapter extends AbstractThreadedSyncAdapter impleme
try { try {
for (Map.Entry<LocalCollection<?>, RemoteCollection<?>> entry : syncCollections.entrySet()) for (Map.Entry<LocalCollection<?>, RemoteCollection<?>> entry : syncCollections.entrySet())
new SyncManager(entry.getKey(), entry.getValue()).synchronize(extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL), syncResult); new SyncManager(entry.getKey(), entry.getValue()).synchronize(extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL), syncResult);
} catch (DavException ex) { } catch (DavException ex) {
exceptionToShow = ex;
syncResult.stats.numParseExceptions++; syncResult.stats.numParseExceptions++;
Log.e(TAG, "Invalid DAV response", ex); Log.e(TAG, "Invalid DAV response", ex);
exceptionToShow = ex;
} catch (HttpException ex) { } catch (HttpException ex) {
if (ex.getCode() == HttpStatus.SC_UNAUTHORIZED) { if (ex.getCode() == HttpStatus.SC_UNAUTHORIZED) {
exceptionToShow = ex;
Log.e(TAG, "HTTP Unauthorized " + ex.getCode(), ex); Log.e(TAG, "HTTP Unauthorized " + ex.getCode(), ex);
syncResult.stats.numAuthExceptions++; // hard error syncResult.stats.numAuthExceptions++; // hard error
} else if (ex.isClientError()) {
exceptionToShow = ex; exceptionToShow = ex;
exceptionIntent = new Intent(context, AccountActivity.class);
exceptionIntent.putExtra(AccountActivity.EXTRA_ACCOUNT, account);
} else if (ex.isClientError()) {
Log.e(TAG, "Hard HTTP error " + ex.getCode(), ex); Log.e(TAG, "Hard HTTP error " + ex.getCode(), ex);
syncResult.stats.numParseExceptions++; // hard error syncResult.stats.numParseExceptions++; // hard error
exceptionToShow = ex;
} else { } else {
Log.w(TAG, "Soft HTTP error " + ex.getCode() + " (Android will try again later)", ex); Log.w(TAG, "Soft HTTP error " + ex.getCode() + " (Android will try again later)", ex);
syncResult.stats.numIoExceptions++; // soft error syncResult.stats.numIoExceptions++; // soft error
} }
} catch (LocalStorageException ex) { } catch (LocalStorageException ex) {
exceptionToShow = ex;
syncResult.databaseError = true; // hard error syncResult.databaseError = true; // hard error
Log.e(TAG, "Local storage (content provider) exception", ex); Log.e(TAG, "Local storage (content provider) exception", ex);
exceptionToShow = ex;
} catch (IOException ex) { } catch (IOException ex) {
syncResult.stats.numIoExceptions++; // soft error syncResult.stats.numIoExceptions++; // soft error
Log.e(TAG, "I/O error (Android will try again later)", ex); Log.e(TAG, "I/O error (Android will try again later)", ex);
} catch (URISyntaxException ex) { if (ex instanceof SSLException) // always notify on SSL/TLS errors
exceptionToShow = ex; exceptionToShow = ex;
} catch (URISyntaxException ex) {
syncResult.stats.numParseExceptions++; // hard error syncResult.stats.numParseExceptions++; // hard error
Log.e(TAG, "Invalid URI (file name) syntax", ex); Log.e(TAG, "Invalid URI (file name) syntax", ex);
exceptionToShow = ex;
} }
} finally { } finally {
// allow httpClient shutdown // allow httpClient shutdown
@ -178,8 +187,10 @@ public abstract class DavSyncAdapter extends AbstractThreadedSyncAdapter impleme
// show sync errors as notification // show sync errors as notification
if (exceptionToShow != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { if (exceptionToShow != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
Intent intentHelp = new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.WEB_URL_VIEW_LOGS)); if (exceptionIntent == null)
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intentHelp, 0); exceptionIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.WEB_URL_VIEW_LOGS));
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, exceptionIntent, 0);
Notification.Builder builder = new Notification.Builder(context) Notification.Builder builder = new Notification.Builder(context)
.setSmallIcon(R.drawable.ic_launcher) .setSmallIcon(R.drawable.ic_launcher)
.setPriority(Notification.PRIORITY_LOW) .setPriority(Notification.PRIORITY_LOW)

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid; package at.bitfire.davdroid.ui;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
@ -20,7 +20,9 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import at.bitfire.davdroid.syncadapter.AddAccountActivity; import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.ui.setup.AddAccountActivity;
import at.bitfire.davdroid.ui.settings.SettingsActivity; import at.bitfire.davdroid.ui.settings.SettingsActivity;
public class MainActivity extends Activity { public class MainActivity extends Activity {
@ -29,7 +31,7 @@ public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.main_activity);
TextView tvWorkaround = (TextView)findViewById(R.id.text_workaround); TextView tvWorkaround = (TextView)findViewById(R.id.text_workaround);
if (fromPlayStore()) { if (fromPlayStore()) {

View File

@ -17,7 +17,7 @@ import android.util.Log;
import at.bitfire.davdroid.R; import at.bitfire.davdroid.R;
public class AccountActivity extends Activity { public class AccountActivity extends Activity {
static final String EXTRA_ACCOUNT = "account"; public static final String EXTRA_ACCOUNT = "account";
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.ui.setup;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
@ -31,6 +31,7 @@ import at.bitfire.davdroid.R;
import at.bitfire.davdroid.resource.LocalCalendar; import at.bitfire.davdroid.resource.LocalCalendar;
import at.bitfire.davdroid.resource.LocalStorageException; import at.bitfire.davdroid.resource.LocalStorageException;
import at.bitfire.davdroid.resource.ServerInfo; import at.bitfire.davdroid.resource.ServerInfo;
import at.bitfire.davdroid.syncadapter.AccountSettings;
public class AccountDetailsFragment extends Fragment implements TextWatcher { public class AccountDetailsFragment extends Fragment implements TextWatcher {
public static final String KEY_SERVER_INFO = "server_info"; public static final String KEY_SERVER_INFO = "server_info";
@ -42,7 +43,7 @@ public class AccountDetailsFragment extends Fragment implements TextWatcher {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.account_details, container, false); View v = inflater.inflate(R.layout.setup_account_details, container, false);
serverInfo = (ServerInfo)getArguments().getSerializable(KEY_SERVER_INFO); serverInfo = (ServerInfo)getArguments().getSerializable(KEY_SERVER_INFO);
@ -61,7 +62,7 @@ public class AccountDetailsFragment extends Fragment implements TextWatcher {
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.account_details, menu); inflater.inflate(R.menu.setup_account_details, menu);
} }
@Override @Override

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.ui.setup;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
@ -24,11 +24,11 @@ public class AddAccountActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.add_account); setContentView(R.layout.setup_add_account);
if (savedInstanceState == null) { // first call if (savedInstanceState == null) { // first call
getFragmentManager().beginTransaction() getFragmentManager().beginTransaction()
.add(R.id.right_pane, new LoginTypeFragment(), "login_type") .add(R.id.right_pane, new LoginTypeFragment())
.commit(); .commit();
} }
} }
@ -36,7 +36,7 @@ public class AddAccountActivity extends Activity {
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater(); MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.add_account, menu); inflater.inflate(R.menu.setup_add_account, menu);
return true; return true;
} }

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.ui.setup;
import android.app.DialogFragment; import android.app.DialogFragment;
import android.app.Fragment; import android.app.Fragment;
@ -33,7 +33,7 @@ public class LoginEmailFragment extends Fragment implements TextWatcher {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.login_email, container, false); View v = inflater.inflate(R.layout.setup_login_email, container, false);
editEmail = (EditText)v.findViewById(R.id.email_address); editEmail = (EditText)v.findViewById(R.id.email_address);
editEmail.addTextChangedListener(this); editEmail.addTextChangedListener(this);

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.ui.setup;
import android.app.Fragment; import android.app.Fragment;
import android.os.Bundle; import android.os.Bundle;
@ -26,7 +26,7 @@ public class LoginTypeFragment extends Fragment {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.login_type, container, false); View v = inflater.inflate(R.layout.setup_login_type, container, false);
btnTypeEmail = (RadioButton)v.findViewById(R.id.login_type_email); btnTypeEmail = (RadioButton)v.findViewById(R.id.login_type_email);
btnTypeURL = (RadioButton)v.findViewById(R.id.login_type_url); btnTypeURL = (RadioButton)v.findViewById(R.id.login_type_url);

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.ui.setup;
import android.app.DialogFragment; import android.app.DialogFragment;
import android.app.Fragment; import android.app.Fragment;
@ -45,7 +45,7 @@ public class LoginURLFragment extends Fragment implements TextWatcher {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.login_url, container, false); View v = inflater.inflate(R.layout.setup_login_url, container, false);
// protocol selection spinner // protocol selection spinner
textHttpWarning = (TextView)v.findViewById(R.id.http_warning); textHttpWarning = (TextView)v.findViewById(R.id.http_warning);

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.ui.setup;
import android.app.DialogFragment; import android.app.DialogFragment;
import android.app.LoaderManager.LoaderCallbacks; import android.app.LoaderManager.LoaderCallbacks;
@ -57,7 +57,7 @@ public class QueryServerDialogFragment extends DialogFragment implements LoaderC
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.query_server, container, false); return inflater.inflate(R.layout.setup_query_server, container, false);
} }
@Override @Override

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.ui.setup;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
@ -19,7 +19,6 @@ import android.widget.ListAdapter;
import at.bitfire.davdroid.R; import at.bitfire.davdroid.R;
import at.bitfire.davdroid.resource.ServerInfo; import at.bitfire.davdroid.resource.ServerInfo;
import at.bitfire.davdroid.resource.ServerInfo.ResourceInfo.Type;
import lombok.Getter; import lombok.Getter;
public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter { public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter {
@ -104,14 +103,14 @@ public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter
LayoutInflater inflater = LayoutInflater.from(parent.getContext()); LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (getItemViewType(position)) { switch (getItemViewType(position)) {
case TYPE_ADDRESS_BOOKS_HEADING: case TYPE_ADDRESS_BOOKS_HEADING:
v = inflater.inflate(R.layout.address_books_heading, parent, false); v = inflater.inflate(R.layout.setup_address_books_heading, parent, false);
break; break;
case TYPE_ADDRESS_BOOKS_ROW: case TYPE_ADDRESS_BOOKS_ROW:
v = inflater.inflate(android.R.layout.simple_list_item_single_choice, null); v = inflater.inflate(android.R.layout.simple_list_item_single_choice, null);
v.setPadding(0, 8, 0, 8); v.setPadding(0, 8, 0, 8);
break; break;
case TYPE_CALENDARS_HEADING: case TYPE_CALENDARS_HEADING:
v = inflater.inflate(R.layout.calendars_heading, parent, false); v = inflater.inflate(R.layout.setup_calendars_heading, parent, false);
break; break;
case TYPE_CALENDARS_ROW: case TYPE_CALENDARS_ROW:
v = inflater.inflate(android.R.layout.simple_list_item_multiple_choice, null); v = inflater.inflate(android.R.layout.simple_list_item_multiple_choice, null);

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.ui.setup;
import android.app.ListFragment; import android.app.ListFragment;
import android.os.Bundle; import android.os.Bundle;
@ -47,7 +47,7 @@ public class SelectCollectionsFragment extends ListFragment {
final ListView listView = getListView(); final ListView listView = getListView();
listView.setPadding(20, 30, 20, 30); listView.setPadding(20, 30, 20, 30);
View header = getActivity().getLayoutInflater().inflate(R.layout.select_collections_header, getListView(), false); View header = getActivity().getLayoutInflater().inflate(R.layout.setup_select_collections_header, getListView(), false);
listView.addHeaderView(header, getListView(), false); listView.addHeaderView(header, getListView(), false);
final ServerInfo serverInfo = (ServerInfo)getArguments().getSerializable(KEY_SERVER_INFO); final ServerInfo serverInfo = (ServerInfo)getArguments().getSerializable(KEY_SERVER_INFO);

View File

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*/ */
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.ui.setup;
import android.content.Context; import android.content.Context;
import android.view.LayoutInflater; import android.view.LayoutInflater;