Merge branch 'appcompat-on-top-of-pserwylo' into 'master'
Appcompat on top of pserwylo This is a refactor of @pserwylo's !19 to get appcompat building with `ant` and Eclipse. I reviewed @pserwylo's commits and they are ready to go as they are in this merge request.
This commit is contained in:
commit
5af5306311
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -34,6 +34,10 @@
|
|||||||
path = extern/nanohttpd
|
path = extern/nanohttpd
|
||||||
url = https://github.com/eighthave/nanohttpd
|
url = https://github.com/eighthave/nanohttpd
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
|
[submodule "extern/android-support-v4-preferencefragment"]
|
||||||
|
path = extern/android-support-v4-preferencefragment
|
||||||
|
url = https://github.com/CyberEagle/android-support-v4-preferencefragment.git
|
||||||
|
ignore = dirty
|
||||||
[submodule "extern/zxing-core"]
|
[submodule "extern/zxing-core"]
|
||||||
path = extern/zxing-core
|
path = extern/zxing-core
|
||||||
url = https://gitlab.com/fdroid/zxing-core.git
|
url = https://gitlab.com/fdroid/zxing-core.git
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
android:versionName="0.69-test" >
|
android:versionName="0.69-test" >
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="5"
|
android:minSdkVersion="7"
|
||||||
android:targetSdkVersion="19" />
|
android:targetSdkVersion="19" />
|
||||||
|
|
||||||
<supports-screens
|
<supports-screens
|
||||||
@ -203,6 +203,9 @@
|
|||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:parentActivityName=".FDroid"
|
android:parentActivityName=".FDroid"
|
||||||
android:screenOrientation="portrait" >
|
android:screenOrientation="portrait" >
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".FDroid" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".views.SelectLocalAppsActivity"
|
android:name=".views.SelectLocalAppsActivity"
|
||||||
@ -216,7 +219,11 @@
|
|||||||
android:name=".views.RepoDetailsActivity"
|
android:name=".views.RepoDetailsActivity"
|
||||||
android:label="@string/menu_manage"
|
android:label="@string/menu_manage"
|
||||||
android:parentActivityName=".ManageRepo"
|
android:parentActivityName=".ManageRepo"
|
||||||
android:windowSoftInputMode="stateHidden" />
|
android:windowSoftInputMode="stateHidden">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".ManageRepo" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".AppDetails"
|
android:name=".AppDetails"
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
#!/bin/bash -ex
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
target=`sed -n 's,^target=\(.*\),\1,p' project.properties`
|
||||||
|
|
||||||
android update lib-project --path extern/UniversalImageLoader/library
|
android update lib-project --path extern/UniversalImageLoader/library
|
||||||
android update lib-project --path extern/AndroidPinning
|
android update lib-project --path extern/AndroidPinning
|
||||||
android update lib-project --path extern/MemorizingTrustManager
|
android update lib-project --path extern/MemorizingTrustManager
|
||||||
android update lib-project --path extern/libsuperuser/libsuperuser
|
android update lib-project --path extern/libsuperuser/libsuperuser
|
||||||
android update lib-project --path extern/zxing-core
|
android update lib-project --path extern/zxing-core
|
||||||
|
android update lib-project --path extern/android-support-v4-preferencefragment
|
||||||
|
android update lib-project --path extern/Support/v7/appcompat --target $target
|
||||||
android update project --path . --name F-Droid
|
android update project --path . --name F-Droid
|
||||||
|
|
||||||
{ echo -e "\nSuccessfully updated the main project.\n"; } 2>/dev/null
|
{ echo -e "\nSuccessfully updated the main project.\n"; } 2>/dev/null
|
||||||
|
32
build.gradle
32
build.gradle
@ -7,16 +7,18 @@ buildscript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def toolVersion = "19.1"
|
|
||||||
apply plugin: 'android'
|
apply plugin: 'android'
|
||||||
|
|
||||||
sdkLoc = System.getenv("ANDROID_HOME")
|
def toolVersion = "19.1"
|
||||||
|
sdkLoc = getSdkPath()
|
||||||
|
|
||||||
FileCollection getAndroidPrebuilt(String apiLevel) {
|
FileCollection getAndroidPrebuilt(String apiLevel) {
|
||||||
files("$sdkLoc/platforms/android-$apiLevel/android.jar")
|
files("$sdkLoc/platforms/android-$apiLevel/android.jar")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':support-v4')
|
compile project(':support-v4')
|
||||||
|
compile project(':support-appcompat-v7')
|
||||||
compile project(':extern:AndroidPinning')
|
compile project(':extern:AndroidPinning')
|
||||||
compile project(':extern:UniversalImageLoader:library')
|
compile project(':extern:UniversalImageLoader:library')
|
||||||
compile project(':extern:MemorizingTrustManager')
|
compile project(':extern:MemorizingTrustManager')
|
||||||
@ -25,6 +27,9 @@ dependencies {
|
|||||||
compile project(':extern:jmdns')
|
compile project(':extern:jmdns')
|
||||||
compile project(':extern:zipsigner')
|
compile project(':extern:zipsigner')
|
||||||
compile project(':extern:zxing-core')
|
compile project(':extern:zxing-core')
|
||||||
|
compile( project(':extern:android-support-v4-preferencefragment') ) {
|
||||||
|
exclude module: 'support-v4'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
project(':extern:UniversalImageLoader:library') {
|
project(':extern:UniversalImageLoader:library') {
|
||||||
@ -120,6 +125,15 @@ android.applicationVariants.all { variant ->
|
|||||||
// This is the hacky way which we force the subprojects to use the same build tools:
|
// This is the hacky way which we force the subprojects to use the same build tools:
|
||||||
// http://stackoverflow.com/a/21032272
|
// http://stackoverflow.com/a/21032272
|
||||||
subprojects {
|
subprojects {
|
||||||
|
|
||||||
|
// The support-v4 library assumes certain things are defined in the
|
||||||
|
// root project (which is usually the android-support project, but
|
||||||
|
// this time it is the F-Droid project.
|
||||||
|
if (project.name.equals("support-v4")) {
|
||||||
|
apply plugin: 'maven'
|
||||||
|
rootProject.ext.supportRepoOut = ""
|
||||||
|
}
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
android {
|
android {
|
||||||
|
|
||||||
@ -138,3 +152,17 @@ subprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently a bit hacky, because android.plugin is protected.
|
||||||
|
* The end goal is to find something in the android BaseExtension class found here:
|
||||||
|
* https://android.googlesource.com/platform/tools/build/+/master/gradle/src/main/groovy/com/android/build/gradle/BaseExtension.groovy
|
||||||
|
* which ends up asking their Sdk class for it's location. That class knows about
|
||||||
|
* both ANDROID_HOME env variables, and also local.properties sdk.loc properties.
|
||||||
|
*
|
||||||
|
* If in the future, the android.adbExe is found to be inappropriate, deprecated,
|
||||||
|
* or a better way of finding the sdk path exists, we can change the implementation
|
||||||
|
* of this method to reflect that.
|
||||||
|
*/
|
||||||
|
def getSdkPath() {
|
||||||
|
new File( "$android.adbExe/../../" ).canonicalPath
|
||||||
|
}
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project name="custom_rules">
|
<project name="custom_rules">
|
||||||
|
|
||||||
|
<target name="-pre-build">
|
||||||
|
|
||||||
|
<echo message="Copying a bunch of files around to make F-Droid and its submodules build" />
|
||||||
|
<copy tofile="extern/android-support-v4-preferencefragment/libs/android-support-v4.jar"
|
||||||
|
file="libs/android-support-v4.jar" />
|
||||||
|
<copy tofile="extern/Support/v7/appcompat/libs/android-support-v4.jar"
|
||||||
|
file="libs/android-support-v4.jar" />
|
||||||
|
|
||||||
|
</target>
|
||||||
|
|
||||||
<target name="javadoc" description="Generate Javadocs">
|
<target name="javadoc" description="Generate Javadocs">
|
||||||
<javadoc sourcepath="${source.dir}"
|
<javadoc sourcepath="${source.dir}"
|
||||||
destdir="${out.dir}/javadoc"
|
destdir="${out.dir}/javadoc"
|
||||||
|
1
extern/android-support-v4-preferencefragment
vendored
Submodule
1
extern/android-support-v4-preferencefragment
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit fab3cf8a0699a5ba45b66d4dcddcf7947239de9b
|
@ -7,6 +7,8 @@ android.library.reference.2=extern/MemorizingTrustManager
|
|||||||
android.library.reference.3=extern/AndroidPinning
|
android.library.reference.3=extern/AndroidPinning
|
||||||
android.library.reference.4=extern/libsuperuser/libsuperuser
|
android.library.reference.4=extern/libsuperuser/libsuperuser
|
||||||
android.library.reference.5=extern/zxing-core
|
android.library.reference.5=extern/zxing-core
|
||||||
|
android.library.reference.6=extern/android-support-v4-preferencefragment
|
||||||
|
android.library.reference.7=extern/Support/v7/appcompat
|
||||||
|
|
||||||
# For java libraries, place symlinks in extern/symlinks-for-ant-and-eclipse/
|
# For java libraries, place symlinks in extern/symlinks-for-ant-and-eclipse/
|
||||||
source.dir=src;extern/symlinks-for-ant-and-eclipse
|
source.dir=src;extern/symlinks-for-ant-and-eclipse
|
||||||
|
34
res/layout-land/app_details.xml
Normal file
34
res/layout-land/app_details.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:padding="5dp"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/app_summary_container"
|
||||||
|
android:layout_width="0px"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/fragment_app_summary"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:name="org.fdroid.fdroid.AppDetails$AppDetailsSummaryFragment"
|
||||||
|
tools:layout="@layout/app_details_summary"/>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/fragment_app_list"
|
||||||
|
android:layout_width="0px"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:name="org.fdroid.fdroid.AppDetails$AppDetailsListFragment"
|
||||||
|
tools:layout="@android:layout/list_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -1,91 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:baselineAligned="false"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_weight="0.5" >
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/landleft"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="5dp"
|
|
||||||
android:layout_marginRight="4dp"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:orientation="vertical" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="false"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/header"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="4dp"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/icon"
|
|
||||||
android:contentDescription="@string/app_icon"
|
|
||||||
android:layout_width="56dp"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:layout_toRightOf="@id/icon"
|
|
||||||
android:layout_toEndOf="@id/icon"
|
|
||||||
android:orientation="vertical" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/license"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/categories"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/license"
|
|
||||||
android:layout_above="@id/status"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/status"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
<ListView
|
|
||||||
android:id="@android:id/list"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_weight="0.5"
|
|
||||||
android:scrollbars="none" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
16
res/layout/app_details.xml
Normal file
16
res/layout/app_details.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:padding="5dp">
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/fragment_app_list"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:name="org.fdroid.fdroid.AppDetails$AppDetailsListFragment"
|
||||||
|
tools:layout="@android:layout/list_content"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
154
res/layout/app_details_summary.xml
Normal file
154
res/layout/app_details_summary.xml
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:contentDescription="@string/app_icon"
|
||||||
|
android:layout_width="56dp"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
tools:src="@drawable/ic_launcher"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/status"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toRightOf="@id/icon"
|
||||||
|
android:layout_toEndOf="@id/icon"
|
||||||
|
android:layout_alignBottom="@id/icon"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
tools:text="Installed"
|
||||||
|
android:textSize="13sp" android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="false"
|
||||||
|
tools:text="F-Droid"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
android:layout_toRightOf="@id/icon"
|
||||||
|
android:layout_above="@id/status" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/categories"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignBottom="@id/icon"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
tools:text="System, Internet"
|
||||||
|
android:textSize="13sp" android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/license"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_above="@id/categories"
|
||||||
|
android:paddingRight="4dp"
|
||||||
|
tools:text="GPLv3+"
|
||||||
|
android:textSize="13sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/summary"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/icon"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="Application manager" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/appid"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/summary"
|
||||||
|
android:textSize="12sp"
|
||||||
|
tools:text="org.fdroid.fdroid" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/signature"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/appid"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/antifeatures"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/signature"
|
||||||
|
android:layout_marginTop="6sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="#ff0000"
|
||||||
|
tools:text="Feeds you too much chocolate" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/description"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/antifeatures"
|
||||||
|
android:layout_marginTop="8sp"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:singleLine="false"
|
||||||
|
tools:text="Connects to F-Droid compatible repositories. The default repo is hosted at f-droid.org, which contains only bona fide FOSS.
|
||||||
|
|
||||||
|
Android is open in the sense that you are free to install apks from anywhere you wish, but there are many good reasons for using a client/repository setup:
|
||||||
|
|
||||||
|
* Be notified when updates are available
|
||||||
|
* Keep track of older and beta versions
|
||||||
|
* Filter apps that aren't compatible with the device
|
||||||
|
* Find apps via categories and searchable descriptions
|
||||||
|
* Access associated urls for donations, source code etc.
|
||||||
|
* Stay safe by checking repo index signatures and apk hashes
|
||||||
|
|
||||||
|
Changelog" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/permissions"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/description"
|
||||||
|
android:layout_marginTop="8sp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="Permissions for version 1.0" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/permissions_list"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/permissions"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:singleLine="false"
|
||||||
|
tools:text=" * Full network access
|
||||||
|
* View network connections
|
||||||
|
* View Wi-Fi connections
|
||||||
|
* Connect and disconnect from Wi-Fi
|
||||||
|
* Pair with Bluetooth devices
|
||||||
|
* Run at startup
|
||||||
|
* Modify or delete the contents of your USB storage
|
||||||
|
* Control Near Field Communication
|
||||||
|
* Directly install apps
|
||||||
|
* Delete apps
|
||||||
|
* Full permission to all device features and storage
|
||||||
|
* Test access to protected storage" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -1,104 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:padding="5dp"
|
|
||||||
android:baselineAligned="false"
|
|
||||||
android:orientation="vertical" >
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:baselineAligned="false" >
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/icon"
|
|
||||||
android:contentDescription="@string/app_icon"
|
|
||||||
android:layout_width="56dp"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_toRightOf="@id/icon"
|
|
||||||
android:layout_toEndOf="@id/icon"
|
|
||||||
android:padding="5dp"
|
|
||||||
android:baselineAligned="false"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/license"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:layout_marginLeft="6sp"
|
|
||||||
android:layout_marginStart="6sp"
|
|
||||||
android:textSize="12sp"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:textSize="17sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:gravity="start"
|
|
||||||
android:textAlignment="viewStart"
|
|
||||||
android:layout_toLeftOf="@id/license"
|
|
||||||
android:layout_toStartOf="@id/license" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/categories"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_marginLeft="6sp"
|
|
||||||
android:layout_marginStart="6sp"
|
|
||||||
android:layout_below="@id/title"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/status"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:gravity="start"
|
|
||||||
android:textAlignment="viewStart"
|
|
||||||
android:layout_toLeftOf="@id/categories"
|
|
||||||
android:layout_toStartOf="@id/categories"
|
|
||||||
android:layout_below="@id/title" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<ListView
|
|
||||||
android:id="@android:id/list"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:scrollbars="none" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,10 +1,14 @@
|
|||||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<style name="AppBaseThemeDark" parent="android:Theme.Holo">
|
<style name="AppBaseThemeDark" parent="Theme.AppCompat">
|
||||||
<!-- API 11 theme customizations go here -->
|
<!-- API 11 theme customizations go here -->
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppBaseThemeLight" parent="android:Theme.Holo.Light">
|
<style name="AppBaseThemeLight" parent="Theme.AppCompat.Light">
|
||||||
|
<!-- API 11 theme customizations go here -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="AppBaseThemeLightWithDarkActionBar" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
<!-- API 11 theme customizations go here -->
|
<!-- API 11 theme customizations go here -->
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -11,5 +11,6 @@
|
|||||||
<string-array name="themeNames">
|
<string-array name="themeNames">
|
||||||
<item>Dark</item>
|
<item>Dark</item>
|
||||||
<item>Light</item>
|
<item>Light</item>
|
||||||
|
<item>Light (with dark action bar)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<item type="id" name="categorySpinner" />
|
<item type="id" name="categorySpinner" />
|
||||||
|
<item type="id" name="appDetailsSummaryHeader" />
|
||||||
</resources>
|
</resources>
|
@ -25,6 +25,7 @@
|
|||||||
<string-array name="themeValues">
|
<string-array name="themeValues">
|
||||||
<item>dark</item>
|
<item>dark</item>
|
||||||
<item>light</item>
|
<item>light</item>
|
||||||
|
<item>lightWithDarkActionBar</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<style name="AppBaseThemeDark" parent="android:Theme.Black">
|
<style name="AppBaseThemeDark" parent="Theme.AppCompat">
|
||||||
<!-- backward-compatibility theme options go here -->
|
<!-- backward-compatibility theme options go here -->
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppBaseThemeLight" parent="android:Theme.Light">
|
<style name="AppBaseThemeLight" parent="Theme.AppCompat.Light">
|
||||||
|
<!-- backward-compatibility theme options go here -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="AppBaseThemeLightWithDarkActionBar" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
<!-- backward-compatibility theme options go here -->
|
<!-- backward-compatibility theme options go here -->
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -25,4 +29,8 @@
|
|||||||
<!-- customizations that are not API-level specific go here. -->
|
<!-- customizations that are not API-level specific go here. -->
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="AppThemeLightWithDarkActionBar" parent="AppBaseThemeLightWithDarkActionBar">
|
||||||
|
<!-- customizations that are not API-level specific go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -10,6 +10,7 @@ include ':extern:spongycastle:pg'
|
|||||||
include ':extern:spongycastle:pkix'
|
include ':extern:spongycastle:pkix'
|
||||||
include ':extern:spongycastle:prov'
|
include ':extern:spongycastle:prov'
|
||||||
include ':extern:zxing-core'
|
include ':extern:zxing-core'
|
||||||
|
include ':extern:android-support-v4-preferencefragment'
|
||||||
|
|
||||||
include ':support-v4'
|
include ':support-v4'
|
||||||
project(':support-v4').projectDir = new File('extern/Support/v4')
|
project(':support-v4').projectDir = new File('extern/Support/v4')
|
||||||
|
@ -21,10 +21,12 @@ package org.fdroid.fdroid;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.ListActivity;
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.content.*;
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
@ -34,12 +36,12 @@ import android.graphics.Bitmap;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.preference.PreferenceManager;
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.ListFragment;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v4.view.MenuItemCompat;
|
import android.support.v4.view.MenuItemCompat;
|
||||||
import android.text.Editable;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.Html.TagHandler;
|
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
@ -52,8 +54,8 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
@ -64,20 +66,45 @@ import org.fdroid.fdroid.Utils.CommaSeparatedList;
|
|||||||
import org.fdroid.fdroid.compat.ActionBarCompat;
|
import org.fdroid.fdroid.compat.ActionBarCompat;
|
||||||
import org.fdroid.fdroid.compat.MenuManager;
|
import org.fdroid.fdroid.compat.MenuManager;
|
||||||
import org.fdroid.fdroid.compat.PackageManagerCompat;
|
import org.fdroid.fdroid.compat.PackageManagerCompat;
|
||||||
import org.fdroid.fdroid.data.*;
|
import org.fdroid.fdroid.data.Apk;
|
||||||
|
import org.fdroid.fdroid.data.ApkProvider;
|
||||||
|
import org.fdroid.fdroid.data.App;
|
||||||
|
import org.fdroid.fdroid.data.AppProvider;
|
||||||
|
import org.fdroid.fdroid.data.Repo;
|
||||||
|
import org.fdroid.fdroid.data.RepoProvider;
|
||||||
import org.fdroid.fdroid.installer.Installer;
|
import org.fdroid.fdroid.installer.Installer;
|
||||||
import org.fdroid.fdroid.installer.Installer.AndroidNotCompatibleException;
|
import org.fdroid.fdroid.installer.Installer.AndroidNotCompatibleException;
|
||||||
import org.fdroid.fdroid.installer.Installer.InstallerCallback;
|
import org.fdroid.fdroid.installer.Installer.InstallerCallback;
|
||||||
import org.fdroid.fdroid.net.ApkDownloader;
|
import org.fdroid.fdroid.net.ApkDownloader;
|
||||||
import org.fdroid.fdroid.net.Downloader;
|
import org.fdroid.fdroid.net.Downloader;
|
||||||
import org.xml.sax.XMLReader;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AppDetails extends ListActivity implements ProgressListener {
|
interface AppDetailsData {
|
||||||
|
public App getApp();
|
||||||
|
public AppDetails.ApkListAdapter getApks();
|
||||||
|
public Signature getInstalledSignature();
|
||||||
|
public String getInstalledSignatureId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface which allows the apk list fragment to communicate with the activity when
|
||||||
|
* a user requests to install/remove an apk by clicking on an item in the list.
|
||||||
|
*
|
||||||
|
* NOTE: This is <em>not</em> to do with with the sudo/packagemanager/other installer
|
||||||
|
* stuff which allows multiple ways to install apps. It is only here to make fragment-
|
||||||
|
* activity communication possible.
|
||||||
|
*/
|
||||||
|
interface AppInstallListener {
|
||||||
|
public void install(final Apk apk);
|
||||||
|
public void removeApk(String packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AppDetails extends ActionBarActivity implements ProgressListener, AppDetailsData, AppInstallListener {
|
||||||
|
|
||||||
private static final String TAG = "org.fdroid.fdroid.AppDetails";
|
private static final String TAG = "org.fdroid.fdroid.AppDetails";
|
||||||
|
|
||||||
public static final int REQUEST_ENABLE_BLUETOOTH = 2;
|
public static final int REQUEST_ENABLE_BLUETOOTH = 2;
|
||||||
@ -118,14 +145,13 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
AppDetails.this.finish();
|
AppDetails.this.finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateViews();
|
|
||||||
|
|
||||||
|
refreshApkList();
|
||||||
MenuManager.create(AppDetails.this).invalidateOptionsMenu();
|
MenuManager.create(AppDetails.this).invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ApkListAdapter extends ArrayAdapter<Apk> {
|
||||||
private class ApkListAdapter extends ArrayAdapter<Apk> {
|
|
||||||
|
|
||||||
private LayoutInflater mInflater = (LayoutInflater) mctx.getSystemService(
|
private LayoutInflater mInflater = (LayoutInflater) mctx.getSystemService(
|
||||||
Context.LAYOUT_INFLATER_SERVICE);
|
Context.LAYOUT_INFLATER_SERVICE);
|
||||||
@ -134,7 +160,7 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
super(context, 0);
|
super(context, 0);
|
||||||
List<Apk> apks = ApkProvider.Helper.findByApp(context, app.id);
|
List<Apk> apks = ApkProvider.Helper.findByApp(context, app.id);
|
||||||
for (Apk apk : apks ) {
|
for (Apk apk : apks ) {
|
||||||
if (apk.compatible || pref_incompatibleVersions) {
|
if (apk.compatible || Preferences.get().showIncompatibleVersions()) {
|
||||||
add(apk);
|
add(apk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,7 +175,7 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
ViewHolder holder;
|
ViewHolder holder;
|
||||||
|
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
convertView = mInflater.inflate(R.layout.apklistitem, null);
|
convertView = mInflater.inflate(R.layout.apklistitem, parent, false);
|
||||||
|
|
||||||
holder = new ViewHolder();
|
holder = new ViewHolder();
|
||||||
holder.version = (TextView) convertView.findViewById(R.id.version);
|
holder.version = (TextView) convertView.findViewById(R.id.version);
|
||||||
@ -185,7 +211,7 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
holder.size.setVisibility(View.GONE);
|
holder.size.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pref_expert) {
|
if (!Preferences.get().expertMode()) {
|
||||||
holder.api.setVisibility(View.GONE);
|
holder.api.setVisibility(View.GONE);
|
||||||
} else if (apk.minSdkVersion > 0 && apk.maxSdkVersion > 0) {
|
} else if (apk.minSdkVersion > 0 && apk.maxSdkVersion > 0) {
|
||||||
holder.api.setText(getString(R.string.minsdk_up_to_maxsdk,
|
holder.api.setText(getString(R.string.minsdk_up_to_maxsdk,
|
||||||
@ -216,7 +242,7 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
holder.added.setVisibility(View.GONE);
|
holder.added.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pref_expert && apk.nativecode != null) {
|
if (Preferences.get().expertMode() && apk.nativecode != null) {
|
||||||
holder.nativecode.setText(apk.nativecode.toString().replaceAll(","," "));
|
holder.nativecode.setText(apk.nativecode.toString().replaceAll(","," "));
|
||||||
holder.nativecode.setVisibility(View.VISIBLE);
|
holder.nativecode.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
@ -277,11 +303,7 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
private boolean startingIgnoreAll;
|
private boolean startingIgnoreAll;
|
||||||
private int startingIgnoreThis;
|
private int startingIgnoreThis;
|
||||||
|
|
||||||
LinearLayout headerView;
|
|
||||||
View infoView;
|
|
||||||
|
|
||||||
private final Context mctx = this;
|
private final Context mctx = this;
|
||||||
private DisplayImageOptions displayImageOptions;
|
|
||||||
private Installer installer;
|
private Installer installer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -337,9 +359,9 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
// fdroid.app:app.id
|
// fdroid.app:app.id
|
||||||
appId = data.getEncodedSchemeSpecificPart();
|
appId = data.getEncodedSchemeSpecificPart();
|
||||||
}
|
}
|
||||||
Log.d("FDroid", "AppDetails launched from link, for '" + appId + "'");
|
Log.d(TAG, "AppDetails launched from link, for '" + appId + "'");
|
||||||
} else if (!i.hasExtra(EXTRA_APPID)) {
|
} else if (!i.hasExtra(EXTRA_APPID)) {
|
||||||
Log.e("FDroid", "No application ID in AppDetails!?");
|
Log.e(TAG, "No application ID in AppDetails!?");
|
||||||
} else {
|
} else {
|
||||||
appId = i.getStringExtra(EXTRA_APPID);
|
appId = i.getStringExtra(EXTRA_APPID);
|
||||||
}
|
}
|
||||||
@ -355,33 +377,16 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
displayImageOptions = new DisplayImageOptions.Builder()
|
|
||||||
.cacheInMemory(true)
|
|
||||||
.cacheOnDisk(true)
|
|
||||||
.imageScaleType(ImageScaleType.NONE)
|
|
||||||
.showImageOnLoading(R.drawable.ic_repo_app_default)
|
|
||||||
.showImageForEmptyUri(R.drawable.ic_repo_app_default)
|
|
||||||
.bitmapConfig(Bitmap.Config.RGB_565)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
setContentView(R.layout.appdetails);
|
|
||||||
|
|
||||||
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
|
|
||||||
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
|
|
||||||
// for reason why.
|
|
||||||
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
|
|
||||||
|
|
||||||
if (getIntent().hasExtra(EXTRA_FROM)) {
|
if (getIntent().hasExtra(EXTRA_FROM)) {
|
||||||
setTitle(getIntent().getStringExtra(EXTRA_FROM));
|
setTitle(getIntent().getStringExtra(EXTRA_FROM));
|
||||||
}
|
}
|
||||||
|
|
||||||
mPm = getPackageManager();
|
mPm = getPackageManager();
|
||||||
|
|
||||||
installer = Installer.getActivityInstaller(this, mPm,
|
installer = Installer.getActivityInstaller(this, mPm, myInstallerCallback);
|
||||||
myInstallerCallback);
|
|
||||||
|
|
||||||
// Get the preferences we're going to use in this Activity...
|
// Get the preferences we're going to use in this Activity...
|
||||||
ConfigurationChangeHelper previousData = (ConfigurationChangeHelper)getLastNonConfigurationInstance();
|
ConfigurationChangeHelper previousData = (ConfigurationChangeHelper)getLastCustomNonConfigurationInstance();
|
||||||
if (previousData != null) {
|
if (previousData != null) {
|
||||||
Log.d(TAG, "Recreating view after configuration change.");
|
Log.d(TAG, "Recreating view after configuration change.");
|
||||||
downloadHandler = previousData.downloader;
|
downloadHandler = previousData.downloader;
|
||||||
@ -397,27 +402,33 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferences prefs = PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(getBaseContext());
|
|
||||||
pref_expert = prefs.getBoolean(Preferences.PREF_EXPERT, false);
|
|
||||||
pref_permissions = prefs.getBoolean(Preferences.PREF_PERMISSIONS, false);
|
|
||||||
pref_incompatibleVersions = prefs.getBoolean(
|
|
||||||
Preferences.PREF_INCOMP_VER, false);
|
|
||||||
|
|
||||||
// Set up the list...
|
// Set up the list...
|
||||||
headerView = new LinearLayout(this);
|
|
||||||
ListView lv = (ListView) findViewById(android.R.id.list);
|
|
||||||
lv.addHeaderView(headerView);
|
|
||||||
adapter = new ApkListAdapter(this, app);
|
adapter = new ApkListAdapter(this, app);
|
||||||
setListAdapter(adapter);
|
|
||||||
|
|
||||||
startViews();
|
// Wait until all other intialization before doing this, because it will create the
|
||||||
|
// fragments, which rely on data from the activity that is set earlier in this method.
|
||||||
|
setContentView(R.layout.app_details);
|
||||||
|
|
||||||
|
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
|
||||||
|
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
|
||||||
|
// for reason why.
|
||||||
|
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
|
// Check for the presence of a view which only exists in the landscape view.
|
||||||
|
// This seems to be the preferred way to interrogate the view, rather than
|
||||||
|
// to check the orientation. I guess this is because views can be dynamically
|
||||||
|
// chosen based on more than just orientation (e.g. large screen sizes).
|
||||||
|
View onlyInLandscape = findViewById(R.id.app_summary_container);
|
||||||
|
|
||||||
|
AppDetailsListFragment listFragment =
|
||||||
|
(AppDetailsListFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_app_list);
|
||||||
|
if (onlyInLandscape == null) {
|
||||||
|
listFragment.setupSummaryHeader();
|
||||||
|
} else {
|
||||||
|
listFragment.removeSummaryHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean pref_expert;
|
}
|
||||||
private boolean pref_permissions;
|
|
||||||
private boolean pref_incompatibleVersions;
|
|
||||||
|
|
||||||
// The signature of the installed version.
|
// The signature of the installed version.
|
||||||
private Signature mInstalledSignature;
|
private Signature mInstalledSignature;
|
||||||
@ -446,9 +457,12 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
updateProgressDialog();
|
updateProgressDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateViews();
|
@Override
|
||||||
|
protected void onResumeFragments() {
|
||||||
|
super.onResumeFragments();
|
||||||
|
refreshApkList();
|
||||||
MenuManager.create(this).invalidateOptionsMenu();
|
MenuManager.create(this).invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,7 +523,7 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object onRetainNonConfigurationInstance() {
|
public Object onRetainCustomNonConfigurationInstance() {
|
||||||
inProcessOfChangingConfiguration = true;
|
inProcessOfChangingConfiguration = true;
|
||||||
return new ConfigurationChangeHelper(downloadHandler, app);
|
return new ConfigurationChangeHelper(downloadHandler, app);
|
||||||
}
|
}
|
||||||
@ -538,7 +552,7 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
// Return true if the app was found, false otherwise.
|
// Return true if the app was found, false otherwise.
|
||||||
private boolean reset(String appId) {
|
private boolean reset(String appId) {
|
||||||
|
|
||||||
Log.d("FDroid", "Getting application details for " + appId);
|
Log.d(TAG, "Getting application details for " + appId);
|
||||||
App newApp = null;
|
App newApp = null;
|
||||||
|
|
||||||
if (appId != null && appId.length() > 0) {
|
if (appId != null && appId.length() > 0) {
|
||||||
@ -579,233 +593,22 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
Hasher hash = new Hasher("MD5", mInstalledSignature.toCharsString().getBytes());
|
Hasher hash = new Hasher("MD5", mInstalledSignature.toCharsString().getBytes());
|
||||||
mInstalledSigID = hash.getHash();
|
mInstalledSigID = hash.getHash();
|
||||||
} catch (NameNotFoundException e) {
|
} catch (NameNotFoundException e) {
|
||||||
Log.d("FDroid", "Failed to get installed signature");
|
Log.d(TAG, "Failed to get installed signature");
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
Log.d("FDroid", "Failed to calculate signature MD5 sum");
|
Log.d(TAG, "Failed to calculate signature MD5 sum");
|
||||||
mInstalledSignature = null;
|
mInstalledSignature = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startViews() {
|
private void refreshApkList() {
|
||||||
|
|
||||||
// Insert the 'infoView' (which contains the summary, various odds and
|
|
||||||
// ends, and the description) into the appropriate place, if we're in
|
|
||||||
// landscape mode. In portrait mode, we put it in the listview's
|
|
||||||
// header..
|
|
||||||
infoView = View.inflate(this, R.layout.appinfo, null);
|
|
||||||
LinearLayout landparent = (LinearLayout) findViewById(R.id.landleft);
|
|
||||||
headerView.removeAllViews();
|
|
||||||
if (landparent != null) {
|
|
||||||
landparent.addView(infoView);
|
|
||||||
Log.d("FDroid", "Setting up landscape view");
|
|
||||||
} else {
|
|
||||||
headerView.addView(infoView);
|
|
||||||
Log.d("FDroid", "Setting up portrait view");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the icon...
|
|
||||||
ImageView iv = (ImageView) findViewById(R.id.icon);
|
|
||||||
ImageLoader.getInstance().displayImage(app.iconUrl, iv,
|
|
||||||
displayImageOptions);
|
|
||||||
|
|
||||||
// Set the title and other header details...
|
|
||||||
TextView tv = (TextView) findViewById(R.id.title);
|
|
||||||
tv.setText(app.name);
|
|
||||||
tv = (TextView) findViewById(R.id.license);
|
|
||||||
tv.setText(app.license);
|
|
||||||
|
|
||||||
if (app.categories != null) {
|
|
||||||
tv = (TextView) findViewById(R.id.categories);
|
|
||||||
tv.setText(app.categories.toString().replaceAll(",",", "));
|
|
||||||
}
|
|
||||||
|
|
||||||
tv = (TextView) infoView.findViewById(R.id.description);
|
|
||||||
|
|
||||||
tv.setMovementMethod(LinkMovementMethod.getInstance());
|
|
||||||
|
|
||||||
// Need this to add the unimplemented support for ordered and unordered
|
|
||||||
// lists to Html.fromHtml().
|
|
||||||
class HtmlTagHandler implements TagHandler {
|
|
||||||
int listNum;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleTag(boolean opening, String tag, Editable output,
|
|
||||||
XMLReader reader) {
|
|
||||||
if (tag.equals("ul")) {
|
|
||||||
if (opening)
|
|
||||||
listNum = -1;
|
|
||||||
else
|
|
||||||
output.append('\n');
|
|
||||||
} else if (opening && tag.equals("ol")) {
|
|
||||||
if (opening)
|
|
||||||
listNum = 1;
|
|
||||||
else
|
|
||||||
output.append('\n');
|
|
||||||
} else if (tag.equals("li")) {
|
|
||||||
if (opening) {
|
|
||||||
if (listNum == -1) {
|
|
||||||
output.append("\t• ");
|
|
||||||
} else {
|
|
||||||
output.append("\t").append(Integer.toString(listNum)).append(". ");
|
|
||||||
listNum++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
output.append('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Spanned desc = Html.fromHtml(
|
|
||||||
app.description, null, new HtmlTagHandler());
|
|
||||||
tv.setText(desc.subSequence(0, desc.length() - 2));
|
|
||||||
|
|
||||||
tv = (TextView) infoView.findViewById(R.id.appid);
|
|
||||||
if (pref_expert)
|
|
||||||
tv.setText(app.id);
|
|
||||||
else
|
|
||||||
tv.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
tv = (TextView) infoView.findViewById(R.id.summary);
|
|
||||||
tv.setText(app.summary);
|
|
||||||
|
|
||||||
Apk curApk = null;
|
|
||||||
for (int i = 0; i < adapter.getCount(); i ++) {
|
|
||||||
Apk apk = adapter.getItem(i);
|
|
||||||
if (apk.vercode == app.suggestedVercode) {
|
|
||||||
curApk = apk;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pref_permissions && !adapter.isEmpty() &&
|
|
||||||
((curApk != null && curApk.compatible) || pref_incompatibleVersions)) {
|
|
||||||
tv = (TextView) infoView.findViewById(R.id.permissions_list);
|
|
||||||
|
|
||||||
CommaSeparatedList permsList = adapter.getItem(0).permissions;
|
|
||||||
if (permsList == null) {
|
|
||||||
tv.setText(getString(R.string.no_permissions));
|
|
||||||
} else {
|
|
||||||
Iterator<String> permissions = permsList.iterator();
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
while (permissions.hasNext()) {
|
|
||||||
String permissionName = permissions.next();
|
|
||||||
try {
|
|
||||||
Permission permission = new Permission(this, permissionName);
|
|
||||||
sb.append("\t• ").append(permission.getName()).append('\n');
|
|
||||||
} catch (NameNotFoundException e) {
|
|
||||||
if (permissionName.equals("ACCESS_SUPERUSER")) {
|
|
||||||
sb.append("\t• Full permissions to all device features and storage\n");
|
|
||||||
} else {
|
|
||||||
Log.d("FDroid", "Permission not yet available: " + permissionName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sb.length() > 0) sb.setLength(sb.length() - 1);
|
|
||||||
tv.setText(sb.toString());
|
|
||||||
}
|
|
||||||
tv = (TextView) infoView.findViewById(R.id.permissions);
|
|
||||||
tv.setText(getString(
|
|
||||||
R.string.permissions_for_long, adapter.getItem(0).version));
|
|
||||||
} else {
|
|
||||||
infoView.findViewById(R.id.permissions).setVisibility(View.GONE);
|
|
||||||
infoView.findViewById(R.id.permissions_list).setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
tv = (TextView) infoView.findViewById(R.id.antifeatures);
|
|
||||||
if (app.antiFeatures != null) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (String af : app.antiFeatures) {
|
|
||||||
String afdesc = descAntiFeature(af);
|
|
||||||
if (afdesc != null) {
|
|
||||||
sb.append("\t• ").append(afdesc).append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
sb.setLength(sb.length() - 1);
|
|
||||||
tv.setText(sb.toString());
|
|
||||||
} else {
|
|
||||||
tv.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tv.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String descAntiFeature(String af) {
|
|
||||||
if (af.equals("Ads"))
|
|
||||||
return getString(R.string.antiadslist);
|
|
||||||
if (af.equals("Tracking"))
|
|
||||||
return getString(R.string.antitracklist);
|
|
||||||
if (af.equals("NonFreeNet"))
|
|
||||||
return getString(R.string.antinonfreenetlist);
|
|
||||||
if (af.equals("NonFreeAdd"))
|
|
||||||
return getString(R.string.antinonfreeadlist);
|
|
||||||
if (af.equals("NonFreeDep"))
|
|
||||||
return getString(R.string.antinonfreedeplist);
|
|
||||||
if (af.equals("UpstreamNonFree"))
|
|
||||||
return getString(R.string.antiupstreamnonfreelist);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateViews() {
|
|
||||||
|
|
||||||
// Refresh the list...
|
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
|
|
||||||
TextView tv = (TextView) findViewById(R.id.status);
|
|
||||||
if (app.isInstalled()) {
|
|
||||||
tv.setText(getString(R.string.details_installed,
|
|
||||||
app.installedVersionName));
|
|
||||||
NfcBeamManager.setAndroidBeam(this, app.id);
|
|
||||||
} else {
|
|
||||||
tv.setText(getString(R.string.details_notinstalled));
|
|
||||||
NfcBeamManager.disableAndroidBeam(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
tv = (TextView) infoView.findViewById(R.id.signature);
|
|
||||||
if (pref_expert && mInstalledSignature != null) {
|
|
||||||
tv.setVisibility(View.VISIBLE);
|
|
||||||
tv.setText("Signed: " + mInstalledSigID);
|
|
||||||
} else {
|
|
||||||
tv.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
|
||||||
final Apk apk = adapter.getItem(position - l.getHeaderViewsCount());
|
|
||||||
if (app.installedVersionCode == apk.vercode)
|
|
||||||
removeApk(app.id);
|
|
||||||
else if (app.installedVersionCode > apk.vercode) {
|
|
||||||
AlertDialog.Builder ask_alrt = new AlertDialog.Builder(this);
|
|
||||||
ask_alrt.setMessage(getString(R.string.installDowngrade));
|
|
||||||
ask_alrt.setPositiveButton(getString(R.string.yes),
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog,
|
|
||||||
int whichButton) {
|
|
||||||
install(apk);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ask_alrt.setNegativeButton(getString(R.string.no),
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog,
|
|
||||||
int whichButton) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
AlertDialog alert = ask_alrt.create();
|
|
||||||
alert.show();
|
|
||||||
} else
|
|
||||||
install(apk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
|
|
||||||
super.onCreateOptionsMenu(menu);
|
super.onPrepareOptionsMenu(menu);
|
||||||
menu.clear();
|
menu.clear();
|
||||||
if (app == null)
|
if (app == null)
|
||||||
return true;
|
return true;
|
||||||
@ -997,8 +800,7 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Install the version of this app denoted by 'app.curApk'.
|
// Install the version of this app denoted by 'app.curApk'.
|
||||||
private void install(final Apk apk) {
|
public void install(final Apk apk) {
|
||||||
final Activity activity = this;
|
|
||||||
String [] projection = { RepoProvider.DataColumns.ADDRESS };
|
String [] projection = { RepoProvider.DataColumns.ADDRESS };
|
||||||
Repo repo = RepoProvider.Helper.findById(this, apk.repo, projection);
|
Repo repo = RepoProvider.Helper.findById(this, apk.repo, projection);
|
||||||
if (repo == null || repo.address == null) {
|
if (repo == null || repo.address == null) {
|
||||||
@ -1064,7 +866,8 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeApk(String packageName) {
|
@Override
|
||||||
|
public void removeApk(String packageName) {
|
||||||
setProgressBarIndeterminateVisibility(true);
|
setProgressBarIndeterminateVisibility(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -1253,4 +1056,327 @@ public class AppDetails extends ListActivity implements ProgressListener {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public App getApp() {
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApkListAdapter getApks() {
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Signature getInstalledSignature() {
|
||||||
|
return mInstalledSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstalledSignatureId() {
|
||||||
|
return mInstalledSigID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AppDetailsSummaryFragment extends Fragment {
|
||||||
|
|
||||||
|
protected final Preferences prefs;
|
||||||
|
protected final DisplayImageOptions displayImageOptions;
|
||||||
|
private AppDetailsData data;
|
||||||
|
|
||||||
|
public AppDetailsSummaryFragment() {
|
||||||
|
prefs = Preferences.get();
|
||||||
|
displayImageOptions = new DisplayImageOptions.Builder()
|
||||||
|
.cacheInMemory(true)
|
||||||
|
.cacheOnDisk(true)
|
||||||
|
.imageScaleType(ImageScaleType.NONE)
|
||||||
|
.showImageOnLoading(R.drawable.ic_repo_app_default)
|
||||||
|
.showImageForEmptyUri(R.drawable.ic_repo_app_default)
|
||||||
|
.bitmapConfig(Bitmap.Config.RGB_565)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Activity activity) {
|
||||||
|
super.onAttach(activity);
|
||||||
|
data = (AppDetailsData)activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected App getApp() {
|
||||||
|
return data.getApp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ApkListAdapter getApks() {
|
||||||
|
return data.getApks();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Signature getInstalledSignature() {
|
||||||
|
return data.getInstalledSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getInstalledSignatureId() {
|
||||||
|
return data.getInstalledSignatureId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
View summaryView = inflater.inflate(R.layout.app_details_summary, container, false);
|
||||||
|
setupView(summaryView);
|
||||||
|
return summaryView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
updateViews(getView());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupView(View view) {
|
||||||
|
|
||||||
|
// Set the icon...
|
||||||
|
ImageView iv = (ImageView) view.findViewById(R.id.icon);
|
||||||
|
ImageLoader.getInstance().displayImage(getApp().iconUrl, iv, displayImageOptions);
|
||||||
|
|
||||||
|
// Set the title and other header details...
|
||||||
|
TextView tv = (TextView) view.findViewById(R.id.title);
|
||||||
|
tv.setText(getApp().name);
|
||||||
|
tv = (TextView) view.findViewById(R.id.license);
|
||||||
|
tv.setText(getApp().license);
|
||||||
|
|
||||||
|
if (getApp().categories != null) {
|
||||||
|
tv = (TextView) view.findViewById(R.id.categories);
|
||||||
|
tv.setText(getApp().categories.toString().replaceAll(",", ", "));
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView description = (TextView) view.findViewById(R.id.description);
|
||||||
|
Spanned desc = Html.fromHtml(getApp().description, null, new Utils.HtmlTagHandler());
|
||||||
|
description.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
description.setText(desc.subSequence(0, desc.length() - 2));
|
||||||
|
|
||||||
|
TextView appIdView = (TextView) view.findViewById(R.id.appid);
|
||||||
|
if (prefs.expertMode())
|
||||||
|
appIdView.setText(getApp().id);
|
||||||
|
else
|
||||||
|
appIdView.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
TextView summaryView = (TextView) view.findViewById(R.id.summary);
|
||||||
|
summaryView.setText(getApp().summary);
|
||||||
|
|
||||||
|
Apk curApk = null;
|
||||||
|
for (int i = 0; i < getApks().getCount(); i ++) {
|
||||||
|
Apk apk = getApks().getItem(i);
|
||||||
|
if (apk.vercode == getApp().suggestedVercode) {
|
||||||
|
curApk = apk;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView permissionListView = (TextView) view.findViewById(R.id.permissions_list);
|
||||||
|
TextView permissionHeader = (TextView) view.findViewById(R.id.permissions);
|
||||||
|
boolean curApkCompatible = curApk != null && curApk.compatible;
|
||||||
|
if (prefs.showPermissions() && !getApks().isEmpty() &&
|
||||||
|
( curApkCompatible || prefs.showIncompatibleVersions() ) ) {
|
||||||
|
|
||||||
|
CommaSeparatedList permsList = getApks().getItem(0).permissions;
|
||||||
|
if (permsList == null) {
|
||||||
|
permissionListView.setText(getString(R.string.no_permissions));
|
||||||
|
} else {
|
||||||
|
Iterator<String> permissions = permsList.iterator();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (permissions.hasNext()) {
|
||||||
|
String permissionName = permissions.next();
|
||||||
|
try {
|
||||||
|
Permission permission = new Permission(getActivity(), permissionName);
|
||||||
|
// TODO: Make this list RTL friendly
|
||||||
|
sb.append("\t• ").append(permission.getName()).append('\n');
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
if (permissionName.equals("ACCESS_SUPERUSER")) {
|
||||||
|
// TODO: i18n this string, but surely it is already translated somewhere?
|
||||||
|
sb.append("\t• Full permissions to all device features and storage\n");
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Permission not yet available: " + permissionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sb.length() > 0) sb.setLength(sb.length() - 1);
|
||||||
|
permissionListView.setText(sb.toString());
|
||||||
|
}
|
||||||
|
permissionHeader.setText(getString(R.string.permissions_for_long, getApks().getItem(0).version));
|
||||||
|
} else {
|
||||||
|
permissionListView.setVisibility(View.GONE);
|
||||||
|
permissionHeader.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView antiFeaturesView = (TextView) view.findViewById(R.id.antifeatures);
|
||||||
|
if (getApp().antiFeatures != null) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String af : getApp().antiFeatures) {
|
||||||
|
String afdesc = descAntiFeature(af);
|
||||||
|
if (afdesc != null) {
|
||||||
|
sb.append("\t• ").append(afdesc).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.setLength(sb.length() - 1);
|
||||||
|
antiFeaturesView.setText(sb.toString());
|
||||||
|
} else {
|
||||||
|
antiFeaturesView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
antiFeaturesView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateViews(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String descAntiFeature(String af) {
|
||||||
|
if (af.equals("Ads"))
|
||||||
|
return getString(R.string.antiadslist);
|
||||||
|
if (af.equals("Tracking"))
|
||||||
|
return getString(R.string.antitracklist);
|
||||||
|
if (af.equals("NonFreeNet"))
|
||||||
|
return getString(R.string.antinonfreenetlist);
|
||||||
|
if (af.equals("NonFreeAdd"))
|
||||||
|
return getString(R.string.antinonfreeadlist);
|
||||||
|
if (af.equals("NonFreeDep"))
|
||||||
|
return getString(R.string.antinonfreedeplist);
|
||||||
|
if (af.equals("UpstreamNonFree"))
|
||||||
|
return getString(R.string.antiupstreamnonfreelist);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateViews(View view) {
|
||||||
|
|
||||||
|
if (view == null) {
|
||||||
|
Log.e(TAG, "AppDetailsSummaryFragment.refreshApkList - view == null. Oops.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView statusView = (TextView) view.findViewById(R.id.status);
|
||||||
|
if (getApp().isInstalled()) {
|
||||||
|
statusView.setText(getString(R.string.details_installed, getApp().installedVersionName));
|
||||||
|
NfcBeamManager.setAndroidBeam(getActivity(), getApp().id);
|
||||||
|
} else {
|
||||||
|
statusView.setText(getString(R.string.details_notinstalled));
|
||||||
|
NfcBeamManager.disableAndroidBeam(getActivity());
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView signatureView = (TextView) view.findViewById(R.id.signature);
|
||||||
|
if (prefs.expertMode() && getInstalledSignature() != null) {
|
||||||
|
signatureView.setVisibility(View.VISIBLE);
|
||||||
|
signatureView.setText("Signed: " + getInstalledSignatureId());
|
||||||
|
} else {
|
||||||
|
signatureView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AppDetailsListFragment extends ListFragment {
|
||||||
|
|
||||||
|
private final String SUMMARY_TAG = "summary";
|
||||||
|
|
||||||
|
private AppDetailsData data;
|
||||||
|
private AppInstallListener installListener;
|
||||||
|
private AppDetailsSummaryFragment summaryFragment = null;
|
||||||
|
|
||||||
|
private FrameLayout headerView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Activity activity) {
|
||||||
|
super.onAttach(activity);
|
||||||
|
data = (AppDetailsData)activity;
|
||||||
|
installListener = (AppInstallListener)activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void install(final Apk apk) {
|
||||||
|
installListener.install(apk);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void remove() {
|
||||||
|
installListener.removeApk(getApp().id);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected App getApp() {
|
||||||
|
return data.getApp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ApkListAdapter getApks() {
|
||||||
|
return data.getApks();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
|
// A bit of a hack, but we can't add the header view in setupSummaryHeader(),
|
||||||
|
// due to the fact it needs to happen before setListAdapter(). Also, seeing
|
||||||
|
// as we may never add a summary header (i.e. in landscape), this is probably
|
||||||
|
// the last opportunity to set the list adapter. As such, we use the headerView
|
||||||
|
// as a mechanism to optionally allow adding a header in the future.
|
||||||
|
if (headerView == null) {
|
||||||
|
headerView = new FrameLayout(getActivity().getApplicationContext());
|
||||||
|
headerView.setId(R.id.appDetailsSummaryHeader);
|
||||||
|
} else {
|
||||||
|
Fragment summaryFragment = getChildFragmentManager().findFragmentByTag(SUMMARY_TAG);
|
||||||
|
if (summaryFragment != null) {
|
||||||
|
getChildFragmentManager().beginTransaction().remove(summaryFragment).commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setListAdapter(null);
|
||||||
|
getListView().addHeaderView(headerView);
|
||||||
|
setListAdapter(getApks());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
|
final Apk apk = getApks().getItem(position - l.getHeaderViewsCount());
|
||||||
|
if (getApp().installedVersionCode == apk.vercode)
|
||||||
|
remove();
|
||||||
|
else if (getApp().installedVersionCode > apk.vercode) {
|
||||||
|
AlertDialog.Builder ask_alrt = new AlertDialog.Builder(getActivity());
|
||||||
|
ask_alrt.setMessage(getString(R.string.installDowngrade));
|
||||||
|
ask_alrt.setPositiveButton(getString(R.string.yes),
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog,
|
||||||
|
int whichButton) {
|
||||||
|
install(apk);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ask_alrt.setNegativeButton(getString(R.string.no),
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog,
|
||||||
|
int whichButton) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AlertDialog alert = ask_alrt.create();
|
||||||
|
alert.show();
|
||||||
|
} else
|
||||||
|
install(apk);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSummaryHeader() {
|
||||||
|
Fragment summary = getChildFragmentManager().findFragmentByTag(SUMMARY_TAG);
|
||||||
|
if (summary != null) {
|
||||||
|
getChildFragmentManager().beginTransaction().remove(summary).commit();
|
||||||
|
headerView.removeAllViews();
|
||||||
|
headerView.setVisibility(View.GONE);
|
||||||
|
summaryFragment = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupSummaryHeader() {
|
||||||
|
Fragment fragment = getChildFragmentManager().findFragmentByTag(SUMMARY_TAG);
|
||||||
|
if (fragment != null) {
|
||||||
|
summaryFragment = (AppDetailsSummaryFragment)fragment;
|
||||||
|
} else {
|
||||||
|
summaryFragment = new AppDetailsSummaryFragment();
|
||||||
|
}
|
||||||
|
getChildFragmentManager().beginTransaction().replace(headerView.getId(), summaryFragment, SUMMARY_TAG).commit();
|
||||||
|
headerView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -32,9 +32,9 @@ import android.database.ContentObserver;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentActivity;
|
|
||||||
import android.support.v4.view.MenuItemCompat;
|
import android.support.v4.view.MenuItemCompat;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -42,13 +42,12 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.fdroid.fdroid.compat.TabManager;
|
import org.fdroid.fdroid.compat.TabManager;
|
||||||
import org.fdroid.fdroid.data.AppProvider;
|
import org.fdroid.fdroid.data.AppProvider;
|
||||||
import org.fdroid.fdroid.views.AppListFragmentPageAdapter;
|
import org.fdroid.fdroid.views.AppListFragmentPageAdapter;
|
||||||
import org.fdroid.fdroid.views.LocalRepoActivity;
|
import org.fdroid.fdroid.views.LocalRepoActivity;
|
||||||
|
|
||||||
public class FDroid extends FragmentActivity {
|
public class FDroid extends ActionBarActivity {
|
||||||
|
|
||||||
public static final int REQUEST_APPDETAILS = 0;
|
public static final int REQUEST_APPDETAILS = 0;
|
||||||
public static final int REQUEST_MANAGEREPOS = 1;
|
public static final int REQUEST_MANAGEREPOS = 1;
|
||||||
@ -80,6 +79,7 @@ public class FDroid extends FragmentActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.fdroid);
|
setContentView(R.layout.fdroid);
|
||||||
createViews();
|
createViews();
|
||||||
|
|
||||||
getTabManager().createTabs();
|
getTabManager().createTabs();
|
||||||
|
|
||||||
// Start a search by just typing
|
// Start a search by just typing
|
||||||
@ -333,7 +333,7 @@ public class FDroid extends FragmentActivity {
|
|||||||
|
|
||||||
private TabManager getTabManager() {
|
private TabManager getTabManager() {
|
||||||
if (tabManager == null) {
|
if (tabManager == null) {
|
||||||
tabManager = TabManager.create(this, viewPager);
|
tabManager = new TabManager(this, viewPager);
|
||||||
}
|
}
|
||||||
return tabManager;
|
return tabManager;
|
||||||
}
|
}
|
||||||
|
@ -32,15 +32,12 @@ import android.os.*;
|
|||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.cache.disc.impl.LimitedAgeDiscCache;
|
import com.nostra13.universalimageloader.cache.disc.impl.LimitedAgeDiscCache;
|
||||||
import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
|
import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||||
import com.nostra13.universalimageloader.utils.StorageUtils;
|
import com.nostra13.universalimageloader.utils.StorageUtils;
|
||||||
|
|
||||||
import de.duenndns.ssl.MemorizingTrustManager;
|
import de.duenndns.ssl.MemorizingTrustManager;
|
||||||
|
|
||||||
import org.fdroid.fdroid.Preferences.ChangeListener;
|
import org.fdroid.fdroid.Preferences.ChangeListener;
|
||||||
import org.fdroid.fdroid.compat.PRNGFixes;
|
import org.fdroid.fdroid.compat.PRNGFixes;
|
||||||
import org.fdroid.fdroid.data.AppProvider;
|
import org.fdroid.fdroid.data.AppProvider;
|
||||||
@ -52,6 +49,11 @@ import org.fdroid.fdroid.net.WifiStateChangeService;
|
|||||||
import org.thoughtcrime.ssl.pinning.PinningTrustManager;
|
import org.thoughtcrime.ssl.pinning.PinningTrustManager;
|
||||||
import org.thoughtcrime.ssl.pinning.SystemKeyStore;
|
import org.thoughtcrime.ssl.pinning.SystemKeyStore;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -74,7 +76,7 @@ public class FDroidApp extends Application {
|
|||||||
BluetoothAdapter bluetoothAdapter = null;
|
BluetoothAdapter bluetoothAdapter = null;
|
||||||
|
|
||||||
private static enum Theme {
|
private static enum Theme {
|
||||||
dark, light
|
dark, light, lightWithDarkActionBar
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Theme curTheme = Theme.dark;
|
private static Theme curTheme = Theme.dark;
|
||||||
@ -88,11 +90,14 @@ public class FDroidApp extends Application {
|
|||||||
public void applyTheme(Activity activity) {
|
public void applyTheme(Activity activity) {
|
||||||
switch (curTheme) {
|
switch (curTheme) {
|
||||||
case dark:
|
case dark:
|
||||||
//activity.setTheme(R.style.AppThemeDark);
|
activity.setTheme(R.style.AppThemeDark);
|
||||||
return;
|
break;
|
||||||
case light:
|
case light:
|
||||||
activity.setTheme(R.style.AppThemeLight);
|
activity.setTheme(R.style.AppThemeLight);
|
||||||
return;
|
break;
|
||||||
|
case lightWithDarkActionBar:
|
||||||
|
activity.setTheme(R.style.AppThemeLightWithDarkActionBar);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,20 +26,19 @@ import android.net.Uri;
|
|||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentActivity;
|
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.fdroid.fdroid.compat.ActionBarCompat;
|
|
||||||
import org.fdroid.fdroid.views.fragments.RepoListFragment;
|
import org.fdroid.fdroid.views.fragments.RepoListFragment;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
public class ManageRepo extends FragmentActivity {
|
|
||||||
|
public class ManageRepo extends ActionBarActivity {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we have a new repo added, or the address of a repo has changed, then
|
* If we have a new repo added, or the address of a repo has changed, then
|
||||||
@ -53,9 +52,9 @@ public class ManageRepo extends FragmentActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
((FDroidApp) getApplication()).applyTheme(this);
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
if (fm.findFragmentById(android.R.id.content) == null) {
|
if (fm.findFragmentById(android.R.id.content) == null) {
|
||||||
@ -72,7 +71,7 @@ public class ManageRepo extends FragmentActivity {
|
|||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,15 +2,16 @@
|
|||||||
package org.fdroid.fdroid;
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.nfc.NfcAdapter;
|
import android.nfc.NfcAdapter;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
|
||||||
// aka Android 4.0 aka Ice Cream Sandwich
|
// aka Android 4.0 aka Ice Cream Sandwich
|
||||||
public class NfcNotEnabledActivity extends Activity {
|
public class NfcNotEnabledActivity extends ActionBarActivity
|
||||||
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ACTION_NFC_SETTINGS was added in 4.1 aka Jelly Bean MR1 as a
|
* ACTION_NFC_SETTINGS was added in 4.1 aka Jelly Bean MR1 as a
|
||||||
@ -35,7 +36,10 @@ public class NfcNotEnabledActivity extends Activity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
final Intent intent = new Intent();
|
final Intent intent = new Intent();
|
||||||
if (Build.VERSION.SDK_INT >= 16) {
|
if (Build.VERSION.SDK_INT >= 16) {
|
||||||
doOnJellybean(intent);
|
doOnJellybean(intent);
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
package org.fdroid.fdroid;
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles shared preferences for FDroid, looking after the names of
|
* Handles shared preferences for FDroid, looking after the names of
|
||||||
* preferences, default values and caching. Needs to be setup in the FDroidApp
|
* preferences, default values and caching. Needs to be setup in the FDroidApp
|
||||||
@ -55,6 +61,9 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
|||||||
private static final boolean DEFAULT_SYSTEM_INSTALLER = false;
|
private static final boolean DEFAULT_SYSTEM_INSTALLER = false;
|
||||||
private static final boolean DEFAULT_LOCAL_REPO_BONJOUR = true;
|
private static final boolean DEFAULT_LOCAL_REPO_BONJOUR = true;
|
||||||
private static final boolean DEFAULT_LOCAL_REPO_HTTPS = false;
|
private static final boolean DEFAULT_LOCAL_REPO_HTTPS = false;
|
||||||
|
private static final boolean DEFAULT_INCOMP_VER = false;
|
||||||
|
private static final boolean DEFAULT_EXPERT = false;
|
||||||
|
private static final boolean DEFAULT_PERMISSIONS = false;
|
||||||
|
|
||||||
private boolean compactLayout = DEFAULT_COMPACT_LAYOUT;
|
private boolean compactLayout = DEFAULT_COMPACT_LAYOUT;
|
||||||
private boolean filterAppsRequiringRoot = DEFAULT_ROOTED;
|
private boolean filterAppsRequiringRoot = DEFAULT_ROOTED;
|
||||||
@ -92,6 +101,18 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
|||||||
return preferences.getBoolean(PREF_LOCAL_REPO_BONJOUR, DEFAULT_LOCAL_REPO_BONJOUR);
|
return preferences.getBoolean(PREF_LOCAL_REPO_BONJOUR, DEFAULT_LOCAL_REPO_BONJOUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean showIncompatibleVersions() {
|
||||||
|
return preferences.getBoolean(PREF_INCOMP_VER, DEFAULT_INCOMP_VER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean showPermissions() {
|
||||||
|
return preferences.getBoolean(PREF_PERMISSIONS, DEFAULT_PERMISSIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean expertMode() {
|
||||||
|
return preferences.getBoolean(PREF_EXPERT, DEFAULT_EXPERT);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isLocalRepoHttpsEnabled() {
|
public boolean isLocalRepoHttpsEnabled() {
|
||||||
return preferences.getBoolean(PREF_LOCAL_REPO_HTTPS, DEFAULT_LOCAL_REPO_HTTPS);
|
return preferences.getBoolean(PREF_LOCAL_REPO_HTTPS, DEFAULT_LOCAL_REPO_HTTPS);
|
||||||
}
|
}
|
||||||
|
@ -19,288 +19,42 @@
|
|||||||
package org.fdroid.fdroid;
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.Preference;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.preference.Preference.OnPreferenceClickListener;
|
|
||||||
import android.preference.PreferenceActivity;
|
|
||||||
import android.preference.CheckBoxPreference;
|
|
||||||
import android.preference.EditTextPreference;
|
|
||||||
import android.preference.ListPreference;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import org.fdroid.fdroid.views.fragments.PreferenceFragment;
|
||||||
|
|
||||||
import org.fdroid.fdroid.Preferences;
|
public class PreferencesActivity extends ActionBarActivity {
|
||||||
import org.fdroid.fdroid.compat.ActionBarCompat;
|
|
||||||
import org.fdroid.fdroid.installer.CheckRootAsyncTask;
|
|
||||||
import org.fdroid.fdroid.installer.CheckRootAsyncTask.CheckRootCallback;
|
|
||||||
import org.fdroid.fdroid.installer.Installer;
|
|
||||||
|
|
||||||
public class PreferencesActivity extends PreferenceActivity implements
|
|
||||||
OnSharedPreferenceChangeListener {
|
|
||||||
|
|
||||||
public static final int RESULT_RESTART = 4;
|
public static final int RESULT_RESTART = 4;
|
||||||
private int result = 0;
|
|
||||||
|
|
||||||
private static String[] summariesToUpdate = {
|
|
||||||
Preferences.PREF_UPD_INTERVAL,
|
|
||||||
Preferences.PREF_UPD_WIFI_ONLY,
|
|
||||||
Preferences.PREF_UPD_NOTIFY,
|
|
||||||
Preferences.PREF_UPD_HISTORY,
|
|
||||||
Preferences.PREF_ROOTED,
|
|
||||||
Preferences.PREF_INCOMP_VER,
|
|
||||||
Preferences.PREF_THEME,
|
|
||||||
Preferences.PREF_PERMISSIONS,
|
|
||||||
Preferences.PREF_COMPACT_LAYOUT,
|
|
||||||
Preferences.PREF_IGN_TOUCH,
|
|
||||||
Preferences.PREF_LOCAL_REPO_BONJOUR,
|
|
||||||
Preferences.PREF_LOCAL_REPO_NAME,
|
|
||||||
Preferences.PREF_LOCAL_REPO_HTTPS,
|
|
||||||
Preferences.PREF_CACHE_APK,
|
|
||||||
Preferences.PREF_EXPERT,
|
|
||||||
Preferences.PREF_ROOT_INSTALLER,
|
|
||||||
Preferences.PREF_SYSTEM_INSTALLER
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
((FDroidApp) getApplication()).applyTheme(this);
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
|
if (fm.findFragmentById(android.R.id.content) == null) {
|
||||||
|
// Need to set a dummy view (which will get overridden by the fragment manager
|
||||||
|
// below) so that we can call setContentView(). This is a work around for
|
||||||
|
// a (bug?) thing in 3.0, 3.1 which requires setContentView to be invoked before
|
||||||
|
// the actionbar is played with:
|
||||||
|
// http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
|
||||||
|
setContentView( new LinearLayout(this) );
|
||||||
|
|
||||||
|
PreferenceFragment preferenceFragment = new PreferenceFragment();
|
||||||
|
fm.beginTransaction()
|
||||||
|
.add(android.R.id.content, preferenceFragment)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
|
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
|
||||||
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
|
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
|
||||||
// for reason why.
|
// for reason why.
|
||||||
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.preferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onoffSummary(String key, int on, int off) {
|
|
||||||
CheckBoxPreference pref = (CheckBoxPreference)findPreference(key);
|
|
||||||
if (pref.isChecked()) {
|
|
||||||
pref.setSummary(on);
|
|
||||||
} else {
|
|
||||||
pref.setSummary(off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void entrySummary(String key) {
|
|
||||||
ListPreference pref = (ListPreference)findPreference(key);
|
|
||||||
pref.setSummary(pref.getEntry());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void textSummary(String key, int resId) {
|
|
||||||
EditTextPreference pref = (EditTextPreference)findPreference(key);
|
|
||||||
pref.setSummary(getString(resId, pref.getText()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateSummary(String key, boolean changing) {
|
|
||||||
|
|
||||||
if (key.equals(Preferences.PREF_UPD_INTERVAL)) {
|
|
||||||
ListPreference pref = (ListPreference)findPreference(
|
|
||||||
Preferences.PREF_UPD_INTERVAL);
|
|
||||||
int interval = Integer.parseInt(pref.getValue().toString());
|
|
||||||
Preference onlyOnWifi = findPreference(
|
|
||||||
Preferences.PREF_UPD_WIFI_ONLY);
|
|
||||||
onlyOnWifi.setEnabled(interval > 0);
|
|
||||||
if (interval == 0) {
|
|
||||||
pref.setSummary(R.string.update_interval_zero);
|
|
||||||
} else {
|
|
||||||
pref.setSummary(pref.getEntry());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_UPD_WIFI_ONLY)) {
|
|
||||||
onoffSummary(key, R.string.automatic_scan_wifi_on,
|
|
||||||
R.string.automatic_scan_wifi_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_UPD_NOTIFY)) {
|
|
||||||
onoffSummary(key, R.string.notify_on,
|
|
||||||
R.string.notify_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_UPD_HISTORY)) {
|
|
||||||
textSummary(key, R.string.update_history_summ);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_PERMISSIONS)) {
|
|
||||||
onoffSummary(key, R.string.showPermissions_on,
|
|
||||||
R.string.showPermissions_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_COMPACT_LAYOUT)) {
|
|
||||||
onoffSummary(key, R.string.compactlayout_on,
|
|
||||||
R.string.compactlayout_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_THEME)) {
|
|
||||||
entrySummary(key);
|
|
||||||
if (changing) {
|
|
||||||
result |= RESULT_RESTART;
|
|
||||||
setResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_INCOMP_VER)) {
|
|
||||||
onoffSummary(key, R.string.show_incompat_versions_on,
|
|
||||||
R.string.show_incompat_versions_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_ROOTED)) {
|
|
||||||
onoffSummary(key, R.string.rooted_on,
|
|
||||||
R.string.rooted_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_IGN_TOUCH)) {
|
|
||||||
onoffSummary(key, R.string.ignoreTouch_on,
|
|
||||||
R.string.ignoreTouch_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_LOCAL_REPO_BONJOUR)) {
|
|
||||||
onoffSummary(key, R.string.local_repo_bonjour_on,
|
|
||||||
R.string.local_repo_bonjour_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_LOCAL_REPO_NAME)) {
|
|
||||||
textSummary(key, R.string.local_repo_name_summary);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_LOCAL_REPO_HTTPS)) {
|
|
||||||
onoffSummary(key, R.string.local_repo_https_on,
|
|
||||||
R.string.local_repo_https_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_CACHE_APK)) {
|
|
||||||
onoffSummary(key, R.string.cache_downloaded_on,
|
|
||||||
R.string.cache_downloaded_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_EXPERT)) {
|
|
||||||
onoffSummary(key, R.string.expert_on,
|
|
||||||
R.string.expert_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_ROOT_INSTALLER)) {
|
|
||||||
onoffSummary(key, R.string.root_installer_on,
|
|
||||||
R.string.root_installer_off);
|
|
||||||
|
|
||||||
} else if (key.equals(Preferences.PREF_SYSTEM_INSTALLER)) {
|
|
||||||
onoffSummary(key, R.string.system_installer_on,
|
|
||||||
R.string.system_installer_off);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes RootInstaller preference. This method ensures that the preference can only be checked and persisted
|
|
||||||
* when the user grants root access for F-Droid.
|
|
||||||
*/
|
|
||||||
protected void initRootInstallerPreference() {
|
|
||||||
CheckBoxPreference pref = (CheckBoxPreference) findPreference(Preferences.PREF_ROOT_INSTALLER);
|
|
||||||
|
|
||||||
// we are handling persistence ourself!
|
|
||||||
pref.setPersistent(false);
|
|
||||||
|
|
||||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
final CheckBoxPreference pref = (CheckBoxPreference) preference;
|
|
||||||
|
|
||||||
if (pref.isChecked()) {
|
|
||||||
CheckRootAsyncTask checkTask = new CheckRootAsyncTask(PreferencesActivity.this, new CheckRootCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRootCheck(boolean rootGranted) {
|
|
||||||
if (rootGranted) {
|
|
||||||
// root access granted
|
|
||||||
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
|
||||||
editor.putBoolean(Preferences.PREF_ROOT_INSTALLER, true);
|
|
||||||
editor.commit();
|
|
||||||
pref.setChecked(true);
|
|
||||||
} else {
|
|
||||||
// root access denied
|
|
||||||
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
|
||||||
editor.putBoolean(Preferences.PREF_ROOT_INSTALLER, false);
|
|
||||||
editor.commit();
|
|
||||||
pref.setChecked(false);
|
|
||||||
|
|
||||||
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(PreferencesActivity.this);
|
|
||||||
alertBuilder.setTitle(R.string.root_access_denied_title);
|
|
||||||
alertBuilder.setMessage(PreferencesActivity.this.getString(R.string.root_access_denied_body));
|
|
||||||
alertBuilder.setNeutralButton(android.R.string.ok, null);
|
|
||||||
alertBuilder.create().show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
checkTask.execute();
|
|
||||||
} else {
|
|
||||||
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
|
||||||
editor.putBoolean(Preferences.PREF_ROOT_INSTALLER, false);
|
|
||||||
editor.commit();
|
|
||||||
pref.setChecked(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes SystemInstaller preference, which can only be enabled when F-Droid is installed as a system-app
|
|
||||||
*/
|
|
||||||
protected void initSystemInstallerPreference() {
|
|
||||||
CheckBoxPreference pref = (CheckBoxPreference) findPreference(Preferences.PREF_SYSTEM_INSTALLER);
|
|
||||||
|
|
||||||
// we are handling persistence ourself!
|
|
||||||
pref.setPersistent(false);
|
|
||||||
|
|
||||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
final CheckBoxPreference pref = (CheckBoxPreference) preference;
|
|
||||||
|
|
||||||
if (pref.isChecked()) {
|
|
||||||
if (Installer.hasSystemPermissions(PreferencesActivity.this, PreferencesActivity.this.getPackageManager())) {
|
|
||||||
// system-permission are granted, i.e. F-Droid is a system-app
|
|
||||||
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
|
||||||
editor.putBoolean(Preferences.PREF_SYSTEM_INSTALLER, true);
|
|
||||||
editor.commit();
|
|
||||||
pref.setChecked(true);
|
|
||||||
} else {
|
|
||||||
// system-permission not available
|
|
||||||
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
|
||||||
editor.putBoolean(Preferences.PREF_SYSTEM_INSTALLER, false);
|
|
||||||
editor.commit();
|
|
||||||
pref.setChecked(false);
|
|
||||||
|
|
||||||
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(PreferencesActivity.this);
|
|
||||||
alertBuilder.setTitle(R.string.system_permission_denied_title);
|
|
||||||
alertBuilder.setMessage(PreferencesActivity.this.getString(R.string.system_permission_denied_body));
|
|
||||||
alertBuilder.setNeutralButton(android.R.string.ok, null);
|
|
||||||
alertBuilder.create().show();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
|
||||||
editor.putBoolean(Preferences.PREF_SYSTEM_INSTALLER, false);
|
|
||||||
editor.commit();
|
|
||||||
pref.setChecked(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
|
|
||||||
getPreferenceScreen().getSharedPreferences()
|
|
||||||
.registerOnSharedPreferenceChangeListener(this);
|
|
||||||
|
|
||||||
for (String key : summariesToUpdate) {
|
|
||||||
updateSummary(key, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
initRootInstallerPreference();
|
|
||||||
initSystemInstallerPreference();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
|
|
||||||
getPreferenceScreen().getSharedPreferences()
|
|
||||||
.unregisterOnSharedPreferenceChangeListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -313,10 +67,4 @@ public class PreferencesActivity extends PreferenceActivity implements
|
|||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSharedPreferenceChanged(
|
|
||||||
SharedPreferences sharedPreferences, String key) {
|
|
||||||
updateSummary(key, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,16 @@ package org.fdroid.fdroid;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentActivity;
|
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v4.view.MenuItemCompat;
|
import android.support.v4.view.MenuItemCompat;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import org.fdroid.fdroid.compat.ActionBarCompat;
|
|
||||||
import org.fdroid.fdroid.views.fragments.SearchResultsFragment;
|
import org.fdroid.fdroid.views.fragments.SearchResultsFragment;
|
||||||
|
|
||||||
public class SearchResults extends FragmentActivity {
|
public class SearchResults extends ActionBarActivity {
|
||||||
|
|
||||||
private static final int SEARCH = Menu.FIRST;
|
private static final int SEARCH = Menu.FIRST;
|
||||||
|
|
||||||
@ -38,7 +37,6 @@ public class SearchResults extends FragmentActivity {
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
((FDroidApp) getApplication()).applyTheme(this);
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
// Start a search by just typing
|
// Start a search by just typing
|
||||||
@ -61,7 +59,7 @@ public class SearchResults extends FragmentActivity {
|
|||||||
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
|
// Actionbar cannot be accessed until after setContentView (on 3.0 and 3.1 devices)
|
||||||
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
|
// see: http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html
|
||||||
// for reason why.
|
// for reason why.
|
||||||
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,24 +23,41 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
|||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
import android.content.res.XmlResourceParser;
|
import android.content.res.XmlResourceParser;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.Html;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ListAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
import com.nostra13.universalimageloader.utils.StorageUtils;
|
import com.nostra13.universalimageloader.utils.StorageUtils;
|
||||||
|
|
||||||
import org.fdroid.fdroid.data.Repo;
|
import org.fdroid.fdroid.data.Repo;
|
||||||
|
import org.xml.sax.XMLReader;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.Formatter;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public final class Utils {
|
public final class Utils {
|
||||||
|
|
||||||
@ -452,4 +469,38 @@ public final class Utils {
|
|||||||
return String.format("%0" + (bytes.length << 1) + "X", bi);
|
return String.format("%0" + (bytes.length << 1) + "X", bi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Need this to add the unimplemented support for ordered and unordered
|
||||||
|
// lists to Html.fromHtml().
|
||||||
|
public static class HtmlTagHandler implements Html.TagHandler {
|
||||||
|
int listNum;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleTag(boolean opening, String tag, Editable output,
|
||||||
|
XMLReader reader) {
|
||||||
|
if (tag.equals("ul")) {
|
||||||
|
if (opening)
|
||||||
|
listNum = -1;
|
||||||
|
else
|
||||||
|
output.append('\n');
|
||||||
|
} else if (opening && tag.equals("ol")) {
|
||||||
|
if (opening)
|
||||||
|
listNum = 1;
|
||||||
|
else
|
||||||
|
output.append('\n');
|
||||||
|
} else if (tag.equals("li")) {
|
||||||
|
if (opening) {
|
||||||
|
if (listNum == -1) {
|
||||||
|
output.append("\t• ");
|
||||||
|
} else {
|
||||||
|
output.append("\t").append(Integer.toString(listNum)).append(". ");
|
||||||
|
listNum++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,38 @@
|
|||||||
package org.fdroid.fdroid.compat;
|
package org.fdroid.fdroid.compat;
|
||||||
|
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.support.v4.app.FragmentTransaction;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import org.fdroid.fdroid.FDroid;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
public class TabManager {
|
||||||
import android.app.ActionBar;
|
|
||||||
import android.app.FragmentTransaction;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.*;
|
|
||||||
|
|
||||||
import android.support.v4.view.ViewPager;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroid;
|
|
||||||
import org.fdroid.fdroid.R;
|
|
||||||
|
|
||||||
public abstract class TabManager extends Compatibility {
|
|
||||||
|
|
||||||
public static final int INDEX_AVAILABLE = 0;
|
public static final int INDEX_AVAILABLE = 0;
|
||||||
public static final int INDEX_INSTALLED = 1;
|
public static final int INDEX_INSTALLED = 1;
|
||||||
public static final int INDEX_CAN_UPDATE = 2;
|
public static final int INDEX_CAN_UPDATE = 2;
|
||||||
|
|
||||||
public static TabManager create(FDroid parent, ViewPager pager) {
|
private ViewPager pager;
|
||||||
if (hasApi(11)) {
|
private FDroid parent;
|
||||||
return new HoneycombTabManagerImpl(parent, pager);
|
private final ActionBar actionBar;
|
||||||
} else {
|
private Spinner actionBarSpinner = null;
|
||||||
return new OldTabManagerImpl(parent, pager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final ViewPager pager;
|
// Used to make sure we only search for the action bar spinner once
|
||||||
protected final FDroid parent;
|
// in each orientation.
|
||||||
|
private boolean dirtyConfig = true;
|
||||||
|
|
||||||
protected TabManager(FDroid parent, ViewPager pager) {
|
public TabManager(FDroid parent, ViewPager pager) {
|
||||||
|
actionBar = parent.getSupportActionBar();
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.pager = pager;
|
this.pager = pager;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public void createTabs();
|
|
||||||
abstract public void selectTab(int index);
|
|
||||||
abstract public void refreshTabLabel(int index);
|
|
||||||
abstract public void onConfigurationChanged(Configuration newConfig);
|
|
||||||
|
|
||||||
protected CharSequence getLabel(int index) {
|
protected CharSequence getLabel(int index) {
|
||||||
return pager.getAdapter().getPageTitle(index);
|
return pager.getAdapter().getPageTitle(index);
|
||||||
}
|
}
|
||||||
@ -50,126 +40,7 @@ public abstract class TabManager extends Compatibility {
|
|||||||
public void removeNotification(int id) {
|
public void removeNotification(int id) {
|
||||||
parent.removeNotification(id);
|
parent.removeNotification(id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class OldTabManagerImpl extends TabManager {
|
|
||||||
|
|
||||||
private TabHost tabHost;
|
|
||||||
|
|
||||||
public OldTabManagerImpl(FDroid parent, ViewPager pager) {
|
|
||||||
super(parent, pager);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* There is a bit of boiler-plate code required to get a TabWidget showing,
|
|
||||||
* which includes creating a TabHost, populating it with the TabWidget,
|
|
||||||
* and giving it a FrameLayout as a child. This will make the tabs have
|
|
||||||
* dummy empty contents and then hook them up to our ViewPager.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void createTabs() {
|
|
||||||
tabHost = new TabHost(parent, null);
|
|
||||||
tabHost.setLayoutParams(new TabHost.LayoutParams(
|
|
||||||
TabHost.LayoutParams.MATCH_PARENT, TabHost.LayoutParams.WRAP_CONTENT));
|
|
||||||
|
|
||||||
TabWidget tabWidget = new TabWidget(parent);
|
|
||||||
tabWidget.setId(android.R.id.tabs);
|
|
||||||
tabHost.setLayoutParams(new TabHost.LayoutParams(
|
|
||||||
TabWidget.LayoutParams.MATCH_PARENT, TabWidget.LayoutParams.WRAP_CONTENT));
|
|
||||||
|
|
||||||
FrameLayout layout = new FrameLayout(parent);
|
|
||||||
layout.setId(android.R.id.tabcontent);
|
|
||||||
layout.setLayoutParams(new TabWidget.LayoutParams(0, 0));
|
|
||||||
|
|
||||||
tabHost.addView(tabWidget);
|
|
||||||
tabHost.addView(layout);
|
|
||||||
tabHost.setup();
|
|
||||||
|
|
||||||
TabHost.TabContentFactory factory = new TabHost.TabContentFactory() {
|
|
||||||
@Override
|
|
||||||
public View createTabContent(String tag) {
|
|
||||||
return new View(parent);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TabHost.TabSpec availableTabSpec = tabHost.newTabSpec("available")
|
|
||||||
.setIndicator(
|
|
||||||
parent.getString(R.string.tab_noninstalled),
|
|
||||||
parent.getResources().getDrawable(android.R.drawable.ic_input_add))
|
|
||||||
.setContent(factory);
|
|
||||||
|
|
||||||
TabHost.TabSpec installedTabSpec = tabHost.newTabSpec("installed")
|
|
||||||
.setIndicator(
|
|
||||||
parent.getString(R.string.inst),
|
|
||||||
parent.getResources().getDrawable(android.R.drawable.star_off))
|
|
||||||
.setContent(factory);
|
|
||||||
|
|
||||||
TabHost.TabSpec canUpdateTabSpec = tabHost.newTabSpec("canUpdate")
|
|
||||||
.setIndicator(
|
|
||||||
parent.getString(R.string.tab_updates),
|
|
||||||
parent.getResources().getDrawable(android.R.drawable.star_on))
|
|
||||||
.setContent(factory);
|
|
||||||
|
|
||||||
tabHost.addTab(availableTabSpec);
|
|
||||||
tabHost.addTab(installedTabSpec);
|
|
||||||
tabHost.addTab(canUpdateTabSpec);
|
|
||||||
|
|
||||||
LinearLayout contentView = (LinearLayout)parent.findViewById(R.id.fdroid_layout);
|
|
||||||
contentView.addView(tabHost, 0);
|
|
||||||
|
|
||||||
tabHost.setOnTabChangedListener( new TabHost.OnTabChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onTabChanged(String tabId) {
|
|
||||||
int pos = tabHost.getCurrentTab();
|
|
||||||
pager.setCurrentItem(pos);
|
|
||||||
if (pos == INDEX_CAN_UPDATE)
|
|
||||||
removeNotification(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectTab(int index) {
|
|
||||||
tabHost.setCurrentTab(index);
|
|
||||||
if (index == INDEX_CAN_UPDATE)
|
|
||||||
removeNotification(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void refreshTabLabel(int index) {
|
|
||||||
CharSequence text = getLabel(index);
|
|
||||||
|
|
||||||
// Update the count on the 'Updates' tab to show the number available.
|
|
||||||
// This is quite unpleasant, but seems to be the only way to do it.
|
|
||||||
TextView textView = (TextView) tabHost.getTabWidget().getChildAt(index)
|
|
||||||
.findViewById(android.R.id.title);
|
|
||||||
textView.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(11)
|
|
||||||
class HoneycombTabManagerImpl extends TabManager {
|
|
||||||
|
|
||||||
protected final ActionBar actionBar;
|
|
||||||
private Spinner actionBarSpinner = null;
|
|
||||||
|
|
||||||
// Used to make sure we only search for the action bar spinner once
|
|
||||||
// in each orientation.
|
|
||||||
private boolean dirtyConfig = true;
|
|
||||||
|
|
||||||
public HoneycombTabManagerImpl(FDroid parent, ViewPager pager) {
|
|
||||||
super(parent, pager);
|
|
||||||
actionBar = parent.getActionBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createTabs() {
|
public void createTabs() {
|
||||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||||
for (int i = 0; i < pager.getAdapter().getCount(); i ++) {
|
for (int i = 0; i < pager.getAdapter().getCount(); i ++) {
|
||||||
@ -198,7 +69,6 @@ class HoneycombTabManagerImpl extends TabManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectTab(int index) {
|
public void selectTab(int index) {
|
||||||
actionBar.setSelectedNavigationItem(index);
|
actionBar.setSelectedNavigationItem(index);
|
||||||
Spinner actionBarSpinner = getActionBarSpinner();
|
Spinner actionBarSpinner = getActionBarSpinner();
|
||||||
@ -209,13 +79,11 @@ class HoneycombTabManagerImpl extends TabManager {
|
|||||||
removeNotification(1);
|
removeNotification(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void refreshTabLabel(int index) {
|
public void refreshTabLabel(int index) {
|
||||||
CharSequence text = getLabel(index);
|
CharSequence text = getLabel(index);
|
||||||
actionBar.getTabAt(index).setText(text);
|
actionBar.getTabAt(index).setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
dirtyConfig = true;
|
dirtyConfig = true;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,10 @@ import android.annotation.TargetApi;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.*;
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
@ -16,12 +19,22 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Build;
|
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.support.v7.app.ActionBarActivity;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.*;
|
import android.view.Menu;
|
||||||
import android.widget.*;
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import org.fdroid.fdroid.*;
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
|
import org.fdroid.fdroid.PreferencesActivity;
|
||||||
|
import org.fdroid.fdroid.QrGenAsyncTask;
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.localrepo.LocalRepoManager;
|
import org.fdroid.fdroid.localrepo.LocalRepoManager;
|
||||||
import org.fdroid.fdroid.localrepo.LocalRepoService;
|
import org.fdroid.fdroid.localrepo.LocalRepoService;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
@ -30,8 +43,9 @@ import java.util.Locale;
|
|||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
public class LocalRepoActivity extends Activity {
|
public class LocalRepoActivity extends ActionBarActivity {
|
||||||
private static final String TAG = "LocalRepoActivity";
|
|
||||||
|
private static final String TAG = "org.fdroid.fdroid.LocalRepoActivity";
|
||||||
private ProgressDialog repoProgress;
|
private ProgressDialog repoProgress;
|
||||||
|
|
||||||
private WifiManager wifiManager;
|
private WifiManager wifiManager;
|
||||||
@ -46,8 +60,8 @@ public class LocalRepoActivity extends Activity {
|
|||||||
/** Called when the activity is first created. */
|
/** Called when the activity is first created. */
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
((FDroidApp) getApplication()).applyTheme(this);
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.local_repo_activity);
|
setContentView(R.layout.local_repo_activity);
|
||||||
|
|
||||||
enableWifiButton = (Button) findViewById(R.id.enable_wifi);
|
enableWifiButton = (Button) findViewById(R.id.enable_wifi);
|
||||||
|
@ -1,27 +1,31 @@
|
|||||||
|
|
||||||
package org.fdroid.fdroid.views;
|
package org.fdroid.fdroid.views;
|
||||||
|
|
||||||
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.content.SharedPreferences;
|
||||||
import android.os.Build;
|
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.support.v7.app.ActionBarActivity;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.fdroid.fdroid.*;
|
import org.fdroid.fdroid.*;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
|
|
||||||
public class QrWizardDownloadActivity extends Activity {
|
public class QrWizardDownloadActivity extends ActionBarActivity {
|
||||||
private static final String TAG = "QrWizardDownloadActivity";
|
|
||||||
|
private static final String TAG = "org.fdroid.fdroid.QrWizardDownloadActivity";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
((FDroidApp) getApplication()).applyTheme(this);
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
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);
|
||||||
|
@ -1,37 +1,40 @@
|
|||||||
|
|
||||||
package org.fdroid.fdroid.views;
|
package org.fdroid.fdroid.views;
|
||||||
|
|
||||||
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.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.QrGenAsyncTask;
|
import org.fdroid.fdroid.QrGenAsyncTask;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
|
|
||||||
public class QrWizardWifiNetworkActivity extends Activity {
|
public class QrWizardWifiNetworkActivity extends ActionBarActivity {
|
||||||
private static final String TAG = "QrWizardWifiNetworkActivity";
|
private static final String TAG = "org.fdroid.fdroid.QrWizardWifiNetworkActivity";
|
||||||
|
|
||||||
private WifiManager wifiManager;
|
private WifiManager wifiManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
||||||
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);
|
||||||
|
@ -10,19 +10,19 @@ import android.nfc.NfcAdapter;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.NavUtils;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.compat.ActionBarCompat;
|
|
||||||
import org.fdroid.fdroid.data.Repo;
|
import org.fdroid.fdroid.data.Repo;
|
||||||
import org.fdroid.fdroid.data.RepoProvider;
|
import org.fdroid.fdroid.data.RepoProvider;
|
||||||
import org.fdroid.fdroid.views.fragments.RepoDetailsFragment;
|
import org.fdroid.fdroid.views.fragments.RepoDetailsFragment;
|
||||||
|
|
||||||
public class RepoDetailsActivity extends FragmentActivity {
|
public class RepoDetailsActivity extends ActionBarActivity {
|
||||||
public static final String TAG = "RepoDetailsActivity";
|
public static final String TAG = "RepoDetailsActivity";
|
||||||
|
|
||||||
private Repo repo;
|
private Repo repo;
|
||||||
@ -33,7 +33,6 @@ public class RepoDetailsActivity extends FragmentActivity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
((FDroidApp) getApplication()).applyTheme(this);
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
long repoId = getIntent().getLongExtra(RepoDetailsFragment.ARG_REPO_ID, 0);
|
long repoId = getIntent().getLongExtra(RepoDetailsFragment.ARG_REPO_ID, 0);
|
||||||
@ -62,7 +61,7 @@ public class RepoDetailsActivity extends FragmentActivity {
|
|||||||
};
|
};
|
||||||
repo = RepoProvider.Helper.findById(this, repoId, projection);
|
repo = RepoProvider.Helper.findById(this, repoId, projection);
|
||||||
|
|
||||||
ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
setTitle(repo.getName());
|
setTitle(repo.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,4 +122,15 @@ public class RepoDetailsActivity extends FragmentActivity {
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
NavUtils.navigateUpFromSameTask(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,30 @@
|
|||||||
|
|
||||||
package org.fdroid.fdroid.views;
|
package org.fdroid.fdroid.views;
|
||||||
|
|
||||||
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.view.*;
|
import android.support.v4.view.MenuItemCompat;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import android.view.ActionMode;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.widget.SearchView;
|
import android.widget.SearchView;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
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)
|
public class SelectLocalAppsActivity extends ActionBarActivity {
|
||||||
// TODO replace with appcompat-v7
|
|
||||||
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;
|
private SearchView searchView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
((FDroidApp) getApplication()).applyTheme(this);
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.select_local_apps_activity);
|
setContentView(R.layout.select_local_apps_activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,14 +32,14 @@ public class SelectLocalAppsActivity extends Activity {
|
|||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
if (selectLocalAppsFragment == null)
|
if (selectLocalAppsFragment == null)
|
||||||
selectLocalAppsFragment = (SelectLocalAppsFragment) getFragmentManager()
|
selectLocalAppsFragment = (SelectLocalAppsFragment) getSupportFragmentManager()
|
||||||
.findFragmentById(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 = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
|
||||||
searchView.setOnQueryTextListener(selectLocalAppsFragment);
|
searchView.setOnQueryTextListener(selectLocalAppsFragment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
279
src/org/fdroid/fdroid/views/fragments/PreferenceFragment.java
Normal file
279
src/org/fdroid/fdroid/views/fragments/PreferenceFragment.java
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
package org.fdroid.fdroid.views.fragments;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.CheckBoxPreference;
|
||||||
|
import android.preference.EditTextPreference;
|
||||||
|
import android.preference.ListPreference;
|
||||||
|
import android.preference.Preference;
|
||||||
|
import org.fdroid.fdroid.Preferences;
|
||||||
|
import org.fdroid.fdroid.PreferencesActivity;
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.installer.CheckRootAsyncTask;
|
||||||
|
import org.fdroid.fdroid.installer.Installer;
|
||||||
|
|
||||||
|
public class PreferenceFragment
|
||||||
|
extends android.support.v4.preference.PreferenceFragment
|
||||||
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
|
private static String[] summariesToUpdate = {
|
||||||
|
Preferences.PREF_UPD_INTERVAL,
|
||||||
|
Preferences.PREF_UPD_WIFI_ONLY,
|
||||||
|
Preferences.PREF_UPD_NOTIFY,
|
||||||
|
Preferences.PREF_UPD_HISTORY,
|
||||||
|
Preferences.PREF_ROOTED,
|
||||||
|
Preferences.PREF_INCOMP_VER,
|
||||||
|
Preferences.PREF_THEME,
|
||||||
|
Preferences.PREF_PERMISSIONS,
|
||||||
|
Preferences.PREF_COMPACT_LAYOUT,
|
||||||
|
Preferences.PREF_IGN_TOUCH,
|
||||||
|
Preferences.PREF_LOCAL_REPO_BONJOUR,
|
||||||
|
Preferences.PREF_LOCAL_REPO_NAME,
|
||||||
|
Preferences.PREF_LOCAL_REPO_HTTPS,
|
||||||
|
Preferences.PREF_CACHE_APK,
|
||||||
|
Preferences.PREF_EXPERT,
|
||||||
|
Preferences.PREF_ROOT_INSTALLER,
|
||||||
|
Preferences.PREF_SYSTEM_INSTALLER
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
addPreferencesFromResource(R.xml.preferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onoffSummary(String key, int on, int off) {
|
||||||
|
CheckBoxPreference pref = (CheckBoxPreference)findPreference(key);
|
||||||
|
if (pref.isChecked()) {
|
||||||
|
pref.setSummary(on);
|
||||||
|
} else {
|
||||||
|
pref.setSummary(off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void entrySummary(String key) {
|
||||||
|
ListPreference pref = (ListPreference)findPreference(key);
|
||||||
|
pref.setSummary(pref.getEntry());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void textSummary(String key, int resId) {
|
||||||
|
EditTextPreference pref = (EditTextPreference)findPreference(key);
|
||||||
|
pref.setSummary(getString(resId, pref.getText()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateSummary(String key, boolean changing) {
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (key.equals(Preferences.PREF_UPD_INTERVAL)) {
|
||||||
|
ListPreference pref = (ListPreference)findPreference(
|
||||||
|
Preferences.PREF_UPD_INTERVAL);
|
||||||
|
int interval = Integer.parseInt(pref.getValue());
|
||||||
|
Preference onlyOnWifi = findPreference(
|
||||||
|
Preferences.PREF_UPD_WIFI_ONLY);
|
||||||
|
onlyOnWifi.setEnabled(interval > 0);
|
||||||
|
if (interval == 0) {
|
||||||
|
pref.setSummary(R.string.update_interval_zero);
|
||||||
|
} else {
|
||||||
|
pref.setSummary(pref.getEntry());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_UPD_WIFI_ONLY)) {
|
||||||
|
onoffSummary(key, R.string.automatic_scan_wifi_on,
|
||||||
|
R.string.automatic_scan_wifi_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_UPD_NOTIFY)) {
|
||||||
|
onoffSummary(key, R.string.notify_on,
|
||||||
|
R.string.notify_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_UPD_HISTORY)) {
|
||||||
|
textSummary(key, R.string.update_history_summ);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_PERMISSIONS)) {
|
||||||
|
onoffSummary(key, R.string.showPermissions_on,
|
||||||
|
R.string.showPermissions_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_COMPACT_LAYOUT)) {
|
||||||
|
onoffSummary(key, R.string.compactlayout_on,
|
||||||
|
R.string.compactlayout_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_THEME)) {
|
||||||
|
entrySummary(key);
|
||||||
|
if (changing) {
|
||||||
|
result |= PreferencesActivity.RESULT_RESTART;
|
||||||
|
getActivity().setResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_INCOMP_VER)) {
|
||||||
|
onoffSummary(key, R.string.show_incompat_versions_on,
|
||||||
|
R.string.show_incompat_versions_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_ROOTED)) {
|
||||||
|
onoffSummary(key, R.string.rooted_on,
|
||||||
|
R.string.rooted_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_IGN_TOUCH)) {
|
||||||
|
onoffSummary(key, R.string.ignoreTouch_on,
|
||||||
|
R.string.ignoreTouch_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_LOCAL_REPO_BONJOUR)) {
|
||||||
|
onoffSummary(key, R.string.local_repo_bonjour_on,
|
||||||
|
R.string.local_repo_bonjour_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_LOCAL_REPO_NAME)) {
|
||||||
|
textSummary(key, R.string.local_repo_name_summary);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_LOCAL_REPO_HTTPS)) {
|
||||||
|
onoffSummary(key, R.string.local_repo_https_on,
|
||||||
|
R.string.local_repo_https_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_CACHE_APK)) {
|
||||||
|
onoffSummary(key, R.string.cache_downloaded_on,
|
||||||
|
R.string.cache_downloaded_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_EXPERT)) {
|
||||||
|
onoffSummary(key, R.string.expert_on,
|
||||||
|
R.string.expert_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_ROOT_INSTALLER)) {
|
||||||
|
onoffSummary(key, R.string.root_installer_on,
|
||||||
|
R.string.root_installer_off);
|
||||||
|
|
||||||
|
} else if (key.equals(Preferences.PREF_SYSTEM_INSTALLER)) {
|
||||||
|
onoffSummary(key, R.string.system_installer_on,
|
||||||
|
R.string.system_installer_off);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes RootInstaller preference. This method ensures that the preference can only be checked and persisted
|
||||||
|
* when the user grants root access for F-Droid.
|
||||||
|
*/
|
||||||
|
protected void initRootInstallerPreference() {
|
||||||
|
CheckBoxPreference pref = (CheckBoxPreference) findPreference(Preferences.PREF_ROOT_INSTALLER);
|
||||||
|
|
||||||
|
// we are handling persistence ourself!
|
||||||
|
pref.setPersistent(false);
|
||||||
|
|
||||||
|
pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
final CheckBoxPreference pref = (CheckBoxPreference) preference;
|
||||||
|
|
||||||
|
if (pref.isChecked()) {
|
||||||
|
CheckRootAsyncTask checkTask = new CheckRootAsyncTask(getActivity(), new CheckRootAsyncTask.CheckRootCallback() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRootCheck(boolean rootGranted) {
|
||||||
|
if (rootGranted) {
|
||||||
|
// root access granted
|
||||||
|
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
||||||
|
editor.putBoolean(Preferences.PREF_ROOT_INSTALLER, true);
|
||||||
|
editor.commit();
|
||||||
|
pref.setChecked(true);
|
||||||
|
} else {
|
||||||
|
// root access denied
|
||||||
|
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
||||||
|
editor.putBoolean(Preferences.PREF_ROOT_INSTALLER, false);
|
||||||
|
editor.commit();
|
||||||
|
pref.setChecked(false);
|
||||||
|
|
||||||
|
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
|
||||||
|
alertBuilder.setTitle(R.string.root_access_denied_title);
|
||||||
|
alertBuilder.setMessage(getActivity().getString(R.string.root_access_denied_body));
|
||||||
|
alertBuilder.setNeutralButton(android.R.string.ok, null);
|
||||||
|
alertBuilder.create().show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
checkTask.execute();
|
||||||
|
} else {
|
||||||
|
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
||||||
|
editor.putBoolean(Preferences.PREF_ROOT_INSTALLER, false);
|
||||||
|
editor.commit();
|
||||||
|
pref.setChecked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes SystemInstaller preference, which can only be enabled when F-Droid is installed as a system-app
|
||||||
|
*/
|
||||||
|
protected void initSystemInstallerPreference() {
|
||||||
|
CheckBoxPreference pref = (CheckBoxPreference) findPreference(Preferences.PREF_SYSTEM_INSTALLER);
|
||||||
|
|
||||||
|
// we are handling persistence ourself!
|
||||||
|
pref.setPersistent(false);
|
||||||
|
|
||||||
|
pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
final CheckBoxPreference pref = (CheckBoxPreference) preference;
|
||||||
|
|
||||||
|
if (pref.isChecked()) {
|
||||||
|
if (Installer.hasSystemPermissions(getActivity(), getActivity().getPackageManager())) {
|
||||||
|
// system-permission are granted, i.e. F-Droid is a system-app
|
||||||
|
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
||||||
|
editor.putBoolean(Preferences.PREF_SYSTEM_INSTALLER, true);
|
||||||
|
editor.commit();
|
||||||
|
pref.setChecked(true);
|
||||||
|
} else {
|
||||||
|
// system-permission not available
|
||||||
|
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
||||||
|
editor.putBoolean(Preferences.PREF_SYSTEM_INSTALLER, false);
|
||||||
|
editor.commit();
|
||||||
|
pref.setChecked(false);
|
||||||
|
|
||||||
|
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
|
||||||
|
alertBuilder.setTitle(R.string.system_permission_denied_title);
|
||||||
|
alertBuilder.setMessage(getActivity().getString(R.string.system_permission_denied_body));
|
||||||
|
alertBuilder.setNeutralButton(android.R.string.ok, null);
|
||||||
|
alertBuilder.create().show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
||||||
|
editor.putBoolean(Preferences.PREF_SYSTEM_INSTALLER, false);
|
||||||
|
editor.commit();
|
||||||
|
pref.setChecked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
for (String key : summariesToUpdate) {
|
||||||
|
updateSummary(key, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
initRootInstallerPreference();
|
||||||
|
initSystemInstallerPreference();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(
|
||||||
|
SharedPreferences sharedPreferences, String key) {
|
||||||
|
updateSummary(key, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -14,24 +14,25 @@ limitations under the License.
|
|||||||
|
|
||||||
package org.fdroid.fdroid.views.fragments;
|
package org.fdroid.fdroid.views.fragments;
|
||||||
|
|
||||||
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;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
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.text.TextUtils;
|
||||||
import android.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.*;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ListView;
|
||||||
import android.widget.SearchView.OnQueryTextListener;
|
import android.widget.SearchView.OnQueryTextListener;
|
||||||
|
import android.widget.SimpleCursorAdapter;
|
||||||
import android.widget.SimpleCursorAdapter.ViewBinder;
|
import android.widget.SimpleCursorAdapter.ViewBinder;
|
||||||
|
import android.widget.TextView;
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.data.InstalledAppProvider;
|
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||||
@ -41,10 +42,8 @@ import org.fdroid.fdroid.views.SelectLocalAppsActivity;
|
|||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
//TODO replace with appcompat-v7
|
|
||||||
@TargetApi(11)
|
|
||||||
public class SelectLocalAppsFragment extends ListFragment
|
public class SelectLocalAppsFragment extends ListFragment
|
||||||
implements LoaderCallbacks<Cursor>, OnQueryTextListener {
|
implements LoaderManager.LoaderCallbacks<Cursor>, OnQueryTextListener {
|
||||||
|
|
||||||
private PackageManager packageManager;
|
private PackageManager packageManager;
|
||||||
private Drawable defaultAppIcon;
|
private Drawable defaultAppIcon;
|
||||||
@ -95,7 +94,7 @@ public class SelectLocalAppsFragment extends ListFragment
|
|||||||
Drawable icon;
|
Drawable icon;
|
||||||
try {
|
try {
|
||||||
icon = packageManager.getApplicationIcon(packageName);
|
icon = packageManager.getApplicationIcon(packageName);
|
||||||
} catch (NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
icon = defaultAppIcon;
|
icon = defaultAppIcon;
|
||||||
}
|
}
|
||||||
iconView.setImageDrawable(icon);
|
iconView.setImageDrawable(icon);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user