Merge branch 'swap_ux_improvements' of https://gitlab.com/eighthave/fdroidclient
This commit is contained in:
commit
295ef8f02a
@ -4,6 +4,7 @@
|
|||||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" path="extern/nanohttpd/core/src/main/java"/>
|
||||||
<classpathentry kind="src" path="gen"/>
|
<classpathentry kind="src" path="gen"/>
|
||||||
<classpathentry combineaccessrules="false" kind="src" path="/AndroidPinning"/>
|
<classpathentry combineaccessrules="false" kind="src" path="/AndroidPinning"/>
|
||||||
<classpathentry combineaccessrules="false" kind="src" path="/MemorizingActivity"/>
|
<classpathentry combineaccessrules="false" kind="src" path="/MemorizingActivity"/>
|
||||||
|
@ -4,23 +4,50 @@
|
|||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:orientation="vertical" >
|
android:orientation="vertical" >
|
||||||
|
|
||||||
<ToggleButton
|
<Button
|
||||||
|
android:id="@+id/enable_wifi"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/enable_wifi" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
android:id="@+id/repoSwitch"
|
android:id="@+id/repoSwitch"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="15dp"
|
||||||
|
android:text="@string/touch_to_turn_on_local_repo" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="@string/sharing_uri" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sharing_uri"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginLeft="15dp"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:typeface="monospace" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" >
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/wifiNetwork"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:text="@string/wifi_network" />
|
android:text="@string/wifi_network" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/wifiNetworkName"
|
android:id="@+id/wifi_network"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginLeft="15dp"
|
android:layout_marginLeft="15dp"
|
||||||
|
56
res/layout/select_local_apps_list_item.xml
Normal file
56
res/layout/select_local_apps_list_item.xml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?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"
|
||||||
|
tools:ignore="NewApi" >
|
||||||
|
|
||||||
|
<!-- TODO remove NewApi ignore when appcompat-v7 is in place -->
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="48dip"
|
||||||
|
android:layout_height="48dip"
|
||||||
|
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_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
|
android:layout_marginTop="6dip"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceListItem" />
|
||||||
|
|
||||||
|
<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>
|
@ -1,9 +1,14 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_search"
|
||||||
|
android:icon="@android:drawable/ic_menu_search"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:title="@string/menu_search"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_update_repo"
|
android:id="@+id/action_update_repo"
|
||||||
android:icon="@android:drawable/ic_input_add"
|
android:icon="@android:drawable/ic_input_add"
|
||||||
android:showAsAction="ifRoom|withText"
|
android:showAsAction="always|withText"
|
||||||
android:title="@string/update_repo"/>
|
android:title="@string/update_repo"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
@ -1,10 +1,15 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_search"
|
||||||
|
android:actionViewClass="android.widget.SearchView"
|
||||||
|
android:icon="@android:drawable/ic_menu_search"
|
||||||
|
android:showAsAction="collapseActionView|ifRoom"
|
||||||
|
android:title="@string/menu_search"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_settings"
|
android:id="@+id/action_settings"
|
||||||
android:orderInCategory="100"
|
|
||||||
android:showAsAction="never"
|
|
||||||
android:icon="@android:drawable/ic_menu_preferences"
|
android:icon="@android:drawable/ic_menu_preferences"
|
||||||
|
android:showAsAction="never"
|
||||||
android:title="@string/menu_preferences"/>
|
android:title="@string/menu_preferences"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
@ -156,6 +156,8 @@
|
|||||||
<string name="local_repo_running">Your local FDroid repo is accessible.</string>
|
<string name="local_repo_running">Your local FDroid repo is accessible.</string>
|
||||||
<string name="setup_repo">Setup Local Repo</string>
|
<string name="setup_repo">Setup Local Repo</string>
|
||||||
<string name="touch_to_configure_local_repo">Touch to setup your local repo.</string>
|
<string name="touch_to_configure_local_repo">Touch to setup your local repo.</string>
|
||||||
|
<string name="touch_to_turn_on_local_repo">Touch to turn on your local repo.</string>
|
||||||
|
<string name="touch_to_turn_off_local_repo">Touch to turn off your local repo.</string>
|
||||||
<string name="updating">Updating…</string>
|
<string name="updating">Updating…</string>
|
||||||
<string name="update_repo">Update Repo</string>
|
<string name="update_repo">Update Repo</string>
|
||||||
<string name="deleting_repo">Deleting current repo…</string>
|
<string name="deleting_repo">Deleting current repo…</string>
|
||||||
@ -168,6 +170,7 @@
|
|||||||
<string name="icon">icon</string>
|
<string name="icon">icon</string>
|
||||||
<string name="fingerprint">Fingerprint:</string>
|
<string name="fingerprint">Fingerprint:</string>
|
||||||
<string name="wifi_network">WiFi Network:</string>
|
<string name="wifi_network">WiFi Network:</string>
|
||||||
|
<string name="sharing_uri">Sharing URL:</string>
|
||||||
<string name="enable_wifi">Enable WiFi</string>
|
<string name="enable_wifi">Enable WiFi</string>
|
||||||
<string name="enabling_wifi">Enabling WiFi…</string>
|
<string name="enabling_wifi">Enabling WiFi…</string>
|
||||||
<string name="same_wifi_instructions">To connect to other people\'s devices, make sure both devices are on the same WiFi network. Then either type the URL above into F-Droid, or scan this QR Code:</string>
|
<string name="same_wifi_instructions">To connect to other people\'s devices, make sure both devices are on the same WiFi network. Then either type the URL above into F-Droid, or scan this QR Code:</string>
|
||||||
|
@ -122,7 +122,7 @@ public class FDroidApp extends Application {
|
|||||||
// it is more deterministic as to when this gets called...
|
// it is more deterministic as to when this gets called...
|
||||||
Preferences.setup(this);
|
Preferences.setup(this);
|
||||||
|
|
||||||
//Apply the Google PRNG fixes to properly seed SecureRandom
|
// Apply the Google PRNG fixes to properly seed SecureRandom
|
||||||
PRNGFixes.apply();
|
PRNGFixes.apply();
|
||||||
|
|
||||||
localRepo = new LocalRepoManager(getApplicationContext());
|
localRepo = new LocalRepoManager(getApplicationContext());
|
||||||
@ -301,14 +301,17 @@ public class FDroidApp extends Application {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static void startLocalRepoService(Context context) {
|
public static void startLocalRepoService(Context context) {
|
||||||
context.bindService(new Intent(context, LocalRepoService.class),
|
if (!localRepoServiceIsBound) {
|
||||||
serviceConnection, Context.BIND_AUTO_CREATE);
|
Context app = context.getApplicationContext();
|
||||||
localRepoServiceIsBound = true;
|
app.bindService(new Intent(app, LocalRepoService.class),
|
||||||
|
serviceConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
localRepoServiceIsBound = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void stopLocalRepoService(Context context) {
|
public static void stopLocalRepoService(Context context) {
|
||||||
if (localRepoServiceIsBound) {
|
if (localRepoServiceIsBound) {
|
||||||
context.unbindService(serviceConnection);
|
context.getApplicationContext().unbindService(serviceConnection);
|
||||||
localRepoServiceIsBound = false;
|
localRepoServiceIsBound = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,10 @@ package org.fdroid.fdroid;
|
|||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import org.fdroid.fdroid.data.InstalledAppProvider;
|
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||||
@ -44,10 +47,12 @@ public class PackageAddedReceiver extends PackageReceiver {
|
|||||||
Log.d("FDroid", "Inserting installed app info for '" + appId + "' (v" + info.versionCode + ")");
|
Log.d("FDroid", "Inserting installed app info for '" + appId + "' (v" + info.versionCode + ")");
|
||||||
|
|
||||||
Uri uri = InstalledAppProvider.getContentUri();
|
Uri uri = InstalledAppProvider.getContentUri();
|
||||||
ContentValues values = new ContentValues(3);
|
ContentValues values = new ContentValues(4);
|
||||||
values.put(InstalledAppProvider.DataColumns.APP_ID, appId);
|
values.put(InstalledAppProvider.DataColumns.APP_ID, appId);
|
||||||
values.put(InstalledAppProvider.DataColumns.VERSION_CODE, info.versionCode);
|
values.put(InstalledAppProvider.DataColumns.VERSION_CODE, info.versionCode);
|
||||||
values.put(InstalledAppProvider.DataColumns.VERSION_NAME, info.versionName);
|
values.put(InstalledAppProvider.DataColumns.VERSION_NAME, info.versionName);
|
||||||
|
values.put(InstalledAppProvider.DataColumns.APPLICATION_LABEL,
|
||||||
|
InstalledAppProvider.getApplicationLabel(context, appId));
|
||||||
context.getContentResolver().insert(uri, values);
|
context.getContentResolver().insert(uri, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,13 @@ package org.fdroid.fdroid;
|
|||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.data.InstalledAppProvider;
|
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,10 +50,12 @@ public class PackageUpgradedReceiver extends PackageReceiver {
|
|||||||
Log.d("FDroid", "Updating installed app info for '" + appId + "' to v" + info.versionCode + " (" + info.versionName + ")");
|
Log.d("FDroid", "Updating installed app info for '" + appId + "' to v" + info.versionCode + " (" + info.versionName + ")");
|
||||||
|
|
||||||
Uri uri = InstalledAppProvider.getContentUri();
|
Uri uri = InstalledAppProvider.getContentUri();
|
||||||
ContentValues values = new ContentValues(1);
|
ContentValues values = new ContentValues(4);
|
||||||
values.put(InstalledAppProvider.DataColumns.APP_ID, info.packageName);
|
values.put(InstalledAppProvider.DataColumns.APP_ID, appId);
|
||||||
values.put(InstalledAppProvider.DataColumns.VERSION_CODE, info.versionCode);
|
values.put(InstalledAppProvider.DataColumns.VERSION_CODE, info.versionCode);
|
||||||
values.put(InstalledAppProvider.DataColumns.VERSION_NAME, info.versionName);
|
values.put(InstalledAppProvider.DataColumns.VERSION_NAME, info.versionName);
|
||||||
|
values.put(InstalledAppProvider.DataColumns.APPLICATION_LABEL,
|
||||||
|
InstalledAppProvider.getApplicationLabel(context, appId));
|
||||||
context.getContentResolver().insert(uri, values);
|
context.getContentResolver().insert(uri, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ import com.google.zxing.WriterException;
|
|||||||
import com.google.zxing.encode.Contents;
|
import com.google.zxing.encode.Contents;
|
||||||
import com.google.zxing.encode.QRCodeEncoder;
|
import com.google.zxing.encode.QRCodeEncoder;
|
||||||
|
|
||||||
|
// zxing is android-8 and above
|
||||||
|
@TargetApi(8)
|
||||||
public class QrGenAsyncTask extends AsyncTask<String, Void, Void> {
|
public class QrGenAsyncTask extends AsyncTask<String, Void, Void> {
|
||||||
private static final String TAG = "QrGenAsyncTask";
|
private static final String TAG = "QrGenAsyncTask";
|
||||||
|
|
||||||
|
@ -91,12 +91,13 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||||||
public static final String TABLE_INSTALLED_APP = "fdroid_installedApp";
|
public static final String TABLE_INSTALLED_APP = "fdroid_installedApp";
|
||||||
private static final String CREATE_TABLE_INSTALLED_APP = "CREATE TABLE " + TABLE_INSTALLED_APP
|
private static final String CREATE_TABLE_INSTALLED_APP = "CREATE TABLE " + TABLE_INSTALLED_APP
|
||||||
+ " ( "
|
+ " ( "
|
||||||
+ "appId TEXT NOT NULL PRIMARY KEY, "
|
+ InstalledAppProvider.DataColumns.APP_ID + " TEXT NOT NULL PRIMARY KEY, "
|
||||||
+ "versionCode INT NOT NULL, "
|
+ InstalledAppProvider.DataColumns.VERSION_CODE + " INT NOT NULL, "
|
||||||
+ "versionName TEXT NOT NULL "
|
+ InstalledAppProvider.DataColumns.VERSION_NAME + " TEXT NOT NULL, "
|
||||||
|
+ InstalledAppProvider.DataColumns.APPLICATION_LABEL + " TEXT NOT NULL "
|
||||||
+ " );";
|
+ " );";
|
||||||
|
|
||||||
private static final int DB_VERSION = 44;
|
private static final int DB_VERSION = 46;
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
@ -249,11 +250,11 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||||||
addLastUpdatedToRepo(db, oldVersion);
|
addLastUpdatedToRepo(db, oldVersion);
|
||||||
renameRepoId(db, oldVersion);
|
renameRepoId(db, oldVersion);
|
||||||
populateRepoNames(db, oldVersion);
|
populateRepoNames(db, oldVersion);
|
||||||
|
|
||||||
if (oldVersion < 43) createInstalledApp(db);
|
if (oldVersion < 43) createInstalledApp(db);
|
||||||
|
addAppLabelToInstalledCache(db, oldVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate repo list to new structure. (No way to change primary
|
* Migrate repo list to new structure. (No way to change primary
|
||||||
* key in sqlite - table must be recreated).
|
* key in sqlite - table must be recreated).
|
||||||
*/
|
*/
|
||||||
@ -398,6 +399,17 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||||||
db.execSQL(CREATE_TABLE_INSTALLED_APP);
|
db.execSQL(CREATE_TABLE_INSTALLED_APP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addAppLabelToInstalledCache(SQLiteDatabase db, int oldVersion) {
|
||||||
|
if (oldVersion < 45) {
|
||||||
|
Log.i(TAG, "Adding applicationLabel to installed app table. " +
|
||||||
|
"Turns out we will need to repopulate the cache after doing this, " +
|
||||||
|
"so just dropping and recreating the table (instead of altering and adding a column). " +
|
||||||
|
"This will force the entire cache to be rebuilt, including app names.");
|
||||||
|
db.execSQL("DROP TABLE fdroid_installedApp;");
|
||||||
|
createInstalledApp(db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean columnExists(SQLiteDatabase db,
|
private static boolean columnExists(SQLiteDatabase db,
|
||||||
String table, String column) {
|
String table, String column) {
|
||||||
return (db.rawQuery( "select * from " + table + " limit 0,1", null )
|
return (db.rawQuery( "select * from " + table + " limit 0,1", null )
|
||||||
|
@ -135,6 +135,8 @@ public class InstalledAppCacheUpdater {
|
|||||||
.withValue(InstalledAppProvider.DataColumns.APP_ID, info.packageName)
|
.withValue(InstalledAppProvider.DataColumns.APP_ID, info.packageName)
|
||||||
.withValue(InstalledAppProvider.DataColumns.VERSION_CODE, info.versionCode)
|
.withValue(InstalledAppProvider.DataColumns.VERSION_CODE, info.versionCode)
|
||||||
.withValue(InstalledAppProvider.DataColumns.VERSION_NAME, info.versionName)
|
.withValue(InstalledAppProvider.DataColumns.VERSION_NAME, info.versionName)
|
||||||
|
.withValue(InstalledAppProvider.DataColumns.APPLICATION_LABEL,
|
||||||
|
InstalledAppProvider.getApplicationLabel(context, info.packageName))
|
||||||
.build();
|
.build();
|
||||||
ops.add(op);
|
ops.add(op);
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,14 @@ package org.fdroid.fdroid.data;
|
|||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.UriMatcher;
|
import android.content.UriMatcher;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.content.res.Resources.NotFoundException;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -49,17 +54,24 @@ public class InstalledAppProvider extends FDroidProvider {
|
|||||||
public static final String APP_ID = "appId";
|
public static final String APP_ID = "appId";
|
||||||
public static final String VERSION_CODE = "versionCode";
|
public static final String VERSION_CODE = "versionCode";
|
||||||
public static final String VERSION_NAME = "versionName";
|
public static final String VERSION_NAME = "versionName";
|
||||||
|
public static final String APPLICATION_LABEL = "applicationLabel";
|
||||||
|
|
||||||
public static String[] ALL = { _ID, APP_ID, VERSION_CODE, VERSION_NAME };
|
public static String[] ALL = {
|
||||||
|
_ID, APP_ID, VERSION_CODE, VERSION_NAME, APPLICATION_LABEL,
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String PROVIDER_NAME = "InstalledAppProvider";
|
private static final String PROVIDER_NAME = "InstalledAppProvider";
|
||||||
|
|
||||||
|
private static final String PATH_SEARCH = "search";
|
||||||
|
private static final int CODE_SEARCH = CODE_SINGLE + 1;
|
||||||
|
|
||||||
private static final UriMatcher matcher = new UriMatcher(-1);
|
private static final UriMatcher matcher = new UriMatcher(-1);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
matcher.addURI(getAuthority(), null, CODE_LIST);
|
matcher.addURI(getAuthority(), null, CODE_LIST);
|
||||||
|
matcher.addURI(getAuthority(), PATH_SEARCH + "/*", CODE_SEARCH);
|
||||||
matcher.addURI(getAuthority(), "*", CODE_SINGLE);
|
matcher.addURI(getAuthority(), "*", CODE_SINGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +83,27 @@ public class InstalledAppProvider extends FDroidProvider {
|
|||||||
return Uri.withAppendedPath(getContentUri(), appId);
|
return Uri.withAppendedPath(getContentUri(), appId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Uri getSearchUri(String keywords) {
|
||||||
|
return getContentUri().buildUpon()
|
||||||
|
.appendPath(PATH_SEARCH)
|
||||||
|
.appendPath(keywords)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getApplicationLabel(Context context, String packageName) {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
ApplicationInfo appInfo;
|
||||||
|
try {
|
||||||
|
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
|
||||||
|
return appInfo.loadLabel(pm).toString();
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NotFoundException e) {
|
||||||
|
Log.d("InstalledAppProvider", "getApplicationLabel: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return packageName; // all else fails, return id
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTableName() {
|
protected String getTableName() {
|
||||||
return DBHelper.TABLE_INSTALLED_APP;
|
return DBHelper.TABLE_INSTALLED_APP;
|
||||||
@ -94,8 +127,16 @@ public class InstalledAppProvider extends FDroidProvider {
|
|||||||
return new QuerySelection("appId = ?", new String[] { appId } );
|
return new QuerySelection("appId = ?", new String[] { appId } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private QuerySelection querySearch(String keywords) {
|
||||||
|
return new QuerySelection("applicationLabel LIKE ?", new String[] { "%" + keywords + "%" } );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cursor query(Uri uri, String[] projection, String customSelection, String[] selectionArgs, String sortOrder) {
|
public Cursor query(Uri uri, String[] projection, String customSelection, String[] selectionArgs, String sortOrder) {
|
||||||
|
if (sortOrder == null) {
|
||||||
|
sortOrder = DataColumns.APPLICATION_LABEL;
|
||||||
|
}
|
||||||
|
|
||||||
QuerySelection selection = new QuerySelection(customSelection, selectionArgs);
|
QuerySelection selection = new QuerySelection(customSelection, selectionArgs);
|
||||||
switch (matcher.match(uri)) {
|
switch (matcher.match(uri)) {
|
||||||
case CODE_LIST:
|
case CODE_LIST:
|
||||||
@ -105,13 +146,17 @@ public class InstalledAppProvider extends FDroidProvider {
|
|||||||
selection = selection.add(queryApp(uri.getLastPathSegment()));
|
selection = selection.add(queryApp(uri.getLastPathSegment()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CODE_SEARCH:
|
||||||
|
selection = selection.add(querySearch(uri.getLastPathSegment()));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
String message = "Invalid URI for installed app content provider: " + uri;
|
String message = "Invalid URI for installed app content provider: " + uri;
|
||||||
Log.e("FDroid", message);
|
Log.e("FDroid", message);
|
||||||
throw new UnsupportedOperationException(message);
|
throw new UnsupportedOperationException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cursor cursor = read().query(getTableName(), projection, selection.getSelection(), selection.getArgs(), null, null, null);
|
Cursor cursor = read().query(getTableName(), projection, selection.getSelection(), selection.getArgs(), null, null, sortOrder);
|
||||||
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,10 @@ import java.util.Random;
|
|||||||
public class LocalRepoService extends Service {
|
public class LocalRepoService extends Service {
|
||||||
private static final String TAG = "LocalRepoService";
|
private static final String TAG = "LocalRepoService";
|
||||||
|
|
||||||
|
public static final String STATE = "org.fdroid.fdroid.action.LOCAL_REPO_STATE";
|
||||||
|
public static final String STARTED = "org.fdroid.fdroid.category.LOCAL_REPO_STARTED";
|
||||||
|
public static final String STOPPED = "org.fdroid.fdroid.category.LOCAL_REPO_STOPPED";
|
||||||
|
|
||||||
private NotificationManager notificationManager;
|
private NotificationManager notificationManager;
|
||||||
// Unique Identification Number for the Notification.
|
// Unique Identification Number for the Notification.
|
||||||
// We use it on Notification start, and to cancel it.
|
// We use it on Notification start, and to cancel it.
|
||||||
@ -148,6 +152,9 @@ public class LocalRepoService extends Service {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
new Thread(webServer).start();
|
new Thread(webServer).start();
|
||||||
|
Intent intent = new Intent(STATE);
|
||||||
|
intent.putExtra(STATE, STARTED);
|
||||||
|
LocalBroadcastManager.getInstance(LocalRepoService.this).sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopWebServer() {
|
private void stopWebServer() {
|
||||||
@ -158,5 +165,8 @@ public class LocalRepoService extends Service {
|
|||||||
Message msg = webServerThreadHandler.obtainMessage();
|
Message msg = webServerThreadHandler.obtainMessage();
|
||||||
msg.obj = webServerThreadHandler.getLooper().getThread().getName() + " says stop";
|
msg.obj = webServerThreadHandler.getLooper().getThread().getName() + " says stop";
|
||||||
webServerThreadHandler.sendMessage(msg);
|
webServerThreadHandler.sendMessage(msg);
|
||||||
|
Intent intent = new Intent(STATE);
|
||||||
|
intent.putExtra(STATE, STOPPED);
|
||||||
|
LocalBroadcastManager.getInstance(LocalRepoService.this).sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,21 +19,25 @@ import android.support.v4.content.LocalBroadcastManager;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.widget.TextView;
|
import android.widget.*;
|
||||||
import android.widget.Toast;
|
|
||||||
import android.widget.ToggleButton;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.*;
|
import org.fdroid.fdroid.*;
|
||||||
|
import org.fdroid.fdroid.localrepo.LocalRepoService;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
public class LocalRepoActivity extends Activity {
|
public class LocalRepoActivity extends Activity {
|
||||||
private static final String TAG = "LocalRepoActivity";
|
private static final String TAG = "LocalRepoActivity";
|
||||||
private ProgressDialog repoProgress;
|
private ProgressDialog repoProgress;
|
||||||
|
|
||||||
private WifiManager wifiManager;
|
private WifiManager wifiManager;
|
||||||
private ToggleButton repoSwitch;
|
private Button enableWifiButton;
|
||||||
|
private CheckBox repoSwitch;
|
||||||
|
|
||||||
|
private Timer stopTimer;
|
||||||
|
|
||||||
private int SET_IP_ADDRESS = 7345;
|
private int SET_IP_ADDRESS = 7345;
|
||||||
private int UPDATE_REPO = 7346;
|
private int UPDATE_REPO = 7346;
|
||||||
@ -42,9 +46,11 @@ public class LocalRepoActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
setContentView(R.layout.local_repo_activity);
|
setContentView(R.layout.local_repo_activity);
|
||||||
|
|
||||||
repoSwitch = (ToggleButton) findViewById(R.id.repoSwitch);
|
enableWifiButton = (Button) findViewById(R.id.enable_wifi);
|
||||||
|
repoSwitch = (CheckBox) findViewById(R.id.repoSwitch);
|
||||||
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,19 +58,35 @@ public class LocalRepoActivity extends Activity {
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
resetNetworkInfo();
|
resetNetworkInfo();
|
||||||
|
|
||||||
LocalBroadcastManager.getInstance(this).registerReceiver(onWifiChange,
|
LocalBroadcastManager.getInstance(this).registerReceiver(onWifiChange,
|
||||||
new IntentFilter(WifiStateChangeService.BROADCAST));
|
new IntentFilter(WifiStateChangeService.BROADCAST));
|
||||||
|
LocalBroadcastManager.getInstance(this).registerReceiver(onLocalRepoChange,
|
||||||
|
new IntentFilter(LocalRepoService.STATE));
|
||||||
// if no local repo exists, create one with only FDroid in it
|
// if no local repo exists, create one with only FDroid in it
|
||||||
if (!FDroidApp.localRepo.xmlIndex.exists())
|
if (!FDroidApp.localRepo.xmlIndex.exists())
|
||||||
new UpdateAsyncTask(this, new String[] {
|
new UpdateAsyncTask(this, new String[] {
|
||||||
getPackageName(),
|
getPackageName(),
|
||||||
}).execute();
|
}).execute();
|
||||||
|
|
||||||
|
// start repo by default
|
||||||
|
FDroidApp.startLocalRepoService(LocalRepoActivity.this);
|
||||||
|
// automatically turn off after 15 minutes
|
||||||
|
stopTimer = new Timer();
|
||||||
|
stopTimer.schedule(new TimerTask() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
FDroidApp.stopLocalRepoService(LocalRepoActivity.this);
|
||||||
|
}
|
||||||
|
}, 900000); // 15 minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(onWifiChange);
|
LocalBroadcastManager.getInstance(this).unregisterReceiver(onWifiChange);
|
||||||
|
LocalBroadcastManager.getInstance(this).unregisterReceiver(onLocalRepoChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BroadcastReceiver onWifiChange = new BroadcastReceiver() {
|
private BroadcastReceiver onWifiChange = new BroadcastReceiver() {
|
||||||
@ -74,19 +96,33 @@ public class LocalRepoActivity extends Activity {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private BroadcastReceiver onLocalRepoChange = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent i) {
|
||||||
|
String state = i.getStringExtra(LocalRepoService.STATE);
|
||||||
|
if (state != null && state.equals(LocalRepoService.STARTED))
|
||||||
|
setRepoSwitchChecked(true);
|
||||||
|
else
|
||||||
|
setRepoSwitchChecked(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private void resetNetworkInfo() {
|
private void resetNetworkInfo() {
|
||||||
int wifiState = wifiManager.getWifiState();
|
int wifiState = wifiManager.getWifiState();
|
||||||
if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
|
if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
|
||||||
setUIFromWifi();
|
setUIFromWifi();
|
||||||
wireRepoSwitchToWebServer();
|
wireRepoSwitchToWebServer();
|
||||||
|
repoSwitch.setVisibility(View.VISIBLE);
|
||||||
|
enableWifiButton.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
repoSwitch.setChecked(false);
|
repoSwitch.setChecked(false);
|
||||||
repoSwitch.setText(R.string.enable_wifi);
|
repoSwitch.setVisibility(View.GONE);
|
||||||
repoSwitch.setTextOn(getString(R.string.enabling_wifi));
|
enableWifiButton.setVisibility(View.VISIBLE);
|
||||||
repoSwitch.setTextOff(getString(R.string.enable_wifi));
|
enableWifiButton.setText(R.string.enable_wifi);
|
||||||
repoSwitch.setOnClickListener(new View.OnClickListener() {
|
enableWifiButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
enableWifiButton.setText(R.string.enabling_wifi);
|
||||||
wifiManager.setWifiEnabled(true);
|
wifiManager.setWifiEnabled(true);
|
||||||
/*
|
/*
|
||||||
* Once the wifi is connected to a network, then
|
* Once the wifi is connected to a network, then
|
||||||
@ -158,24 +194,34 @@ public class LocalRepoActivity extends Activity {
|
|||||||
repoSwitch.setOnClickListener(new View.OnClickListener() {
|
repoSwitch.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
setRepoSwitchChecked(repoSwitch.isChecked());
|
||||||
if (repoSwitch.isChecked()) {
|
if (repoSwitch.isChecked()) {
|
||||||
FDroidApp.startLocalRepoService(LocalRepoActivity.this);
|
FDroidApp.startLocalRepoService(LocalRepoActivity.this);
|
||||||
} else {
|
} else {
|
||||||
FDroidApp.stopLocalRepoService(LocalRepoActivity.this);
|
FDroidApp.stopLocalRepoService(LocalRepoActivity.this);
|
||||||
|
stopTimer.cancel(); // disable automatic stop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setRepoSwitchChecked(boolean checked) {
|
||||||
|
repoSwitch.setChecked(checked);
|
||||||
|
if (checked) {
|
||||||
|
repoSwitch.setText(R.string.local_repo_running);
|
||||||
|
} else {
|
||||||
|
repoSwitch.setText(R.string.touch_to_turn_on_local_repo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TargetApi(14)
|
@TargetApi(14)
|
||||||
private void setUIFromWifi() {
|
private void setUIFromWifi() {
|
||||||
if (TextUtils.isEmpty(FDroidApp.repo.address))
|
if (TextUtils.isEmpty(FDroidApp.repo.address))
|
||||||
return;
|
return;
|
||||||
// the fingerprint is not useful on the button label
|
// the fingerprint is not useful on the button label
|
||||||
String buttonLabel = FDroidApp.repo.address.replaceAll("\\?.*$", "");
|
String buttonLabel = FDroidApp.repo.address.replaceAll("\\?.*$", "");
|
||||||
repoSwitch.setText(buttonLabel);
|
TextView sharingUriTextView = (TextView) findViewById(R.id.sharing_uri);
|
||||||
repoSwitch.setTextOn(buttonLabel);
|
sharingUriTextView.setText(buttonLabel);
|
||||||
repoSwitch.setTextOff(buttonLabel);
|
|
||||||
/*
|
/*
|
||||||
* Set URL to UPPER for compact QR Code, FDroid will translate it back.
|
* 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.
|
* Remove the SSID from the query string since SSIDs are case-sensitive.
|
||||||
@ -188,9 +234,10 @@ public class LocalRepoActivity extends Activity {
|
|||||||
.replaceAll("ssid=[^?]*", "")
|
.replaceAll("ssid=[^?]*", "")
|
||||||
.toUpperCase(Locale.ENGLISH);
|
.toUpperCase(Locale.ENGLISH);
|
||||||
Log.i("QRURI", qrUriString);
|
Log.i("QRURI", qrUriString);
|
||||||
new QrGenAsyncTask(this, R.id.repoQrCode).execute(qrUriString);
|
if (Build.VERSION.SDK_INT >= 8) // zxing requires >= 8
|
||||||
|
new QrGenAsyncTask(this, R.id.repoQrCode).execute(qrUriString);
|
||||||
|
|
||||||
TextView wifiNetworkNameTextView = (TextView) findViewById(R.id.wifiNetworkName);
|
TextView wifiNetworkNameTextView = (TextView) findViewById(R.id.wifi_network);
|
||||||
wifiNetworkNameTextView.setText(FDroidApp.ssid);
|
wifiNetworkNameTextView.setText(FDroidApp.ssid);
|
||||||
|
|
||||||
TextView fingerprintTextView = (TextView) findViewById(R.id.fingerprint);
|
TextView fingerprintTextView = (TextView) findViewById(R.id.fingerprint);
|
||||||
|
@ -2,11 +2,8 @@
|
|||||||
package org.fdroid.fdroid.views;
|
package org.fdroid.fdroid.views;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.*;
|
||||||
import android.content.Context;
|
import android.os.Build;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
@ -27,6 +24,7 @@ public class QrWizardDownloadActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
setContentView(R.layout.qr_wizard_activity);
|
setContentView(R.layout.qr_wizard_activity);
|
||||||
TextView instructions = (TextView) findViewById(R.id.qrWizardInstructions);
|
TextView instructions = (TextView) findViewById(R.id.qrWizardInstructions);
|
||||||
instructions.setText(R.string.qr_wizard_download_instructions);
|
instructions.setText(R.string.qr_wizard_download_instructions);
|
||||||
@ -73,7 +71,8 @@ public class QrWizardDownloadActivity extends Activity {
|
|||||||
qrString += "://" + FDroidApp.ipAddressString;
|
qrString += "://" + FDroidApp.ipAddressString;
|
||||||
qrString += ":" + FDroidApp.port;
|
qrString += ":" + FDroidApp.port;
|
||||||
|
|
||||||
new QrGenAsyncTask(this, R.id.qrWizardImage).execute(qrString);
|
if (Build.VERSION.SDK_INT >= 8) // zxing requires >= 8
|
||||||
|
new QrGenAsyncTask(this, R.id.qrWizardImage).execute(qrString);
|
||||||
Log.i(TAG, "qr: " + qrString);
|
Log.i(TAG, "qr: " + qrString);
|
||||||
|
|
||||||
TextView wifiNetworkName = (TextView) findViewById(R.id.qrWifiNetworkName);
|
TextView wifiNetworkName = (TextView) findViewById(R.id.qrWifiNetworkName);
|
||||||
|
@ -2,12 +2,10 @@
|
|||||||
package org.fdroid.fdroid.views;
|
package org.fdroid.fdroid.views;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.*;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -33,6 +31,7 @@ public class QrWizardWifiNetworkActivity extends Activity {
|
|||||||
wifiManager.setWifiEnabled(true);
|
wifiManager.setWifiEnabled(true);
|
||||||
FDroidApp.startLocalRepoService(this);
|
FDroidApp.startLocalRepoService(this);
|
||||||
|
|
||||||
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
setContentView(R.layout.qr_wizard_activity);
|
setContentView(R.layout.qr_wizard_activity);
|
||||||
TextView instructions = (TextView) findViewById(R.id.qrWizardInstructions);
|
TextView instructions = (TextView) findViewById(R.id.qrWizardInstructions);
|
||||||
instructions.setText(R.string.qr_wizard_wifi_network_instructions);
|
instructions.setText(R.string.qr_wizard_wifi_network_instructions);
|
||||||
@ -92,12 +91,11 @@ public class QrWizardWifiNetworkActivity extends Activity {
|
|||||||
if (wifiInfo.getHiddenSSID())
|
if (wifiInfo.getHiddenSSID())
|
||||||
qrString += ";H:true";
|
qrString += ";H:true";
|
||||||
qrString += ";;";
|
qrString += ";;";
|
||||||
new QrGenAsyncTask(this, R.id.qrWizardImage).execute(qrString);
|
if (Build.VERSION.SDK_INT >= 8) // zxing requires >= 8
|
||||||
Log.i(TAG, "qr: " + qrString);
|
new QrGenAsyncTask(this, R.id.qrWizardImage).execute(qrString);
|
||||||
|
|
||||||
TextView wifiNetworkName = (TextView) findViewById(R.id.qrWifiNetworkName);
|
TextView wifiNetworkName = (TextView) findViewById(R.id.qrWifiNetworkName);
|
||||||
wifiNetworkName.setText(wifiInfo.getSSID());
|
wifiNetworkName.setText(wifiInfo.getSSID());
|
||||||
Log.i(TAG, "wifi network name: " + wifiInfo.getSSID());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,27 +2,28 @@
|
|||||||
package org.fdroid.fdroid.views;
|
package org.fdroid.fdroid.views;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.view.*;
|
||||||
import android.view.ActionMode;
|
import android.widget.SearchView;
|
||||||
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.PreferencesActivity;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.views.fragments.SelectLocalAppsFragment;
|
import org.fdroid.fdroid.views.fragments.SelectLocalAppsFragment;
|
||||||
|
|
||||||
@TargetApi(11)
|
@TargetApi(11)
|
||||||
// TODO replace with appcompat-v7
|
// TODO replace with appcompat-v7
|
||||||
public class SelectLocalAppsActivity extends FragmentActivity {
|
public class SelectLocalAppsActivity extends Activity {
|
||||||
private static final String TAG = "SelectLocalAppsActivity";
|
private static final String TAG = "SelectLocalAppsActivity";
|
||||||
private SelectLocalAppsFragment selectLocalAppsFragment = null;
|
private SelectLocalAppsFragment selectLocalAppsFragment = null;
|
||||||
|
private SearchView searchView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
setContentView(R.layout.select_local_apps_activity);
|
setContentView(R.layout.select_local_apps_activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,13 +31,15 @@ public class SelectLocalAppsActivity extends FragmentActivity {
|
|||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
if (selectLocalAppsFragment == null)
|
if (selectLocalAppsFragment == null)
|
||||||
selectLocalAppsFragment = (SelectLocalAppsFragment) getSupportFragmentManager().findFragmentById(
|
selectLocalAppsFragment = (SelectLocalAppsFragment) getFragmentManager()
|
||||||
R.id.fragment_app_list);
|
.findFragmentById(R.id.fragment_app_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.select_local_apps_activity, menu);
|
getMenuInflater().inflate(R.menu.select_local_apps_activity, menu);
|
||||||
|
searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
|
||||||
|
searchView.setOnQueryTextListener(selectLocalAppsFragment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +50,10 @@ public class SelectLocalAppsActivity extends FragmentActivity {
|
|||||||
setResult(RESULT_CANCELED);
|
setResult(RESULT_CANCELED);
|
||||||
finish();
|
finish();
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.action_search:
|
||||||
|
SearchView searchView = (SearchView) item.getActionView();
|
||||||
|
searchView.setIconified(false);
|
||||||
|
return true;
|
||||||
case R.id.action_settings:
|
case R.id.action_settings:
|
||||||
startActivity(new Intent(this, PreferencesActivity.class));
|
startActivity(new Intent(this, PreferencesActivity.class));
|
||||||
return true;
|
return true;
|
||||||
@ -60,6 +67,7 @@ public class SelectLocalAppsActivity extends FragmentActivity {
|
|||||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||||
MenuInflater inflater = mode.getMenuInflater();
|
MenuInflater inflater = mode.getMenuInflater();
|
||||||
inflater.inflate(R.menu.select_local_apps_action_mode, menu);
|
inflater.inflate(R.menu.select_local_apps_action_mode, menu);
|
||||||
|
menu.findItem(R.id.action_search).setActionView(searchView);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,17 +15,23 @@ limitations under the License.
|
|||||||
package org.fdroid.fdroid.views.fragments;
|
package org.fdroid.fdroid.views.fragments;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.ListFragment;
|
||||||
|
import android.app.LoaderManager.LoaderCallbacks;
|
||||||
|
import android.content.CursorLoader;
|
||||||
|
import android.content.Loader;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
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.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ListView;
|
import android.widget.*;
|
||||||
|
import android.widget.SearchView.OnQueryTextListener;
|
||||||
|
import android.widget.SimpleCursorAdapter.ViewBinder;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
@ -35,39 +41,72 @@ import org.fdroid.fdroid.views.SelectLocalAppsActivity;
|
|||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
public class SelectLocalAppsFragment extends ListFragment implements LoaderCallbacks<Cursor> {
|
//TODO replace with appcompat-v7
|
||||||
|
@TargetApi(11)
|
||||||
|
public class SelectLocalAppsFragment extends ListFragment
|
||||||
|
implements LoaderCallbacks<Cursor>, OnQueryTextListener {
|
||||||
|
|
||||||
|
private PackageManager packageManager;
|
||||||
|
private Drawable defaultAppIcon;
|
||||||
private SelectLocalAppsActivity selectLocalAppsActivity;
|
private SelectLocalAppsActivity selectLocalAppsActivity;
|
||||||
private ActionMode mActionMode = null;
|
private ActionMode mActionMode = null;
|
||||||
|
private String mCurrentFilterString;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(11)
|
|
||||||
// TODO replace with appcompat-v7
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
setEmptyText(getString(R.string.no_applications_found));
|
setEmptyText(getString(R.string.no_applications_found));
|
||||||
|
|
||||||
|
packageManager = getActivity().getPackageManager();
|
||||||
|
defaultAppIcon = getActivity().getResources()
|
||||||
|
.getDrawable(android.R.drawable.sym_def_app_icon);
|
||||||
|
|
||||||
selectLocalAppsActivity = (SelectLocalAppsActivity) getActivity();
|
selectLocalAppsActivity = (SelectLocalAppsActivity) getActivity();
|
||||||
ListView listView = getListView();
|
ListView listView = getListView();
|
||||||
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||||
SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(),
|
SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(),
|
||||||
android.R.layout.simple_list_item_activated_1,
|
R.layout.select_local_apps_list_item,
|
||||||
null,
|
null,
|
||||||
new String[] {
|
new String[] {
|
||||||
|
InstalledAppProvider.DataColumns.APPLICATION_LABEL,
|
||||||
InstalledAppProvider.DataColumns.APP_ID,
|
InstalledAppProvider.DataColumns.APP_ID,
|
||||||
},
|
},
|
||||||
new int[] {
|
new int[] {
|
||||||
android.R.id.text1,
|
R.id.application_label,
|
||||||
|
R.id.package_name,
|
||||||
},
|
},
|
||||||
0);
|
0);
|
||||||
|
adapter.setViewBinder(new ViewBinder() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
|
||||||
|
Log.i("SelectLocalAppsFragment", "ViewBinder " + 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 (NameNotFoundException e) {
|
||||||
|
icon = defaultAppIcon;
|
||||||
|
}
|
||||||
|
iconView.setImageDrawable(icon);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
setListAdapter(adapter);
|
setListAdapter(adapter);
|
||||||
setListShown(false);
|
setListShown(false); // start out with a progress indicator
|
||||||
|
|
||||||
// either reconnect with an existing loader or start a new one
|
// either reconnect with an existing loader or start a new one
|
||||||
getLoaderManager().initLoader(0, null, this);
|
getLoaderManager().initLoader(0, null, this);
|
||||||
@ -84,15 +123,13 @@ public class SelectLocalAppsFragment extends ListFragment implements LoaderCallb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(11)
|
|
||||||
// TODO replace with appcompat-v7
|
|
||||||
@Override
|
@Override
|
||||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
if (mActionMode == null)
|
if (mActionMode == null)
|
||||||
mActionMode = selectLocalAppsActivity
|
mActionMode = selectLocalAppsActivity
|
||||||
.startActionMode(selectLocalAppsActivity.mActionModeCallback);
|
.startActionMode(selectLocalAppsActivity.mActionModeCallback);
|
||||||
Cursor cursor = (Cursor) l.getAdapter().getItem(position);
|
Cursor c = (Cursor) l.getAdapter().getItem(position);
|
||||||
String packageName = cursor.getString(1);
|
String packageName = c.getString(c.getColumnIndex(DataColumns.APP_ID));
|
||||||
if (FDroidApp.selectedApps.contains(packageName)) {
|
if (FDroidApp.selectedApps.contains(packageName)) {
|
||||||
FDroidApp.selectedApps.remove(packageName);
|
FDroidApp.selectedApps.remove(packageName);
|
||||||
} else {
|
} else {
|
||||||
@ -102,13 +139,19 @@ public class SelectLocalAppsFragment extends ListFragment implements LoaderCallb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CursorLoader onCreateLoader(int id, Bundle args) {
|
public CursorLoader onCreateLoader(int id, Bundle args) {
|
||||||
|
Uri baseUri;
|
||||||
|
if (TextUtils.isEmpty(mCurrentFilterString)) {
|
||||||
|
baseUri = InstalledAppProvider.getContentUri();
|
||||||
|
} else {
|
||||||
|
baseUri = InstalledAppProvider.getSearchUri(mCurrentFilterString);
|
||||||
|
}
|
||||||
CursorLoader loader = new CursorLoader(
|
CursorLoader loader = new CursorLoader(
|
||||||
this.getActivity(),
|
this.getActivity(),
|
||||||
InstalledAppProvider.getContentUri(),
|
baseUri,
|
||||||
InstalledAppProvider.DataColumns.ALL,
|
InstalledAppProvider.DataColumns.ALL,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
InstalledAppProvider.DataColumns.APP_ID);
|
InstalledAppProvider.DataColumns.APPLICATION_LABEL);
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +166,7 @@ public class SelectLocalAppsFragment extends ListFragment implements LoaderCallb
|
|||||||
Cursor c = ((Cursor) listView.getItemAtPosition(i));
|
Cursor c = ((Cursor) listView.getItemAtPosition(i));
|
||||||
String packageName = c.getString(c.getColumnIndex(DataColumns.APP_ID));
|
String packageName = c.getString(c.getColumnIndex(DataColumns.APP_ID));
|
||||||
if (TextUtils.equals(packageName, fdroid)) {
|
if (TextUtils.equals(packageName, fdroid)) {
|
||||||
listView.setItemChecked(i, true);
|
listView.setItemChecked(i, true); // always include FDroid
|
||||||
} else {
|
} else {
|
||||||
for (String selected : FDroidApp.selectedApps) {
|
for (String selected : FDroidApp.selectedApps) {
|
||||||
if (TextUtils.equals(packageName, selected)) {
|
if (TextUtils.equals(packageName, selected)) {
|
||||||
@ -144,4 +187,28 @@ public class SelectLocalAppsFragment extends ListFragment implements LoaderCallb
|
|||||||
public void onLoaderReset(Loader<Cursor> loader) {
|
public void onLoaderReset(Loader<Cursor> loader) {
|
||||||
((SimpleCursorAdapter) this.getListAdapter()).swapCursor(null);
|
((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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,11 @@ import android.net.Uri;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.test.ProviderTestCase2MockContext;
|
import android.test.ProviderTestCase2MockContext;
|
||||||
|
|
||||||
import mock.MockContextEmptyComponents;
|
import mock.MockContextEmptyComponents;
|
||||||
import mock.MockContextSwappableComponents;
|
import mock.MockContextSwappableComponents;
|
||||||
import mock.MockFDroidResources;
|
import mock.MockFDroidResources;
|
||||||
|
|
||||||
import org.fdroid.fdroid.data.*;
|
import org.fdroid.fdroid.data.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -151,6 +153,7 @@ public abstract class FDroidProviderTest<T extends FDroidProvider> extends Provi
|
|||||||
InstalledAppProvider.DataColumns.APP_ID,
|
InstalledAppProvider.DataColumns.APP_ID,
|
||||||
InstalledAppProvider.DataColumns.VERSION_CODE,
|
InstalledAppProvider.DataColumns.VERSION_CODE,
|
||||||
InstalledAppProvider.DataColumns.VERSION_NAME,
|
InstalledAppProvider.DataColumns.VERSION_NAME,
|
||||||
|
InstalledAppProvider.DataColumns.APPLICATION_LABEL,
|
||||||
};
|
};
|
||||||
|
|
||||||
Cursor cursor = getMockContentResolver().query(uri, projection, null, null, null);
|
Cursor cursor = getMockContentResolver().query(uri, projection, null, null, null);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user