port everything to appcompat-v7 (#42, #51)

I went through all of the source code replacing anything that is now
possible using appcompat-v7.  appcompat-v7 is the official way to handle
backwards compatibility, and it is supported by Google and others. Using it
as much as possible should make the code more maintainable and readable by
others since they'll be used to seeing the appcompat-v7 patterns from other
projects.

fixes #51 https://gitlab.com/fdroid/fdroidclient/issues/51
fixes #42 https://gitlab.com/fdroid/fdroidclient/issues/42
This commit is contained in:
Hans-Christoph Steiner 2014-07-09 17:50:57 -04:00
parent 3fef37a5f4
commit b06792524e
14 changed files with 167 additions and 194 deletions

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingBottom="2dip"
android:paddingTop="2dip" >
<ImageView
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_marginTop="6dip"
tools:ignore="ContentDescription" />
<TwoLineListItem
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:mode="twoLine" >
<TextView
android:id="@+id/application_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_marginTop="6dip"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/package_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/application_label"
android:layout_below="@+id/application_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
</TwoLineListItem>
</LinearLayout>

View File

@ -1,28 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:baselineAligned="false" >
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingBottom="2dip"
android:paddingTop="2dip" >
<!-- Actual icon size is dependent on preferences and set in
AppListAdapater.java:layoutIcon() -->
<ImageView
android:id="@+id/icon"
android:contentDescription="@string/app_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_marginTop="6dip"
android:scaleType="fitCenter"
/>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingStart="10dp"
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginRight="?attr/listPreferredItemPaddingRight"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_gravity="center_vertical"
android:baselineAligned="false" >
@ -54,8 +58,8 @@
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_gravity="center_vertical"
android:gravity="end"
android:textAlignment="viewEnd"
@ -89,8 +93,8 @@
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6sp"
android:layout_marginStart="6sp"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_gravity="center_vertical"
android:gravity="end"
android:textAlignment="viewEnd"

View File

@ -16,19 +16,15 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeight"
android:minHeight="?attr/listPreferredItemHeight"
android:paddingBottom="2dip"
android:paddingTop="2dip"
tools:ignore="NewApi" >
<!-- TODO remove NewApi ignore when appcompat-v7 is in place -->
android:paddingTop="2dip" >
<ImageView
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingLeft"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_marginTop="6dip"
tools:ignore="ContentDescription" />
@ -41,16 +37,17 @@
android:id="@+id/application_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingLeft"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_marginTop="6dip"
android:textAppearance="?android:attr/textAppearanceListItem" />
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/package_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/application_label"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_below="@+id/application_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
</TwoLineListItem>

View File

@ -1,20 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/menu_setup_repo"
android:icon="@android:drawable/ic_input_add"
android:showAsAction="ifRoom|withText"
android:title="@string/setup_repo"/>
android:title="@string/setup_repo"
app:showAsAction="ifRoom|withText"/>
<item
android:id="@+id/menu_send_fdroid_via_wifi"
android:icon="@android:drawable/arrow_up_float"
android:showAsAction="never"
android:title="@string/send_fdroid_via_wifi"/>
android:title="@string/send_fdroid_via_wifi"
app:showAsAction="never"/>
<item
android:id="@+id/menu_settings"
android:icon="@android:drawable/ic_menu_preferences"
android:showAsAction="never"
android:title="@string/menu_preferences"/>
android:title="@string/menu_preferences"
app:showAsAction="never"/>
</menu>
</menu>

View File

@ -1,14 +1,17 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/action_search"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="ifRoom"
android:title="@string/menu_search"/>
android:title="@string/menu_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_update_repo"
android:icon="@android:drawable/ic_input_add"
android:showAsAction="always|withText"
android:title="@string/update_repo"/>
android:title="@string/update_repo"
app:showAsAction="always"/>
</menu>

View File

@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="collapseActionView|always"
android:icon="@android:drawable/ic_menu_search"
android:title="@string/menu_search"/>
android:title="@string/menu_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="collapseActionView|always"/>
<item
android:id="@+id/action_settings"
android:icon="@android:drawable/ic_menu_preferences"
android:title="@string/menu_preferences"
app:showAsAction="never"/>
app:showAsAction="ifRoom"/>
</menu>

View File

@ -59,12 +59,12 @@ import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import org.fdroid.fdroid.Utils.CommaSeparatedList;
import org.fdroid.fdroid.compat.ActionBarCompat;
import org.fdroid.fdroid.compat.MenuManager;
import org.fdroid.fdroid.compat.PackageManagerCompat;
import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.data.ApkProvider;
@ -126,18 +126,18 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
TextView added;
TextView nativecode;
}
// observer to update view when package has been installed/deleted
AppObserver myAppObserver;
class AppObserver extends ContentObserver {
public AppObserver(Handler handler) {
super(handler);
super(handler);
}
@Override
public void onChange(boolean selfChange) {
this.onChange(selfChange, null);
}
}
@Override
public void onChange(boolean selfChange, Uri uri) {
@ -147,7 +147,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
}
refreshApkList();
MenuManager.create(AppDetails.this).invalidateOptionsMenu();
supportInvalidateOptionsMenu();
}
}
@ -384,7 +384,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
mPm = getPackageManager();
installer = Installer.getActivityInstaller(this, mPm, myInstallerCallback);
// Get the preferences we're going to use in this Activity...
ConfigurationChangeHelper previousData = (ConfigurationChangeHelper)getLastCustomNonConfigurationInstance();
if (previousData != null) {
@ -409,10 +409,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
// fragments, which rely on data from the activity that is set earlier in this method.
setContentView(R.layout.app_details);
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
// for reason why.
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Check for the presence of a view which only exists in the landscape view.
// This seems to be the preferred way to interrogate the view, rather than
@ -463,7 +460,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
protected void onResumeFragments() {
super.onResumeFragments();
refreshApkList();
MenuManager.create(this).invalidateOptionsMenu();
supportInvalidateOptionsMenu();
}
/**
@ -800,6 +797,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
}
// Install the version of this app denoted by 'app.curApk'.
@Override
public void install(final Apk apk) {
String [] projection = { RepoProvider.DataColumns.ADDRESS };
Repo repo = RepoProvider.Helper.findById(this, apk.repo, projection);
@ -883,7 +881,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
public void onSuccess(final int operation) {
runOnUiThread(new Runnable() {
@Override
public void run() {
public void run() {
if (operation == Installer.InstallerCallback.OPERATION_INSTALL) {
PackageManagerCompat.setInstaller(mPm, app.id);
}
@ -907,9 +905,9 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
@Override
public void run() {
setProgressBarIndeterminateVisibility(false);
Log.e(TAG, "Installer aborted with errorCode: " + errorCode);
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(AppDetails.this);
alertBuilder.setTitle(R.string.installer_error_title);
alertBuilder.setMessage(R.string.installer_error_title);
@ -1049,7 +1047,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
if (installer.handleOnActivityResult(requestCode, resultCode, data)) {
return;
}
switch (requestCode) {
case REQUEST_ENABLE_BLUETOOTH:
fdroidApp.sendViaBluetooth(this, resultCode, app.id);
@ -1057,18 +1055,22 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A
}
}
@Override
public App getApp() {
return app;
}
@Override
public ApkListAdapter getApks() {
return adapter;
}
@Override
public Signature getInstalledSignature() {
return mInstalledSignature;
}
@Override
public String getInstalledSignatureId() {
return mInstalledSigID;
}

View File

@ -18,25 +18,49 @@
package org.fdroid.fdroid;
import android.app.*;
import android.content.*;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.*;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import org.fdroid.fdroid.data.*;
import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.data.ApkProvider;
import org.fdroid.fdroid.data.App;
import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.net.Downloader;
import org.fdroid.fdroid.updater.RepoUpdater;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UpdateService extends IntentService implements ProgressListener {

View File

@ -1,64 +0,0 @@
package org.fdroid.fdroid.compat;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
public abstract class ActionBarCompat extends Compatibility {
public static ActionBarCompat create(Activity activity) {
if (hasApi(11)) {
return new HoneycombActionBarCompatImpl(activity);
} else {
return new OldActionBarCompatImpl(activity);
}
}
protected final Activity activity;
public ActionBarCompat(Activity activity) {
this.activity = activity;
}
/**
* Cannot be accessed until after setContentView (on 3.0 and 3.1 devices) has
* been called on the relevant activity. If you don't have a content view
* (e.g. when using fragment manager to add fragments to the activity) then you
* will still need to call setContentView(), with a "new LinearLayout()" or something
* useless like that.
* See: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
* for details.
*/
public abstract void setDisplayHomeAsUpEnabled(boolean value);
}
class OldActionBarCompatImpl extends ActionBarCompat {
public OldActionBarCompatImpl(Activity activity) {
super(activity);
}
@Override
public void setDisplayHomeAsUpEnabled(boolean value) {
// Do nothing...
}
}
@TargetApi(11)
class HoneycombActionBarCompatImpl extends ActionBarCompat {
private final ActionBar actionBar;
public HoneycombActionBarCompatImpl(Activity activity) {
super(activity);
this.actionBar = activity.getActionBar();
}
@Override
public void setDisplayHomeAsUpEnabled(boolean value) {
actionBar.setDisplayHomeAsUpEnabled(value);
}
}

