diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 9c9a599c4..61014ce33 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -197,6 +197,14 @@ + + + + + + + \ No newline at end of file diff --git a/res/menu/select_local_apps_action_mode.xml b/res/menu/select_local_apps_action_mode.xml new file mode 100644 index 000000000..2550ebcfe --- /dev/null +++ b/res/menu/select_local_apps_action_mode.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/res/menu/select_local_apps_activity.xml b/res/menu/select_local_apps_activity.xml new file mode 100644 index 000000000..0d2d96089 --- /dev/null +++ b/res/menu/select_local_apps_activity.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index bc21277de..ae4f18a66 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -157,12 +157,15 @@ Setup Local Repo Touch to setup your local repo. Updating… + Update Repo Deleting current repo… Adding %s to repo… Writing raw index file (index.xml)… Linking APKs into the repo… Copying app icons into the repo… Finished updating local repo + No applications found + icon Fingerprint: WiFi Network: Enable WiFi diff --git a/src/org/fdroid/fdroid/FDroidApp.java b/src/org/fdroid/fdroid/FDroidApp.java index 1b5bfcf35..d88aae18c 100644 --- a/src/org/fdroid/fdroid/FDroidApp.java +++ b/src/org/fdroid/fdroid/FDroidApp.java @@ -85,7 +85,7 @@ public class FDroidApp extends Application { public static String bssid = ""; public static Repo repo = new Repo(); public static LocalRepoManager localRepo = null; - static Set selectedApps = new HashSet(); + public static Set selectedApps = new HashSet(); private static Messenger localRepoServiceMessenger = null; private static boolean localRepoServiceIsBound = false; diff --git a/src/org/fdroid/fdroid/views/LocalRepoActivity.java b/src/org/fdroid/fdroid/views/LocalRepoActivity.java index 498fd000d..4b87f4d39 100644 --- a/src/org/fdroid/fdroid/views/LocalRepoActivity.java +++ b/src/org/fdroid/fdroid/views/LocalRepoActivity.java @@ -36,6 +36,7 @@ public class LocalRepoActivity extends Activity { private ToggleButton repoSwitch; private int SET_IP_ADDRESS = 7345; + private int UPDATE_REPO = 7346; /** Called when the activity is first created. */ @Override @@ -106,11 +107,7 @@ public class LocalRepoActivity extends Activity { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_setup_repo: - setUIFromWifi(); - String[] packages = new String[2]; - packages[0] = getPackageName(); - packages[1] = "com.android.bluetooth"; - new UpdateAsyncTask(this, packages).execute(); + startActivityForResult(new Intent(this, SelectLocalAppsActivity.class), UPDATE_REPO); return true; case R.id.menu_send_fdroid_via_wifi: startActivity(new Intent(this, QrWizardWifiNetworkActivity.class)); @@ -128,6 +125,10 @@ public class LocalRepoActivity extends Activity { return; if (requestCode == SET_IP_ADDRESS) { setUIFromWifi(); + } else if (requestCode == UPDATE_REPO) { + setUIFromWifi(); + new UpdateAsyncTask(this, FDroidApp.selectedApps.toArray(new String[0])) + .execute(); } } diff --git a/src/org/fdroid/fdroid/views/SelectLocalAppsActivity.java b/src/org/fdroid/fdroid/views/SelectLocalAppsActivity.java new file mode 100644 index 000000000..ff0ad5445 --- /dev/null +++ b/src/org/fdroid/fdroid/views/SelectLocalAppsActivity.java @@ -0,0 +1,89 @@ + +package org.fdroid.fdroid.views; + +import android.annotation.TargetApi; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.view.ActionMode; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; + +import org.fdroid.fdroid.PreferencesActivity; +import org.fdroid.fdroid.R; +import org.fdroid.fdroid.views.fragments.SelectLocalAppsFragment; + +@TargetApi(11) +// TODO replace with appcompat-v7 +public class SelectLocalAppsActivity extends FragmentActivity { + private static final String TAG = "SelectLocalAppsActivity"; + private SelectLocalAppsFragment selectLocalAppsFragment = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.select_local_apps_activity); + } + + @Override + protected void onResume() { + super.onResume(); + if (selectLocalAppsFragment == null) + selectLocalAppsFragment = (SelectLocalAppsFragment) getSupportFragmentManager().findFragmentById( + R.id.fragment_app_list); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.select_local_apps_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + setResult(RESULT_CANCELED); + finish(); + return true; + case R.id.action_settings: + startActivity(new Intent(this, PreferencesActivity.class)); + return true; + } + return super.onOptionsItemSelected(item); + } + + public ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + MenuInflater inflater = mode.getMenuInflater(); + inflater.inflate(R.menu.select_local_apps_action_mode, menu); + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; // Return false if nothing is done + } + + @Override + public boolean onActionItemClicked(final ActionMode mode, MenuItem item) { + switch (item.getItemId()) { + case R.id.action_update_repo: + setResult(RESULT_OK); + finish(); + return true; + default: + return false; + } + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + setResult(RESULT_CANCELED); + finish(); + } + }; +} diff --git a/src/org/fdroid/fdroid/views/fragments/SelectLocalAppsFragment.java b/src/org/fdroid/fdroid/views/fragments/SelectLocalAppsFragment.java new file mode 100644 index 000000000..9eff92157 --- /dev/null +++ b/src/org/fdroid/fdroid/views/fragments/SelectLocalAppsFragment.java @@ -0,0 +1,134 @@ +/* + 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. + */ + +package org.fdroid.fdroid.views.fragments; + +import android.annotation.TargetApi; +import android.database.Cursor; +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.support.v4.widget.SimpleCursorAdapter; +import android.text.TextUtils; +import android.view.ActionMode; +import android.view.View; +import android.widget.ListView; + +import org.fdroid.fdroid.FDroidApp; +import org.fdroid.fdroid.R; +import org.fdroid.fdroid.data.InstalledAppProvider; +import org.fdroid.fdroid.data.InstalledAppProvider.DataColumns; +import org.fdroid.fdroid.views.SelectLocalAppsActivity; + +public class SelectLocalAppsFragment extends ListFragment implements LoaderCallbacks { + + private SelectLocalAppsActivity selectLocalAppsActivity; + private ActionMode mActionMode = null; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @TargetApi(11) + // TODO replace with appcompat-v7 + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + setEmptyText(getString(R.string.no_applications_found)); + + selectLocalAppsActivity = (SelectLocalAppsActivity) getActivity(); + ListView listView = getListView(); + listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(), + android.R.layout.simple_list_item_activated_1, + null, + new String[] { + InstalledAppProvider.DataColumns.APP_ID, + }, + new int[] { + android.R.id.text1, + }, + 0); + setListAdapter(adapter); + setListShown(false); + + // either reconnect with an existing loader or start a new one + getLoaderManager().initLoader(0, null, this); + } + + @TargetApi(11) + // TODO replace with appcompat-v7 + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + if (mActionMode == null) + mActionMode = selectLocalAppsActivity + .startActionMode(selectLocalAppsActivity.mActionModeCallback); + Cursor cursor = (Cursor) l.getAdapter().getItem(position); + String packageName = cursor.getString(1); + if (FDroidApp.selectedApps.contains(packageName)) { + FDroidApp.selectedApps.remove(packageName); + } else { + FDroidApp.selectedApps.add(packageName); + } + } + + @Override + public CursorLoader onCreateLoader(int id, Bundle args) { + CursorLoader loader = new CursorLoader( + this.getActivity(), + InstalledAppProvider.getContentUri(), + InstalledAppProvider.DataColumns.ALL, + null, + null, + InstalledAppProvider.DataColumns.APP_ID); + return loader; + } + + @Override + public void onLoadFinished(Loader loader, Cursor cursor) { + ((SimpleCursorAdapter) this.getListAdapter()).swapCursor(cursor); + + ListView listView = getListView(); + int count = listView.getCount(); + String fdroid = loader.getContext().getPackageName(); + for (int i = 0; i < count; i++) { + Cursor c = ((Cursor) listView.getItemAtPosition(i)); + String packageName = c.getString(c.getColumnIndex(DataColumns.APP_ID)); + if (TextUtils.equals(packageName, fdroid)) { + listView.setItemChecked(i, true); + } else { + for (String selected : FDroidApp.selectedApps) { + if (TextUtils.equals(packageName, selected)) { + listView.setItemChecked(i, true); + } + } + } + } + + if (isResumed()) { + setListShown(true); + } else { + setListShownNoAnimation(true); + } + } + + @Override + public void onLoaderReset(Loader loader) { + ((SimpleCursorAdapter) this.getListAdapter()).swapCursor(null); + } +}