Moved code from LocalRepo to the Swap UI to reuse it.
Along with a bunch of networking stuff, a lot of UI to do with selecting apps to swap was also moved. The background on the list is transparent, which allows blue to shine through. Also, the text on the list items is white, which will not work with a white background. I've temporarily dropped support for searching this list too, until I get some feedback from carrie et al. NOTE: This stuff was written before hans fixed apcompat problems with LocalRepoActivity, but then rebased over it later. As such, it doesn't contain his fixes. Will need to do that before a stable release. i.e. Still has a bit of a dependency on API 11 which needs to be resolved.
This commit is contained in:
parent
ae9cb5b89b
commit
6d807793c2
@ -14,7 +14,7 @@
|
|||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/checkbox_dont_show"
|
android:id="@+id/button_start_swap"
|
||||||
android:text="START A SWAP"
|
android:text="START A SWAP"
|
||||||
style="@style/SwapTheme.AppList.StartButton"
|
style="@style/SwapTheme.AppList.StartButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -14,27 +14,27 @@
|
|||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
tools:text="One person needs to scan the code, or type the URL of the other swapper into a browser."
|
android:text="One person needs to scan the code, or type the URL of the other swapper into a browser."
|
||||||
style="@style/SwapTheme.Wizard.MainText"/>
|
style="@style/SwapTheme.Wizard.MainText"/>
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/wifi_qr_code"
|
android:id="@+id/wifi_qr_code"
|
||||||
tools:src="@drawable/swap_qr_example"
|
tools:src="@drawable/swap_qr_example"
|
||||||
android:layout_below="@+id/textView" android:layout_above="@+id/device_ip_address"/>
|
android:layout_below="@+id/textView"
|
||||||
|
android:layout_above="@+id/device_ip_address"/>
|
||||||
|
|
||||||
<Button style="@style/SwapTheme.Wizard.OptionButton"
|
<Button style="@style/SwapTheme.Wizard.OptionButton"
|
||||||
android:id="@+id/btn_not_working"
|
android:id="@+id/btn_not_working"
|
||||||
android:text="It's not working"
|
android:text="@string/swap_wifi_qr_not_working"
|
||||||
android:layout_alignParentBottom="true" />
|
android:layout_alignParentBottom="true" />
|
||||||
|
|
||||||
<Button style="@style/SwapTheme.Wizard.OptionButton"
|
<Button style="@style/SwapTheme.Wizard.OptionButton"
|
||||||
android:text="Open QR Code Scanner"
|
android:text="@string/open_qr_code_scanner"
|
||||||
android:layout_above="@id/btn_not_working" android:layout_gravity="center" android:id="@+id/button"/>
|
android:layout_above="@id/btn_not_working" android:layout_gravity="center" android:id="@+id/button"/>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="New Text"
|
|
||||||
android:id="@+id/device_ip_address"
|
android:id="@+id/device_ip_address"
|
||||||
tools:text="192.168.1.1:8888"
|
tools:text="192.168.1.1:8888"
|
||||||
android:layout_above="@+id/button" android:layout_centerHorizontal="true"
|
android:layout_above="@+id/button" android:layout_centerHorizontal="true"
|
||||||
|
11
res/menu/swap_skip.xml
Normal file
11
res/menu/swap_skip.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_skip"
|
||||||
|
android:title="Skip"
|
||||||
|
android:titleCondensed="Skip"/>
|
||||||
|
|
||||||
|
<!-- Currently in a style, but that style probably wont work on 8 -> 11 devices -->
|
||||||
|
<!--android:drawable="@drawable/swap_action_button_skin"-->
|
||||||
|
|
||||||
|
</menu>
|
@ -303,4 +303,6 @@
|
|||||||
<string name="swap">Swap apps</string>
|
<string name="swap">Swap apps</string>
|
||||||
<string name="swap_no_wifi_network">No network yet</string>
|
<string name="swap_no_wifi_network">No network yet</string>
|
||||||
<string name="swap_view_available_networks">(Tap to open available networks)</string>
|
<string name="swap_view_available_networks">(Tap to open available networks)</string>
|
||||||
|
<string name="swap_wifi_qr_not_working">It\'s not working</string>
|
||||||
|
<string name="open_qr_code_scanner">Open QR Code Scanner</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -40,6 +40,8 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="SwapTheme.AppList" parent="AppThemeLightWithDarkActionBar">
|
<style name="SwapTheme.AppList" parent="AppThemeLightWithDarkActionBar">
|
||||||
|
<item name="android:windowBackground">@color/white</item>
|
||||||
|
<item name="android:background">@color/white</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="SwapTheme.AppList.StartButton">
|
<style name="SwapTheme.AppList.StartButton">
|
||||||
|
@ -56,6 +56,7 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
|||||||
public static final String PREF_ENABLE_PROXY = "enableProxy";
|
public static final String PREF_ENABLE_PROXY = "enableProxy";
|
||||||
public static final String PREF_PROXY_HOST = "proxyHost";
|
public static final String PREF_PROXY_HOST = "proxyHost";
|
||||||
public static final String PREF_PROXY_PORT = "proxyPort";
|
public static final String PREF_PROXY_PORT = "proxyPort";
|
||||||
|
public static final String PREF_SHOW_NFC_DURING_SWAP = "showNfcDuringSwap";
|
||||||
|
|
||||||
private static final boolean DEFAULT_COMPACT_LAYOUT = false;
|
private static final boolean DEFAULT_COMPACT_LAYOUT = false;
|
||||||
private static final boolean DEFAULT_ROOTED = true;
|
private static final boolean DEFAULT_ROOTED = true;
|
||||||
@ -70,6 +71,7 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
|||||||
private static final boolean DEFAULT_ENABLE_PROXY = false;
|
private static final boolean DEFAULT_ENABLE_PROXY = false;
|
||||||
public static final String DEFAULT_PROXY_HOST = "127.0.0.1";
|
public static final String DEFAULT_PROXY_HOST = "127.0.0.1";
|
||||||
public static final int DEFAULT_PROXY_PORT = 8118;
|
public static final int DEFAULT_PROXY_PORT = 8118;
|
||||||
|
public static final boolean DEFAULT_SHOW_NFC_DURING_SWAP = true;
|
||||||
|
|
||||||
private boolean compactLayout = DEFAULT_COMPACT_LAYOUT;
|
private boolean compactLayout = DEFAULT_COMPACT_LAYOUT;
|
||||||
private boolean filterAppsRequiringRoot = DEFAULT_ROOTED;
|
private boolean filterAppsRequiringRoot = DEFAULT_ROOTED;
|
||||||
@ -115,6 +117,14 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
|||||||
return preferences.getBoolean(PREF_PERMISSIONS, DEFAULT_PERMISSIONS);
|
return preferences.getBoolean(PREF_PERMISSIONS, DEFAULT_PERMISSIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean showNfcDuringSwap() {
|
||||||
|
return preferences.getBoolean(PREF_SHOW_NFC_DURING_SWAP, DEFAULT_SHOW_NFC_DURING_SWAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShowNfcDuringSwap(boolean show) {
|
||||||
|
preferences.edit().putBoolean(PREF_SHOW_NFC_DURING_SWAP, show).commit();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean expertMode() {
|
public boolean expertMode() {
|
||||||
return preferences.getBoolean(PREF_EXPERT, DEFAULT_EXPERT);
|
return preferences.getBoolean(PREF_EXPERT, DEFAULT_EXPERT);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
@ -13,7 +14,6 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
@ -33,7 +33,7 @@ public class JoinWifiFragment extends Fragment {
|
|||||||
joinWifiView.setOnClickListener(new View.OnClickListener() {
|
joinWifiView.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Toast.makeText(getActivity(), "Touched view", Toast.LENGTH_LONG);
|
openAvailableNetworks();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return joinWifiView;
|
return joinWifiView;
|
||||||
@ -61,4 +61,8 @@ public class JoinWifiFragment extends Fragment {
|
|||||||
ssidView.setText(text);
|
ssidView.setText(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void openAvailableNetworks() {
|
||||||
|
startActivity(new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,61 @@
|
|||||||
package org.fdroid.fdroid.views.swap;
|
package org.fdroid.fdroid.views.swap;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.nfc.NdefMessage;
|
||||||
|
import android.nfc.NdefRecord;
|
||||||
|
import android.nfc.NfcAdapter;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.Utils;
|
||||||
|
|
||||||
public class NfcSwapFragment extends Fragment {
|
public class NfcSwapFragment extends Fragment {
|
||||||
|
|
||||||
@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.swap_nfc, container, false);
|
View view = inflater.inflate(R.layout.swap_nfc, container, false);
|
||||||
|
CheckBox dontShowAgain = (CheckBox)view.findViewById(R.id.checkbox_dont_show);
|
||||||
|
dontShowAgain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
Preferences.get().setShowNfcDuringSwap(!isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setupNfc();
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isNfcSupported(Context context) {
|
||||||
|
return Build.VERSION.SDK_INT >= 14 && getNfcAdapter(context) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(10)
|
||||||
|
private static NfcAdapter getNfcAdapter(Context context) {
|
||||||
|
return NfcAdapter.getDefaultAdapter(context.getApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(10)
|
||||||
|
private void setupNfc() {
|
||||||
|
// the required NFC API was added in 4.0 aka Ice Cream Sandwich
|
||||||
|
if (Build.VERSION.SDK_INT >= 14) {
|
||||||
|
NfcAdapter nfcAdapter = getNfcAdapter(getActivity());
|
||||||
|
if (nfcAdapter == null)
|
||||||
|
return;
|
||||||
|
nfcAdapter.setNdefPushMessage(new NdefMessage(new NdefRecord[] {
|
||||||
|
NdefRecord.createUri(Utils.getSharingUri(getActivity(), FDroidApp.repo)),
|
||||||
|
}), getActivity());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
198
src/org/fdroid/fdroid/views/swap/SelectAppsFragment.java
Normal file
198
src/org/fdroid/fdroid/views/swap/SelectAppsFragment.java
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
package org.fdroid.fdroid.views.swap;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
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.text.TextUtils;
|
||||||
|
import android.view.ActionMode;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.SearchView;
|
||||||
|
import android.widget.SimpleCursorAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||||
|
import org.fdroid.fdroid.localrepo.LocalRepoManager;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class SelectAppsFragment extends ListFragment
|
||||||
|
implements LoaderManager.LoaderCallbacks<Cursor>, SearchView.OnQueryTextListener {
|
||||||
|
|
||||||
|
private PackageManager packageManager;
|
||||||
|
private Drawable defaultAppIcon;
|
||||||
|
private ActionMode mActionMode = null;
|
||||||
|
private String mCurrentFilterString;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
LayoutInflater themedInflater = (LayoutInflater)new ContextThemeWrapper(inflater.getContext(), R.style.SwapTheme_AppList).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
|
||||||
|
View view = super.onCreateView(themedInflater, container, savedInstanceState);
|
||||||
|
ListView listView = (ListView)view.findViewById(android.R.id.list);
|
||||||
|
listView.addHeaderView(themedInflater.inflate(R.layout.swap_create_header, null, false));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
|
setEmptyText(getString(R.string.no_applications_found));
|
||||||
|
|
||||||
|
packageManager = getActivity().getPackageManager();
|
||||||
|
defaultAppIcon = getResources().getDrawable(android.R.drawable.sym_def_app_icon);
|
||||||
|
|
||||||
|
ListView listView = getListView();
|
||||||
|
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||||
|
SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(),
|
||||||
|
R.layout.select_local_apps_list_item,
|
||||||
|
null,
|
||||||
|
new String[] {
|
||||||
|
InstalledAppProvider.DataColumns.APPLICATION_LABEL,
|
||||||
|
InstalledAppProvider.DataColumns.APP_ID,
|
||||||
|
},
|
||||||
|
new int[] {
|
||||||
|
R.id.application_label,
|
||||||
|
R.id.package_name,
|
||||||
|
});
|
||||||
|
adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
|
||||||
|
if (columnIndex == cursor.getColumnIndex(InstalledAppProvider.DataColumns.APP_ID)) {
|
||||||
|
String packageName = cursor.getString(columnIndex);
|
||||||
|
TextView textView = (TextView) view.findViewById(R.id.package_name);
|
||||||
|
textView.setText(packageName);
|
||||||
|
LinearLayout ll = (LinearLayout) view.getParent().getParent();
|
||||||
|
ImageView iconView = (ImageView) ll.getChildAt(0);
|
||||||
|
Drawable icon;
|
||||||
|
try {
|
||||||
|
icon = packageManager.getApplicationIcon(packageName);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
icon = defaultAppIcon;
|
||||||
|
}
|
||||||
|
iconView.setImageDrawable(icon);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setListAdapter(adapter);
|
||||||
|
setListShown(false); // start out with a progress indicator
|
||||||
|
|
||||||
|
// either reconnect with an existing loader or start a new one
|
||||||
|
getLoaderManager().initLoader(0, null, this);
|
||||||
|
|
||||||
|
// build list of existing apps from what is on the file system
|
||||||
|
if (FDroidApp.selectedApps == null) {
|
||||||
|
FDroidApp.selectedApps = new HashSet<String>();
|
||||||
|
for (String filename : LocalRepoManager.get(getActivity()).repoDir.list()) {
|
||||||
|
if (filename.matches(".*\\.apk")) {
|
||||||
|
String packageName = filename.substring(0, filename.indexOf("_"));
|
||||||
|
FDroidApp.selectedApps.add(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
|
Cursor c = (Cursor) l.getAdapter().getItem(position);
|
||||||
|
String packageName = c.getString(c.getColumnIndex(InstalledAppProvider.DataColumns.APP_ID));
|
||||||
|
if (FDroidApp.selectedApps.contains(packageName)) {
|
||||||
|
FDroidApp.selectedApps.remove(packageName);
|
||||||
|
} else {
|
||||||
|
FDroidApp.selectedApps.add(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CursorLoader onCreateLoader(int id, Bundle args) {
|
||||||
|
Uri baseUri;
|
||||||
|
if (TextUtils.isEmpty(mCurrentFilterString)) {
|
||||||
|
baseUri = InstalledAppProvider.getContentUri();
|
||||||
|
} else {
|
||||||
|
baseUri = InstalledAppProvider.getSearchUri(mCurrentFilterString);
|
||||||
|
}
|
||||||
|
return new CursorLoader(
|
||||||
|
this.getActivity(),
|
||||||
|
baseUri,
|
||||||
|
InstalledAppProvider.DataColumns.ALL,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
InstalledAppProvider.DataColumns.APPLICATION_LABEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||||
|
((SimpleCursorAdapter) this.getListAdapter()).swapCursor(cursor);
|
||||||
|
|
||||||
|
ListView listView = getListView();
|
||||||
|
String fdroid = loader.getContext().getPackageName();
|
||||||
|
for (int i = 0; i < listView.getCount() - 1; i++) {
|
||||||
|
Cursor c = ((Cursor) listView.getItemAtPosition(i + 1));
|
||||||
|
String packageName = c.getString(c.getColumnIndex(InstalledAppProvider.DataColumns.APP_ID));
|
||||||
|
if (TextUtils.equals(packageName, fdroid)) {
|
||||||
|
listView.setItemChecked(i, true); // always include FDroid
|
||||||
|
} 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<Cursor> loader) {
|
||||||
|
((SimpleCursorAdapter) this.getListAdapter()).swapCursor(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onQueryTextChange(String newText) {
|
||||||
|
String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
|
||||||
|
if (mCurrentFilterString == null && newFilter == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mCurrentFilterString != null && mCurrentFilterString.equals(newFilter)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
mCurrentFilterString = newFilter;
|
||||||
|
getLoaderManager().restartLoader(0, null, this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onQueryTextSubmit(String query) {
|
||||||
|
// this is not needed since we respond to every change in text
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCurrentFilterString() {
|
||||||
|
return mCurrentFilterString;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
src/org/fdroid/fdroid/views/swap/StartSwapFragment.java
Normal file
38
src/org/fdroid/fdroid/views/swap/StartSwapFragment.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package org.fdroid.fdroid.views.swap;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
|
||||||
|
public class StartSwapFragment extends Fragment {
|
||||||
|
|
||||||
|
private SwapProcessManager manager;
|
||||||
|
|
||||||
|
public void onAttach(Activity activity) {
|
||||||
|
super.onAttach(activity);
|
||||||
|
manager = (SwapProcessManager)activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
LayoutInflater themedInflater = (LayoutInflater)new ContextThemeWrapper(inflater.getContext(), R.style.SwapTheme_AppList).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
|
||||||
|
View view = themedInflater.inflate(R.layout.swap_blank, container, false);
|
||||||
|
view.findViewById(R.id.button_start_swap).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
manager.nextStep();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,41 +6,32 @@ import android.support.v4.view.MenuItemCompat;
|
|||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.views.fragments.SelectLocalAppsFragment;
|
||||||
|
|
||||||
public class SwapActivity extends ActionBarActivity implements SwapProcessManager {
|
public class SwapActivity extends ActionBarActivity implements SwapProcessManager {
|
||||||
|
|
||||||
|
private static final String STATE_START_SWAP = "startSwap";
|
||||||
|
private static final String STATE_SELECT_APPS = "selectApps";
|
||||||
private static final String STATE_JOIN_WIFI = "joinWifi";
|
private static final String STATE_JOIN_WIFI = "joinWifi";
|
||||||
private static final String STATE_NFC = "nfc";
|
private static final String STATE_NFC = "nfc";
|
||||||
private static final String STATE_WIFI_QR = "wifiQr";
|
private static final String STATE_WIFI_QR = "wifiQr";
|
||||||
|
|
||||||
@Override
|
private MenuItem nextMenuItem;
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
private String nextMenuItemLabel;
|
||||||
getMenuInflater().inflate(R.menu.swap, menu);
|
|
||||||
MenuItem next = menu.getItem(0);
|
|
||||||
MenuItemCompat.setShowAsAction(next, MenuItemCompat.SHOW_AS_ACTION_ALWAYS | MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public void nextStep() {
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
||||||
return super.onPrepareOptionsMenu(menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == R.id.action_next) {
|
|
||||||
moveToNext();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void moveToNext() {
|
|
||||||
getSupportFragmentManager().popBackStack();
|
getSupportFragmentManager().popBackStack();
|
||||||
FragmentManager.BackStackEntry lastFragment = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1);
|
FragmentManager.BackStackEntry lastFragment = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1);
|
||||||
String name = lastFragment.getName();
|
String name = lastFragment.getName();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
|
case STATE_START_SWAP:
|
||||||
|
onSelectApps();
|
||||||
|
break;
|
||||||
|
case STATE_SELECT_APPS:
|
||||||
|
onJoinWifi();
|
||||||
|
break;
|
||||||
case STATE_JOIN_WIFI:
|
case STATE_JOIN_WIFI:
|
||||||
onAttemptNfc();
|
onAttemptNfc();
|
||||||
break;
|
break;
|
||||||
@ -51,6 +42,47 @@ public class SwapActivity extends ActionBarActivity implements SwapProcessManage
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
supportInvalidateOptionsMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
super.onCreateOptionsMenu(menu);
|
||||||
|
getMenuInflater().inflate(R.menu.swap_next, menu);
|
||||||
|
nextMenuItem = menu.getItem(0);
|
||||||
|
nextMenuItem.setVisible(false);
|
||||||
|
MenuItemCompat.setShowAsAction(nextMenuItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS | MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hideNextButton() {
|
||||||
|
nextMenuItemLabel = null;
|
||||||
|
supportInvalidateOptionsMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showNextButton() {
|
||||||
|
nextMenuItemLabel = getString(R.string.next);
|
||||||
|
supportInvalidateOptionsMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
|
if (nextMenuItemLabel == null) {
|
||||||
|
nextMenuItem.setVisible(false);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
nextMenuItem.setVisible(true);
|
||||||
|
nextMenuItem.setTitle(nextMenuItemLabel);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
if (item.getItemId() == nextMenuItem.getItemId()) {
|
||||||
|
nextStep();
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -62,35 +94,61 @@ public class SwapActivity extends ActionBarActivity implements SwapProcessManage
|
|||||||
|
|
||||||
getSupportFragmentManager()
|
getSupportFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.add(android.R.id.content, new JoinWifiFragment(), STATE_JOIN_WIFI)
|
.add(android.R.id.content, new StartSwapFragment(), STATE_START_SWAP)
|
||||||
.addToBackStack(STATE_JOIN_WIFI)
|
.addToBackStack(STATE_START_SWAP)
|
||||||
.commit();
|
.commit();
|
||||||
|
hideNextButton();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void onSelectApps() {
|
||||||
public void onAttemptNfc() {
|
|
||||||
getSupportFragmentManager()
|
getSupportFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.addToBackStack(STATE_NFC)
|
.add(android.R.id.content, new SelectAppsFragment(), STATE_SELECT_APPS)
|
||||||
.replace(android.R.id.content, new NfcSwapFragment(), STATE_NFC)
|
.addToBackStack(STATE_SELECT_APPS)
|
||||||
.commit();
|
.commit();
|
||||||
|
showNextButton();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onJoinWifi() {
|
||||||
|
|
||||||
|
getSupportFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
|
.add(android.R.id.content, new JoinWifiFragment(), STATE_JOIN_WIFI)
|
||||||
|
.addToBackStack(STATE_JOIN_WIFI)
|
||||||
|
.commit();
|
||||||
|
showNextButton();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAttemptNfc() {
|
||||||
|
if (Preferences.get().showNfcDuringSwap() && NfcSwapFragment.isNfcSupported(this)) {
|
||||||
|
getSupportFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
|
.addToBackStack(STATE_NFC)
|
||||||
|
.replace(android.R.id.content, new NfcSwapFragment(), STATE_NFC)
|
||||||
|
.commit();
|
||||||
|
showNextButton();
|
||||||
|
} else {
|
||||||
|
onWifiQr();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBluetooth() {
|
public void onBluetooth() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onWifiQr() {
|
public void onWifiQr() {
|
||||||
getSupportFragmentManager()
|
getSupportFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.addToBackStack(STATE_WIFI_QR)
|
.addToBackStack(STATE_WIFI_QR)
|
||||||
.replace(android.R.id.content, new WifiQrFragment(), STATE_WIFI_QR)
|
.replace(android.R.id.content, new WifiQrFragment(), STATE_WIFI_QR)
|
||||||
.commit();
|
.commit();
|
||||||
|
showNextButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package org.fdroid.fdroid.views.swap;
|
package org.fdroid.fdroid.views.swap;
|
||||||
|
|
||||||
public interface SwapProcessManager {
|
public interface SwapProcessManager {
|
||||||
public void onAttemptNfc();
|
public void nextStep();
|
||||||
public void onBluetooth();
|
|
||||||
public void onWifiQr();
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,73 @@
|
|||||||
package org.fdroid.fdroid.views.swap;
|
package org.fdroid.fdroid.views.swap;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.graphics.LightingColorFilter;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
|
import org.fdroid.fdroid.QrGenAsyncTask;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.Utils;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class WifiQrFragment extends Fragment {
|
public class WifiQrFragment extends Fragment {
|
||||||
|
|
||||||
@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.swap_nfc, container, false);
|
View view = inflater.inflate(R.layout.swap_wifi_qr, container, false);
|
||||||
|
ImageView qrImage = (ImageView)view.findViewById(R.id.wifi_qr_code);
|
||||||
|
|
||||||
|
// Replace all blacks with the background blue.
|
||||||
|
qrImage.setColorFilter(new LightingColorFilter(0xffffffff, getResources().getColor(R.color.swap_blue)));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
setUIFromWifi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(14)
|
||||||
|
private void setUIFromWifi() {
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(FDroidApp.repo.address))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// the fingerprint is not useful on the button label
|
||||||
|
String buttonLabel = FDroidApp.ipAddressString + ":" + FDroidApp.port;
|
||||||
|
TextView ipAddressView = (TextView) getView().findViewById(R.id.device_ip_address);
|
||||||
|
ipAddressView.setText(buttonLabel);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set URL to UPPER for compact QR Code, FDroid will translate it back.
|
||||||
|
* Remove the SSID from the query string since SSIDs are case-sensitive.
|
||||||
|
* Instead the receiver will have to rely on the BSSID to find the right
|
||||||
|
* wifi AP to join. Lots of QR Scanners are buggy and do not respect
|
||||||
|
* custom URI schemes, so we have to use http:// or https:// :-(
|
||||||
|
*/
|
||||||
|
final String qrUriString = Utils.getSharingUri(getActivity(), FDroidApp.repo).toString()
|
||||||
|
.replaceFirst("fdroidrepo", "http")
|
||||||
|
.replaceAll("ssid=[^?]*", "")
|
||||||
|
.toUpperCase(Locale.ENGLISH);
|
||||||
|
|
||||||
|
Log.i("QRURI", qrUriString);
|
||||||
|
|
||||||
|
// zxing requires >= 8
|
||||||
|
// TODO: What about 7? I don't feel comfortable bumping the min version for this...
|
||||||
|
// I would suggest show some alternate info, with directions for how to add a new repository manually.
|
||||||
|
if (Build.VERSION.SDK_INT >= 8)
|
||||||
|
new QrGenAsyncTask(getActivity(), R.id.wifi_qr_code).execute(qrUriString);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user