View File

@ -1,49 +0,0 @@
package org.fdroid.fdroid.compat;
import android.annotation.TargetApi;
import android.app.Activity;
abstract public class MenuManager extends Compatibility {
public static MenuManager create(Activity activity) {
if (hasApi(11)) {
return new HoneycombMenuManagerImpl(activity);
} else {
return new OldMenuManagerImpl(activity);
}
}
protected final Activity activity;
protected MenuManager(Activity activity) {
this.activity = activity;
}
abstract public void invalidateOptionsMenu();
}
class OldMenuManagerImpl extends MenuManager {
protected OldMenuManagerImpl(Activity activity) {
super(activity);
}
@Override
public void invalidateOptionsMenu() {
}
}
@TargetApi(11)
class HoneycombMenuManagerImpl extends MenuManager {
protected HoneycombMenuManagerImpl(Activity activity) {
super(activity);
}
@Override
public void invalidateOptionsMenu() {
activity.invalidateOptionsMenu();
}
}

View File

@ -1,7 +1,6 @@
package org.fdroid.fdroid.views;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.support.v4.widget.CursorAdapter;
@ -11,10 +10,12 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.data.App;

View File

@ -30,6 +30,7 @@ import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.PreferencesActivity;
import org.fdroid.fdroid.QrGenAsyncTask;
@ -158,8 +159,6 @@ public class LocalRepoActivity extends ActionBarActivity {
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.local_repo_activity, menu);
if (Build.VERSION.SDK_INT < 14) // TODO remove after including appcompat-v7
menu.findItem(R.id.menu_setup_repo).setVisible(false);
return true;
}

View File

@ -5,11 +5,12 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.SearchView;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.PreferencesActivity;
import org.fdroid.fdroid.R;
@ -51,10 +52,6 @@ public class SelectLocalAppsActivity extends ActionBarActivity {
setResult(RESULT_CANCELED);
finish();
return true;
case R.id.action_search:
SearchView searchView = (SearchView) item.getActionView();
searchView.setIconified(false);
return true;
case R.id.action_settings:
startActivity(new Intent(this, PreferencesActivity.class));
return true;
@ -68,7 +65,6 @@ public class SelectLocalAppsActivity extends ActionBarActivity {
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.select_local_apps_action_mode, menu);
menu.findItem(R.id.action_search).setActionView(searchView);
return true;
}

View File

@ -23,16 +23,17 @@ import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter.ViewBinder;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.SearchView.OnQueryTextListener;
import android.text.TextUtils;
import android.view.ActionMode;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.SimpleCursorAdapter.ViewBinder;
import android.widget.TextView;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.data.InstalledAppProvider;
@ -125,8 +126,8 @@ public class SelectLocalAppsFragment extends ListFragment
public void onListItemClick(ListView l, View v, int position, long id) {
if (mActionMode == null)
mActionMode = selectLocalAppsActivity
.startActionMode(selectLocalAppsActivity.mActionModeCallback);
Cursor c = (Cursor) l.getAdapter().getItem(position);
.startSupportActionMode(selectLocalAppsActivity.mActionModeCallback);
Cursor c = (Cursor) getListAdapter().getItem(position);
String packageName = c.getString(c.getColumnIndex(DataColumns.APP_ID));
if (FDroidApp.selectedApps.contains(packageName)) {
FDroidApp.selectedApps.remove(packageName);
@ -155,7 +156,8 @@ public class SelectLocalAppsFragment extends ListFragment
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
((SimpleCursorAdapter) this.getListAdapter()).swapCursor(cursor);
SimpleCursorAdapter adapter = (SimpleCursorAdapter) getListAdapter();
adapter.swapCursor(cursor);
ListView listView = getListView();
int count = listView.getCount();
@ -183,7 +185,8 @@ public class SelectLocalAppsFragment extends ListFragment
@Override
public void onLoaderReset(Loader<Cursor> loader) {
((SimpleCursorAdapter) this.getListAdapter()).swapCursor(null);
SimpleCursorAdapter adapter = (SimpleCursorAdapter) getListAdapter();
adapter.swapCursor(null);
}
@Override