Merge branch 'develop'
This commit is contained in:
commit
1673f6eaf8
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="de.danoeh.antennapod"
|
package="de.danoeh.antennapod"
|
||||||
android:versionCode="37"
|
android:versionCode="38"
|
||||||
android:versionName="0.9.9.0">
|
android:versionName="0.9.9.1">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
Change Log
|
Change Log
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
Version 0.9.9.1
|
||||||
|
---------------
|
||||||
|
* Several bugfixes and improvements
|
||||||
|
|
||||||
Version 0.9.9.0
|
Version 0.9.9.0
|
||||||
---------------
|
---------------
|
||||||
* New user interface
|
* New user interface
|
||||||
|
|
|
@ -41,9 +41,9 @@
|
||||||
<div id="header" align="center">
|
<div id="header" align="center">
|
||||||
<img src="logo.png" alt="Logo" width="100px" height="100px"/>
|
<img src="logo.png" alt="Logo" width="100px" height="100px"/>
|
||||||
|
|
||||||
<p>AntennaPod, Version 0.9.9.0</p>
|
<p>AntennaPod, Version 0.9.9.1</p>
|
||||||
|
|
||||||
<p>Copyright © 2012 Daniel Oeh</p>
|
<p>Copyright © 2014 Daniel Oeh</p>
|
||||||
|
|
||||||
<p>Licensed under the MIT License <a href="LICENSE.html">(View)</a></p>
|
<p>Licensed under the MIT License <a href="LICENSE.html">(View)</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
10
build.gradle
10
build.gradle
|
@ -3,7 +3,7 @@ buildscript {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:0.10.+'
|
classpath 'com.android.tools.build:gradle:0.11.+'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apply plugin: 'android'
|
apply plugin: 'android'
|
||||||
|
@ -28,16 +28,18 @@ dependencies {
|
||||||
compile 'commons-io:commons-io:2.4'
|
compile 'commons-io:commons-io:2.4'
|
||||||
compile 'com.nineoldandroids:library:2.4.0'
|
compile 'com.nineoldandroids:library:2.4.0'
|
||||||
compile project(':submodules:dslv:library')
|
compile project(':submodules:dslv:library')
|
||||||
|
|
||||||
|
compile 'com.jayway.android.robotium:robotium-solo:5.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 19
|
compileSdkVersion 19
|
||||||
buildToolsVersion "19.0.3"
|
buildToolsVersion "19.1.0"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 10
|
minSdkVersion 10
|
||||||
targetSdkVersion 19
|
targetSdkVersion 19
|
||||||
testPackageName "de.test.antennapod"
|
testApplicationId "de.test.antennapod"
|
||||||
testInstrumentationRunner "instrumentationTest.de.test.antennapod.AntennaPodTestRunner"
|
testInstrumentationRunner "instrumentationTest.de.test.antennapod.AntennaPodTestRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +82,7 @@ android {
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
packageNameSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
runProguard true
|
runProguard true
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -5,7 +5,7 @@
|
||||||
<groupId>de.danoeh</groupId>
|
<groupId>de.danoeh</groupId>
|
||||||
<artifactId>antennapod</artifactId>
|
<artifactId>antennapod</artifactId>
|
||||||
<packaging>apk</packaging>
|
<packaging>apk</packaging>
|
||||||
<version>0.9.9.0</version>
|
<version>0.9.9.1</version>
|
||||||
<name>AntennaPod</name>
|
<name>AntennaPod</name>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
-printmapping out.map
|
|
||||||
-renamesourcefileattribute SourceFile
|
-renamesourcefileattribute SourceFile
|
||||||
-keepattributes SourceFile,LineNumberTable
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
-dontpreverify
|
-dontpreverify
|
||||||
-repackageclasses ''
|
-repackageclasses ''
|
||||||
-allowaccessmodification
|
-allowaccessmodification
|
||||||
-optimizations !code/simplification/arithmetic
|
|
||||||
-keepattributes *Annotation*
|
-keepattributes *Annotation*
|
||||||
|
|
||||||
#-injars libs/presto_client-0.8.5.jar
|
#-injars libs/presto_client-0.8.5.jar
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginBottom="4dp"
|
|
||||||
android:textColor="?android:attr/textColorTertiary"
|
android:textColor="?android:attr/textColorTertiary"
|
||||||
android:textSize="@dimen/text_size_micro"/>
|
android:textSize="@dimen/text_size_micro"/>
|
||||||
|
|
||||||
|
@ -28,7 +27,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/txtvPublished"
|
android:layout_below="@id/txtvPublished"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginRight="4dp"
|
|
||||||
style="@style/AntennaPod.TextView.ListItemPrimaryTitle"/>
|
style="@style/AntennaPod.TextView.ListItemPrimaryTitle"/>
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,7 +57,6 @@
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_below="@id/txtvItemname"
|
android:layout_below="@id/txtvItemname"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:layout_marginBottom="2dp"
|
|
||||||
android:textColor="?android:attr/textColorTertiary"
|
android:textColor="?android:attr/textColorTertiary"
|
||||||
android:textSize="@dimen/text_size_micro"/>
|
android:textSize="@dimen/text_size_micro"/>
|
||||||
|
|
||||||
|
@ -77,22 +74,11 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/statusUnread"
|
android:id="@+id/statusUnread"
|
||||||
android:contentDescription="@string/status_unread_label"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="18dp"
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/AntennaPod.TextView.UnreadIndicator"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"/>
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="@color/status_unread"
|
|
||||||
android:gravity="center"
|
|
||||||
android:minWidth="@dimen/status_indicator_width"
|
|
||||||
android:text="@string/new_label"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="@dimen/text_size_micro"
|
|
||||||
android:textStyle="bold"/>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
<?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="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:paddingRight="8dp" >
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imgvFeedimage"
|
|
||||||
android:contentDescription="@string/cover_label"
|
|
||||||
android:layout_width="@dimen/thumbnail_length"
|
|
||||||
android:layout_height="@dimen/thumbnail_length"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginRight="4dip"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:cropToPadding="true"
|
|
||||||
android:scaleType="fitXY" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/lEpisodeCounts"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:orientation="vertical" >
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/lNewStatusLabel"
|
|
||||||
android:contentDescription="@string/new_episodes_count_label"
|
|
||||||
android:layout_width="@dimen/status_indicator_width"
|
|
||||||
android:layout_height="0dip"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@color/status_unread" >
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginRight="4dp"
|
|
||||||
android:src="@drawable/white_circle"
|
|
||||||
tools:ignore="ContentDescription"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvNewEps"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginLeft="4dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:minEms="2"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="@dimen/text_size_micro"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/lProgressStatusLabel"
|
|
||||||
android:contentDescription="@string/in_progress_episodes_count_label"
|
|
||||||
android:layout_width="@dimen/status_indicator_width"
|
|
||||||
android:layout_height="0dip"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@color/ics_gray" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvProgressEps"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:background="@color/status_progress"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:minEms="2"
|
|
||||||
android:paddingLeft="4dp"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="@dimen/text_size_micro"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="10dp"
|
|
||||||
android:layout_height="8dp"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginRight="2dp"
|
|
||||||
android:layout_marginLeft="2dp"
|
|
||||||
android:src="@drawable/av_play_dark"
|
|
||||||
tools:ignore="ContentDescription"/>
|
|
||||||
</RelativeLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_toLeftOf="@id/lEpisodeCounts"
|
|
||||||
android:layout_toRightOf="@id/imgvFeedimage"
|
|
||||||
android:orientation="vertical" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvFeedname"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
|
||||||
android:textSize="@dimen/text_size_small" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvNumEpisodes"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
|
||||||
android:textSize="@dimen/text_size_micro" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvLastUpdate"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
|
||||||
android:textSize="@dimen/text_size_micro" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
|
@ -1,138 +0,0 @@
|
||||||
<?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="wrap_content"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imgvFeedimage"
|
|
||||||
android:contentDescription="@string/cover_label"
|
|
||||||
android:layout_width="@dimen/thumbnail_length"
|
|
||||||
android:layout_height="@dimen/thumbnail_length"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:cropToPadding="true"
|
|
||||||
android:scaleType="fitXY"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/lEpisodeCounts"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_alignRight="@id/imgvFeedimage"
|
|
||||||
android:layout_below="@id/imgvFeedimage"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/lNewStatusLabel"
|
|
||||||
android:contentDescription="@string/new_episodes_count_label"
|
|
||||||
android:layout_width="@dimen/status_indicator_width"
|
|
||||||
android:layout_height="0dip"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@color/status_unread">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginRight="4dp"
|
|
||||||
android:src="@drawable/white_circle"
|
|
||||||
tools:ignore="ContentDescription"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvNewEps"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginLeft="4dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:minEms="2"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="@dimen/text_size_micro"
|
|
||||||
android:textStyle="bold"/>
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/lProgressStatusLabel"
|
|
||||||
android:contentDescription="@string/in_progress_episodes_count_label"
|
|
||||||
android:layout_width="@dimen/status_indicator_width"
|
|
||||||
android:layout_height="0dip"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@color/ics_gray">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvProgressEps"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:background="@color/status_progress"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:minEms="2"
|
|
||||||
android:paddingLeft="4dp"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="@dimen/text_size_micro"
|
|
||||||
android:textStyle="bold"/>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="10dp"
|
|
||||||
android:layout_height="8dp"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginLeft="2dp"
|
|
||||||
android:layout_marginRight="2dp"
|
|
||||||
android:src="@drawable/av_play_dark"
|
|
||||||
tools:ignore="ContentDescription"/>
|
|
||||||
</RelativeLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignLeft="@id/imgvFeedimage"
|
|
||||||
android:layout_below="@id/imgvFeedimage"
|
|
||||||
android:layout_toLeftOf="@id/lEpisodeCounts"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvFeedname"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:lines="1"
|
|
||||||
android:textSize="@dimen/text_size_small"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
|
||||||
android:textStyle="bold"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvLastUpdate"
|
|
||||||
android:lines="2"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="@dimen/text_size_micro"
|
|
||||||
android:textColor="?android:attr/textColorTertiary"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtvNumEpisodes"
|
|
||||||
android:lines="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:textSize="@dimen/text_size_micro"
|
|
||||||
android:textColor="?android:attr/textColorTertiary"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
|
@ -24,6 +24,7 @@
|
||||||
android:id="@+id/txtvTitle"
|
android:id="@+id/txtvTitle"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:singleLine="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="@dimen/text_size_navdrawer"
|
android:textSize="@dimen/text_size_navdrawer"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imgvCover"
|
android:id="@+id/imgvCover"
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
android:id="@+id/txtvTitle"
|
android:id="@+id/txtvTitle"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:singleLine="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="@dimen/text_size_navdrawer"
|
android:textSize="@dimen/text_size_navdrawer"
|
||||||
|
@ -35,4 +36,18 @@
|
||||||
android:layout_marginRight="48dp"
|
android:layout_marginRight="48dp"
|
||||||
android:layout_toRightOf="@id/imgvCover"
|
android:layout_toRightOf="@id/imgvCover"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtvCount"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:lines="1"
|
||||||
|
android:textColor="?android:attr/textColorTertiary"
|
||||||
|
android:textSize="@dimen/text_size_navdrawer"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:layout_marginTop="14dp"
|
||||||
|
android:layout_marginBottom="14dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerVertical="true"/>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
|
@ -6,11 +6,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<android.support.v4.widget.SwipeRefreshLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:id="@+id/swipeRefreshLayout">
|
|
||||||
|
|
||||||
<com.mobeta.android.dslv.DragSortListView
|
<com.mobeta.android.dslv.DragSortListView
|
||||||
android:id="@android:id/list"
|
android:id="@android:id/list"
|
||||||
android:scrollbarStyle="outsideOverlay"
|
android:scrollbarStyle="outsideOverlay"
|
||||||
|
@ -29,8 +24,6 @@
|
||||||
dslv:float_background_color="?attr/dragview_float_background"
|
dslv:float_background_color="?attr/dragview_float_background"
|
||||||
dslv:use_default_controller="true"/>
|
dslv:use_default_controller="true"/>
|
||||||
|
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@id/android:empty"
|
android:id="@id/android:empty"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -6,29 +6,25 @@
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imgvImage"
|
||||||
|
android:contentDescription="@string/cover_label"
|
||||||
|
android:layout_width="@dimen/thumbnail_length_itemlist"
|
||||||
|
android:layout_height="@dimen/thumbnail_length_itemlist"
|
||||||
|
android:scaleType="centerCrop"/>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginRight="8dp">
|
android:layout_margin="4dp">
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imgvImage"
|
|
||||||
android:contentDescription="@string/cover_label"
|
|
||||||
android:layout_width="@dimen/thumbnail_length_itemlist"
|
|
||||||
android:layout_height="@dimen/thumbnail_length_itemlist"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:scaleType="centerCrop"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtvPublished"
|
android:id="@+id/txtvPublished"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_toRightOf="@id/imgvImage"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
|
@ -40,18 +36,24 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/txtvPublished"
|
android:layout_below="@id/txtvPublished"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:layout_toRightOf="@id/imgvImage"
|
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
style="@style/AntennaPod.TextView.ListItemPrimaryTitle"/>
|
style="@style/AntennaPod.TextView.ListItemPrimaryTitle"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/statusUnread"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
style="@style/AntennaPod.TextView.UnreadIndicator"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_toRightOf="@id/imgvImage"
|
android:layout_alignParentLeft="true"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
@ -74,7 +76,6 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_toLeftOf="@id/imgvInPlaylist"
|
android:layout_toLeftOf="@id/imgvInPlaylist"
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:layout_alignParentLeft="true"/>
|
android:layout_alignParentLeft="true"/>
|
||||||
|
|
||||||
|
@ -83,8 +84,6 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_toLeftOf="@id/imgvInPlaylist"
|
android:layout_toLeftOf="@id/imgvInPlaylist"
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:textColor="?android:attr/textColorTertiary"
|
android:textColor="?android:attr/textColorTertiary"
|
||||||
android:textSize="@dimen/text_size_micro"/>
|
android:textSize="@dimen/text_size_micro"/>
|
||||||
|
|
|
@ -15,30 +15,27 @@
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
android:contentDescription="@string/drag_handle_content_description"/>
|
android:contentDescription="@string/drag_handle_content_description"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imgvImage"
|
||||||
|
android:contentDescription="@string/cover_label"
|
||||||
|
android:layout_width="@dimen/thumbnail_length_queue_item"
|
||||||
|
android:layout_height="@dimen/thumbnail_length_queue_item"
|
||||||
|
android:scaleType="centerCrop"/>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginRight="8dp">
|
android:layout_margin="8dp">
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imgvImage"
|
|
||||||
android:contentDescription="@string/cover_label"
|
|
||||||
android:layout_width="@dimen/thumbnail_length_queue_item"
|
|
||||||
android:layout_height="@dimen/thumbnail_length_queue_item"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:scaleType="centerCrop"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtvTitle"
|
android:id="@+id/txtvTitle"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="4dp"
|
||||||
android:layout_toRightOf="@id/imgvImage"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:lines="2"
|
android:lines="2"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
@ -49,7 +46,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_toRightOf="@id/imgvImage"
|
android:layout_alignParentLeft="true"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
@ -57,6 +54,14 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtvPosition"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:textColor="?android:attr/textColorTertiary"
|
||||||
|
android:textSize="@dimen/text_size_micro"/>
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/pbar_download_progress"
|
android:id="@+id/pbar_download_progress"
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
@ -65,8 +70,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_toRightOf="@id/txtvPosition"/>
|
||||||
android:layout_alignParentLeft="true"/>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -3,13 +3,6 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:custom="http://schemas.android.com/apk/res-auto">
|
xmlns:custom="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/mark_all_read_item"
|
|
||||||
android:title="@string/mark_all_read_label"
|
|
||||||
android:menuCategory="container"
|
|
||||||
custom:showAsAction="ifRoom|collapseActionView"
|
|
||||||
android:icon="?attr/navigation_accept"/>
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/refresh_item"
|
android:id="@+id/refresh_item"
|
||||||
android:title="@string/refresh_label"
|
android:title="@string/refresh_label"
|
||||||
|
@ -17,6 +10,13 @@
|
||||||
custom:showAsAction="ifRoom|collapseActionView"
|
custom:showAsAction="ifRoom|collapseActionView"
|
||||||
android:icon="?attr/navigation_refresh"/>
|
android:icon="?attr/navigation_refresh"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/mark_all_read_item"
|
||||||
|
android:title="@string/mark_all_read_label"
|
||||||
|
android:menuCategory="container"
|
||||||
|
custom:showAsAction="collapseActionView"
|
||||||
|
android:icon="?attr/navigation_accept"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/episode_filter_item"
|
android:id="@+id/episode_filter_item"
|
||||||
android:title="@string/episode_filter_label"
|
android:title="@string/episode_filter_label"
|
||||||
|
|
|
@ -289,7 +289,7 @@
|
||||||
<!--Directory chooser-->
|
<!--Directory chooser-->
|
||||||
<string name="selected_folder_label">Ausgewählter Ordner</string>
|
<string name="selected_folder_label">Ausgewählter Ordner</string>
|
||||||
<string name="create_folder_label">Neuer Ordner</string>
|
<string name="create_folder_label">Neuer Ordner</string>
|
||||||
<string name="choose_data_directory">Wähle Datenordner</string>
|
<string name="choose_data_directory">Datenordner auswählen</string>
|
||||||
<string name="create_folder_msg">Neuen Ordner mit Namen \"%1$s\" erstellen?</string>
|
<string name="create_folder_msg">Neuen Ordner mit Namen \"%1$s\" erstellen?</string>
|
||||||
<string name="create_folder_success">Neuer Ordner angelegt</string>
|
<string name="create_folder_success">Neuer Ordner angelegt</string>
|
||||||
<string name="create_folder_error_no_write_access">Kann in diesem Ordner nicht schreiben</string>
|
<string name="create_folder_error_no_write_access">Kann in diesem Ordner nicht schreiben</string>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<item type="layout" name="feedlist_item">@layout/feedlist_item_grid</item>
|
|
||||||
|
|
||||||
</resources>
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="AntennaPod.TextView.UnreadIndicator" parent="@android:style/TextAppearance.Small">
|
||||||
|
<item name="android:textSize">@dimen/text_size_micro</item>
|
||||||
|
<item name="android:textColor">@color/new_indicator_green</item>
|
||||||
|
<item name="android:text">@string/new_label</item>
|
||||||
|
<item name="android:textAllCaps">true</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
|
@ -3,19 +3,26 @@
|
||||||
<!--Activitiy and fragment titles-->
|
<!--Activitiy and fragment titles-->
|
||||||
<string name="app_name">AntennaPod</string>
|
<string name="app_name">AntennaPod</string>
|
||||||
<string name="feeds_label">订阅</string>
|
<string name="feeds_label">订阅</string>
|
||||||
|
<string name="add_feed_label">添加博客</string>
|
||||||
<string name="podcasts_label">播客</string>
|
<string name="podcasts_label">播客</string>
|
||||||
<string name="episodes_label">曲目</string>
|
<string name="episodes_label">曲目</string>
|
||||||
|
<string name="new_episodes_label">新曲目</string>
|
||||||
|
<string name="all_episodes_label">所有曲目</string>
|
||||||
<string name="new_label">最新</string>
|
<string name="new_label">最新</string>
|
||||||
<string name="waiting_list_label">等待列表</string>
|
<string name="waiting_list_label">等待列表</string>
|
||||||
<string name="settings_label">设置</string>
|
<string name="settings_label">设置</string>
|
||||||
<string name="add_new_feed_label">添加播客</string>
|
<string name="add_new_feed_label">添加播客</string>
|
||||||
<string name="downloads_label">下载</string>
|
<string name="downloads_label">下载</string>
|
||||||
|
<string name="downloads_running_label">正在运行</string>
|
||||||
|
<string name="downloads_completed_label">已完成</string>
|
||||||
<string name="downloads_log_label">日志</string>
|
<string name="downloads_log_label">日志</string>
|
||||||
<string name="cancel_download_label">取消下载</string>
|
<string name="cancel_download_label">取消下载</string>
|
||||||
<string name="playback_history_label">播放历史</string>
|
<string name="playback_history_label">播放历史</string>
|
||||||
<string name="gpodnet_main_label">gpodder.net</string>
|
<string name="gpodnet_main_label">gpodder.net</string>
|
||||||
<string name="gpodnet_auth_label">gpodder.net 登录</string>
|
<string name="gpodnet_auth_label">gpodder.net 登录</string>
|
||||||
<!--New episodes fragment-->
|
<!--New episodes fragment-->
|
||||||
|
<string name="recently_published_episodes_label">最近发布</string>
|
||||||
|
<string name="episode_filter_label">仅显示新曲目</string>
|
||||||
<!--Main activity-->
|
<!--Main activity-->
|
||||||
<string name="drawer_open">打开菜单</string>
|
<string name="drawer_open">打开菜单</string>
|
||||||
<string name="drawer_close">关闭菜单</string>
|
<string name="drawer_close">关闭菜单</string>
|
||||||
|
@ -53,9 +60,11 @@
|
||||||
<!--'Add Feed' Activity labels-->
|
<!--'Add Feed' Activity labels-->
|
||||||
<string name="feedurl_label">订阅 URL</string>
|
<string name="feedurl_label">订阅 URL</string>
|
||||||
<string name="txtvfeedurl_label">添加播客 URL</string>
|
<string name="txtvfeedurl_label">添加播客 URL</string>
|
||||||
|
<string name="podcastdirectories_descr">您可以在 gpodder.net 通过名称、类别或热门来搜索新播客</string>
|
||||||
<string name="browse_gpoddernet_label">浏览 gpodder.net</string>
|
<string name="browse_gpoddernet_label">浏览 gpodder.net</string>
|
||||||
<!--Actions on feeds-->
|
<!--Actions on feeds-->
|
||||||
<string name="mark_all_read_label">全部标识已读</string>
|
<string name="mark_all_read_label">全部标识已读</string>
|
||||||
|
<string name="mark_all_read_msg">将所有曲目标记为已读</string>
|
||||||
<string name="show_info_label">查看信息</string>
|
<string name="show_info_label">查看信息</string>
|
||||||
<string name="remove_feed_label">删除播客</string>
|
<string name="remove_feed_label">删除播客</string>
|
||||||
<string name="share_link_label">分享网站链接</string>
|
<string name="share_link_label">分享网站链接</string>
|
||||||
|
@ -68,6 +77,7 @@
|
||||||
<string name="pause_label">暂停</string>
|
<string name="pause_label">暂停</string>
|
||||||
<string name="stream_label">流媒体</string>
|
<string name="stream_label">流媒体</string>
|
||||||
<string name="remove_label">删除</string>
|
<string name="remove_label">删除</string>
|
||||||
|
<string name="remove_episode_lable">移除曲目</string>
|
||||||
<string name="mark_read_label">标记已读</string>
|
<string name="mark_read_label">标记已读</string>
|
||||||
<string name="mark_unread_label">标记未读</string>
|
<string name="mark_unread_label">标记未读</string>
|
||||||
<string name="add_to_queue_label">添加到播放列表</string>
|
<string name="add_to_queue_label">添加到播放列表</string>
|
||||||
|
@ -91,6 +101,7 @@
|
||||||
<string name="download_error_unsupported_type">未提供的订阅类型</string>
|
<string name="download_error_unsupported_type">未提供的订阅类型</string>
|
||||||
<string name="download_error_connection_error">链接错误</string>
|
<string name="download_error_connection_error">链接错误</string>
|
||||||
<string name="download_error_unknown_host">未知主机</string>
|
<string name="download_error_unknown_host">未知主机</string>
|
||||||
|
<string name="download_error_unauthorized">认证错误</string>
|
||||||
<string name="cancel_all_downloads_label">取消所有下载</string>
|
<string name="cancel_all_downloads_label">取消所有下载</string>
|
||||||
<string name="download_cancelled_msg">已取消下载</string>
|
<string name="download_cancelled_msg">已取消下载</string>
|
||||||
<string name="download_report_title">下载完成</string>
|
<string name="download_report_title">下载完成</string>
|
||||||
|
@ -99,6 +110,7 @@
|
||||||
<string name="download_error_request_error">请求出错</string>
|
<string name="download_error_request_error">请求出错</string>
|
||||||
<string name="download_error_db_access">数据库访问错误</string>
|
<string name="download_error_db_access">数据库访问错误</string>
|
||||||
<string name="downloads_left">\u0020 下载剩余</string>
|
<string name="downloads_left">\u0020 下载剩余</string>
|
||||||
|
<string name="downloads_processing">正在处理下载</string>
|
||||||
<string name="download_notification_title">下载播客数据</string>
|
<string name="download_notification_title">下载播客数据</string>
|
||||||
<string name="download_report_content">%1$d 下载成功, %2$d 失败</string>
|
<string name="download_report_content">%1$d 下载成功, %2$d 失败</string>
|
||||||
<string name="download_log_title_unknown">未知标题</string>
|
<string name="download_log_title_unknown">未知标题</string>
|
||||||
|
@ -106,6 +118,8 @@
|
||||||
<string name="download_type_media">媒体文件</string>
|
<string name="download_type_media">媒体文件</string>
|
||||||
<string name="download_type_image">图片</string>
|
<string name="download_type_image">图片</string>
|
||||||
<string name="download_request_error_dialog_message_prefix">尝试下载文件:\u0020 时出错</string>
|
<string name="download_request_error_dialog_message_prefix">尝试下载文件:\u0020 时出错</string>
|
||||||
|
<string name="authentication_notification_title">需要认证</string>
|
||||||
|
<string name="authentication_notification_msg">您所请求的资源需要用户名和密码</string>
|
||||||
<!--Mediaplayer messages-->
|
<!--Mediaplayer messages-->
|
||||||
<string name="player_error_msg">错误!</string>
|
<string name="player_error_msg">错误!</string>
|
||||||
<string name="player_stopped_msg">没有可播放媒体</string>
|
<string name="player_stopped_msg">没有可播放媒体</string>
|
||||||
|
@ -293,7 +307,10 @@
|
||||||
<string name="in_queue_label">曲目已经在播放列表中</string>
|
<string name="in_queue_label">曲目已经在播放列表中</string>
|
||||||
<string name="new_episodes_count_label">新曲目数</string>
|
<string name="new_episodes_count_label">新曲目数</string>
|
||||||
<string name="in_progress_episodes_count_label">已收听曲目数</string>
|
<string name="in_progress_episodes_count_label">已收听曲目数</string>
|
||||||
|
<string name="drag_handle_content_description">拖动以变更本项目的位置</string>
|
||||||
<!--Feed information screen-->
|
<!--Feed information screen-->
|
||||||
<string name="authentication_label">验证</string>
|
<string name="authentication_label">验证</string>
|
||||||
|
<string name="authentication_descr">给本播客及曲目变更用户名及密码</string>
|
||||||
<!--AntennaPodSP-->
|
<!--AntennaPodSP-->
|
||||||
|
<string name="sp_apps_importing_feeds_msg">正在从选定的应用中导入订阅...</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -9,14 +9,13 @@
|
||||||
<color name="actionbar_gray">#DDDDDD</color>
|
<color name="actionbar_gray">#DDDDDD</color>
|
||||||
<color name="download_success_green">#669900</color>
|
<color name="download_success_green">#669900</color>
|
||||||
<color name="download_failed_red">#CC0000</color>
|
<color name="download_failed_red">#CC0000</color>
|
||||||
<color name="status_unread">#E099CC00</color>
|
|
||||||
<color name="status_progress">#E033B5E5</color>
|
<color name="status_progress">#E033B5E5</color>
|
||||||
<color name="status_playing">#E0EE5F52</color>
|
<color name="status_playing">#E0EE5F52</color>
|
||||||
<color name="overlay_dark">#262C31</color>
|
<color name="overlay_dark">#262C31</color>
|
||||||
<color name="overlay_light">#DDDDDD</color>
|
<color name="overlay_light">#DDDDDD</color>
|
||||||
<color name="swipe_refresh_secondary_color_light">#EDEDED</color>
|
<color name="swipe_refresh_secondary_color_light">#EDEDED</color>
|
||||||
<color name="swipe_refresh_secondary_color_dark">#060708</color>
|
<color name="swipe_refresh_secondary_color_dark">#060708</color>
|
||||||
|
<color name="new_indicator_green">#669900</color>
|
||||||
|
|
||||||
<!-- Use Gingerbread-orange -->
|
<!-- Use Gingerbread-orange -->
|
||||||
<color name="selection_background_color_dark">#FEBB20</color>
|
<color name="selection_background_color_dark">#FEBB20</color>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<dimen name="text_size_medium">18sp</dimen>
|
<dimen name="text_size_medium">18sp</dimen>
|
||||||
<dimen name="text_size_large">22sp</dimen>
|
<dimen name="text_size_large">22sp</dimen>
|
||||||
<dimen name="status_indicator_width">32dp</dimen>
|
<dimen name="status_indicator_width">32dp</dimen>
|
||||||
<dimen name="thumbnail_length_itemlist">80dp</dimen>
|
<dimen name="thumbnail_length_itemlist">85dp</dimen>
|
||||||
<dimen name="thumbnail_length_queue_item">70dp</dimen>
|
<dimen name="thumbnail_length_queue_item">70dp</dimen>
|
||||||
<dimen name="thumbnail_length_downloaded_item">70dp</dimen>
|
<dimen name="thumbnail_length_downloaded_item">70dp</dimen>
|
||||||
<dimen name="thumbnail_length_onlinefeedview">110dp</dimen>
|
<dimen name="thumbnail_length_onlinefeedview">110dp</dimen>
|
||||||
|
|
|
@ -127,7 +127,7 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AntennaPod.TextView.ListItemPrimaryTitle" parent="@android:style/TextAppearance.Small">
|
<style name="AntennaPod.TextView.ListItemPrimaryTitle" parent="@android:style/TextAppearance.Small">
|
||||||
<item name="android:textSize">15sp</item>
|
<item name="android:textSize">14sp</item>
|
||||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
<item name="android:lines">2</item>
|
<item name="android:lines">2</item>
|
||||||
<item name="android:ellipsize">end</item>
|
<item name="android:ellipsize">end</item>
|
||||||
|
@ -139,4 +139,10 @@
|
||||||
<item name="android:maxLines">2</item>
|
<item name="android:maxLines">2</item>
|
||||||
<item name="android:ellipsize">end</item>
|
<item name="android:ellipsize">end</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="AntennaPod.TextView.UnreadIndicator" parent="@android:style/TextAppearance.Small">
|
||||||
|
<item name="android:textSize">@dimen/text_size_micro</item>
|
||||||
|
<item name="android:textColor">@color/new_indicator_green</item>
|
||||||
|
<item name="android:text">@string/new_label</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -2,5 +2,6 @@ package de.danoeh.antennapod;
|
||||||
|
|
||||||
public final class AppConfig {
|
public final class AppConfig {
|
||||||
/** Should be used when setting User-Agent header for HTTP-requests. */
|
/** Should be used when setting User-Agent header for HTTP-requests. */
|
||||||
public final static String USER_AGENT = "AntennaPod/0.9.9.0";
|
public final static String USER_AGENT = "AntennaPod/0.9.9.1";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,6 @@ import de.danoeh.antennapod.storage.DBReader;
|
||||||
import de.danoeh.antennapod.util.playback.ExternalMedia;
|
import de.danoeh.antennapod.util.playback.ExternalMedia;
|
||||||
import de.danoeh.antennapod.util.playback.Playable;
|
import de.danoeh.antennapod.util.playback.Playable;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity for playing audio files.
|
* Activity for playing audio files.
|
||||||
*/
|
*/
|
||||||
|
@ -624,20 +622,20 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Feed> feeds;
|
private DBReader.NavDrawerData navDrawerData;
|
||||||
private AsyncTask<Void, Void, List<Feed>> loadTask;
|
private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
|
||||||
|
|
||||||
private void loadData() {
|
private void loadData() {
|
||||||
loadTask = new AsyncTask<Void, Void, List<Feed>>() {
|
loadTask = new AsyncTask<Void, Void, DBReader.NavDrawerData>() {
|
||||||
@Override
|
@Override
|
||||||
protected List<Feed> doInBackground(Void... params) {
|
protected DBReader.NavDrawerData doInBackground(Void... params) {
|
||||||
return DBReader.getFeedList(AudioplayerActivity.this);
|
return DBReader.getNavDrawerData(AudioplayerActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(List<Feed> result) {
|
protected void onPostExecute(DBReader.NavDrawerData result) {
|
||||||
super.onPostExecute(result);
|
super.onPostExecute(result);
|
||||||
feeds = result;
|
navDrawerData = result;
|
||||||
if (navAdapter != null) {
|
if (navAdapter != null) {
|
||||||
navAdapter.notifyDataSetChanged();
|
navAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
@ -667,8 +665,8 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
||||||
private final NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
|
private final NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
if (feeds != null) {
|
if (navDrawerData != null) {
|
||||||
return feeds.size();
|
return navDrawerData.feeds.size();
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -676,8 +674,8 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Feed getItem(int position) {
|
public Feed getItem(int position) {
|
||||||
if (feeds != null && position < feeds.size()) {
|
if (navDrawerData != null && position < navDrawerData.feeds.size()) {
|
||||||
return feeds.get(position);
|
return navDrawerData.feeds.get(position);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -687,5 +685,15 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
||||||
public int getSelectedItemIndex() {
|
public int getSelectedItemIndex() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getQueueSize() {
|
||||||
|
return (navDrawerData != null) ? navDrawerData.queueSize : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfUnreadItems() {
|
||||||
|
return (navDrawerData != null) ? navDrawerData.numUnreadItems : 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,7 @@ public class FeedInfoActivity extends ActionBarActivity {
|
||||||
menu.findItem(R.id.support_item).setVisible(
|
menu.findItem(R.id.support_item).setVisible(
|
||||||
feed != null && feed.getPaymentLink() != null);
|
feed != null && feed.getPaymentLink() != null);
|
||||||
menu.findItem(R.id.share_link_item).setVisible(feed != null &&feed.getLink() != null);
|
menu.findItem(R.id.share_link_item).setVisible(feed != null &&feed.getLink() != null);
|
||||||
|
menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,10 +39,11 @@ public class MainActivity extends ActionBarActivity {
|
||||||
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED
|
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED
|
||||||
| EventDistributor.DOWNLOAD_QUEUED
|
| EventDistributor.DOWNLOAD_QUEUED
|
||||||
| EventDistributor.FEED_LIST_UPDATE
|
| EventDistributor.FEED_LIST_UPDATE
|
||||||
| EventDistributor.UNREAD_ITEMS_UPDATE;
|
| EventDistributor.UNREAD_ITEMS_UPDATE
|
||||||
|
| EventDistributor.QUEUE_UPDATE;
|
||||||
|
|
||||||
private static final String PREF_NAME = "MainActivityPrefs";
|
public static final String PREF_NAME = "MainActivityPrefs";
|
||||||
private static final String PREF_IS_FIRST_LAUNCH = "prefMainActivityIsFirstLaunch";
|
public static final String PREF_IS_FIRST_LAUNCH = "prefMainActivityIsFirstLaunch";
|
||||||
|
|
||||||
public static final String EXTRA_NAV_INDEX = "nav_index";
|
public static final String EXTRA_NAV_INDEX = "nav_index";
|
||||||
public static final String EXTRA_NAV_TYPE = "nav_type";
|
public static final String EXTRA_NAV_TYPE = "nav_type";
|
||||||
|
@ -147,7 +148,7 @@ public class MainActivity extends ActionBarActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Feed> getFeeds() {
|
public List<Feed> getFeeds() {
|
||||||
return feeds;
|
return (navDrawerData != null) ? navDrawerData.feeds : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadFragment(int viewType, int relPos, Bundle args) {
|
private void loadFragment(int viewType, int relPos, Bundle args) {
|
||||||
|
@ -207,9 +208,9 @@ public class MainActivity extends ActionBarActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadFeedFragment(long feedID) {
|
public void loadFeedFragment(long feedID) {
|
||||||
if (feeds != null) {
|
if (navDrawerData != null) {
|
||||||
for (int i = 0; i < feeds.size(); i++) {
|
for (int i = 0; i < navDrawerData.feeds.size(); i++) {
|
||||||
if (feeds.get(i).getId() == feedID) {
|
if (navDrawerData.feeds.get(i).getId() == feedID) {
|
||||||
loadFragment(NavListAdapter.VIEW_TYPE_SUBSCRIPTION, i, null);
|
loadFragment(NavListAdapter.VIEW_TYPE_SUBSCRIPTION, i, null);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -279,7 +280,7 @@ public class MainActivity extends ActionBarActivity {
|
||||||
EventDistributor.getInstance().register(contentUpdate);
|
EventDistributor.getInstance().register(contentUpdate);
|
||||||
|
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
if (feeds != null && intent.hasExtra(EXTRA_NAV_INDEX) && intent.hasExtra(EXTRA_NAV_TYPE)) {
|
if (navDrawerData != null && intent.hasExtra(EXTRA_NAV_INDEX) && intent.hasExtra(EXTRA_NAV_TYPE)) {
|
||||||
handleNavIntent();
|
handleNavIntent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,15 +323,15 @@ public class MainActivity extends ActionBarActivity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Feed> feeds;
|
private DBReader.NavDrawerData navDrawerData;
|
||||||
private AsyncTask<Void, Void, List<Feed>> loadTask;
|
private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
|
||||||
private int selectedNavListIndex = 0;
|
private int selectedNavListIndex = 0;
|
||||||
|
|
||||||
private NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
|
private NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
if (feeds != null) {
|
if (navDrawerData != null) {
|
||||||
return feeds.size();
|
return navDrawerData.feeds.size();
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -338,8 +339,8 @@ public class MainActivity extends ActionBarActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Feed getItem(int position) {
|
public Feed getItem(int position) {
|
||||||
if (feeds != null && position < feeds.size()) {
|
if (navDrawerData != null && position < navDrawerData.feeds.size()) {
|
||||||
return feeds.get(position);
|
return navDrawerData.feeds.get(position);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -350,23 +351,33 @@ public class MainActivity extends ActionBarActivity {
|
||||||
return selectedNavListIndex;
|
return selectedNavListIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getQueueSize() {
|
||||||
|
return (navDrawerData != null) ? navDrawerData.queueSize : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfUnreadItems() {
|
||||||
|
return (navDrawerData != null) ? navDrawerData.numUnreadItems : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private void loadData() {
|
private void loadData() {
|
||||||
cancelLoadTask();
|
cancelLoadTask();
|
||||||
loadTask = new AsyncTask<Void, Void, List<Feed>>() {
|
loadTask = new AsyncTask<Void, Void, DBReader.NavDrawerData>() {
|
||||||
@Override
|
@Override
|
||||||
protected List<Feed> doInBackground(Void... params) {
|
protected DBReader.NavDrawerData doInBackground(Void... params) {
|
||||||
return DBReader.getFeedList(MainActivity.this);
|
return DBReader.getNavDrawerData(MainActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(List<Feed> result) {
|
protected void onPostExecute(DBReader.NavDrawerData result) {
|
||||||
super.onPostExecute(result);
|
super.onPostExecute(navDrawerData);
|
||||||
boolean handleIntent = (feeds == null);
|
boolean handleIntent = (navDrawerData == null);
|
||||||
|
|
||||||
feeds = result;
|
navDrawerData = result;
|
||||||
navAdapter.notifyDataSetChanged();
|
navAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
if (handleIntent) {
|
if (handleIntent) {
|
||||||
|
|
|
@ -61,6 +61,8 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity {
|
||||||
private Map<String, String> alternateFeedUrls;
|
private Map<String, String> alternateFeedUrls;
|
||||||
private Downloader downloader;
|
private Downloader downloader;
|
||||||
|
|
||||||
|
private boolean isPaused;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
setTheme(UserPreferences.getTheme());
|
setTheme(UserPreferences.getTheme());
|
||||||
|
@ -96,6 +98,18 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
isPaused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
isPaused = true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
@ -126,9 +140,11 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity {
|
||||||
if (status.isSuccessful()) {
|
if (status.isSuccessful()) {
|
||||||
parseFeed();
|
parseFeed();
|
||||||
} else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
|
} else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
|
||||||
Dialog dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this,
|
if (!isFinishing() && !isPaused) {
|
||||||
R.string.authentication_notification_title, downloader.getDownloadRequest().getSource());
|
Dialog dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this,
|
||||||
dialog.show();
|
R.string.authentication_notification_title, downloader.getDownloadRequest().getSource());
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
String errorMsg = status.getReason().getErrorString(
|
String errorMsg = status.getReason().getErrorString(
|
||||||
OnlineFeedViewActivity.this);
|
OnlineFeedViewActivity.this);
|
||||||
|
@ -276,32 +292,30 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showErrorDialog(String errorMsg) {
|
private void showErrorDialog(String errorMsg) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
if (!isFinishing() && !isPaused) {
|
||||||
builder.setTitle(R.string.error_label);
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
if (errorMsg != null) {
|
builder.setTitle(R.string.error_label);
|
||||||
builder.setMessage(getString(R.string.error_msg_prefix) + errorMsg);
|
if (errorMsg != null) {
|
||||||
} else {
|
builder.setMessage(getString(R.string.error_msg_prefix) + errorMsg);
|
||||||
builder.setMessage(R.string.error_msg_prefix);
|
} else {
|
||||||
}
|
builder.setMessage(R.string.error_msg_prefix);
|
||||||
builder.setNeutralButton(android.R.string.ok,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
dialog.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
builder.setOnCancelListener(new OnCancelListener() {
|
|
||||||
@Override
|
|
||||||
public void onCancel(DialogInterface dialog) {
|
|
||||||
setResult(RESULT_ERROR);
|
|
||||||
finish();
|
|
||||||
}
|
}
|
||||||
});
|
builder.setNeutralButton(android.R.string.ok,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
if (!isFinishing()) {
|
@Override
|
||||||
builder.show();
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
builder.setOnCancelListener(new OnCancelListener() {
|
||||||
|
@Override
|
||||||
|
public void onCancel(DialogInterface dialog) {
|
||||||
|
setResult(RESULT_ERROR);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import android.preference.Preference;
|
||||||
import android.preference.Preference.OnPreferenceChangeListener;
|
import android.preference.Preference.OnPreferenceChangeListener;
|
||||||
import android.preference.Preference.OnPreferenceClickListener;
|
import android.preference.Preference.OnPreferenceClickListener;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
|
import android.support.v4.app.NavUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
@ -46,7 +47,7 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
private static final String PREF_FLATTR_THIS_APP = "prefFlattrThisApp";
|
private static final String PREF_FLATTR_THIS_APP = "prefFlattrThisApp";
|
||||||
private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
|
private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
|
||||||
private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
|
private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
|
||||||
private static final String PREF_AUTO_FLATTR = "pref_auto_flattr";
|
private static final String PREF_AUTO_FLATTR = "pref_auto_flattr";
|
||||||
private static final String PREF_OPML_EXPORT = "prefOpmlExport";
|
private static final String PREF_OPML_EXPORT = "prefOpmlExport";
|
||||||
private static final String PREF_ABOUT = "prefAbout";
|
private static final String PREF_ABOUT = "prefAbout";
|
||||||
private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
|
private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
|
||||||
|
@ -89,7 +90,8 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
findPreference(PREF_FLATTR_REVOKE).setOnPreferenceClickListener(
|
findPreference(PREF_FLATTR_REVOKE).setOnPreferenceClickListener(
|
||||||
new OnPreferenceClickListener() {
|
new OnPreferenceClickListener() {
|
||||||
|
@ -101,7 +103,8 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
findPreference(PREF_ABOUT).setOnPreferenceClickListener(
|
findPreference(PREF_ABOUT).setOnPreferenceClickListener(
|
||||||
new OnPreferenceClickListener() {
|
new OnPreferenceClickListener() {
|
||||||
|
@ -113,7 +116,8 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
findPreference(PREF_OPML_EXPORT).setOnPreferenceClickListener(
|
findPreference(PREF_OPML_EXPORT).setOnPreferenceClickListener(
|
||||||
new OnPreferenceClickListener() {
|
new OnPreferenceClickListener() {
|
||||||
|
@ -125,7 +129,8 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
findPreference(PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
|
findPreference(PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
|
||||||
new OnPreferenceClickListener() {
|
new OnPreferenceClickListener() {
|
||||||
|
@ -135,10 +140,12 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
startActivityForResult(
|
startActivityForResult(
|
||||||
new Intent(PreferenceActivity.this,
|
new Intent(PreferenceActivity.this,
|
||||||
DirectoryChooserActivity.class),
|
DirectoryChooserActivity.class),
|
||||||
DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED);
|
DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
findPreference(UserPreferences.PREF_THEME)
|
findPreference(UserPreferences.PREF_THEME)
|
||||||
.setOnPreferenceChangeListener(
|
.setOnPreferenceChangeListener(
|
||||||
new OnPreferenceChangeListener() {
|
new OnPreferenceChangeListener() {
|
||||||
|
@ -153,18 +160,19 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
startActivity(i);
|
startActivity(i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
findPreference(UserPreferences.PREF_ENABLE_AUTODL)
|
findPreference(UserPreferences.PREF_ENABLE_AUTODL)
|
||||||
.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
if (newValue instanceof Boolean) {
|
if (newValue instanceof Boolean) {
|
||||||
findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled((Boolean) newValue);
|
findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled((Boolean) newValue);
|
||||||
setSelectedNetworksEnabled((Boolean) newValue && UserPreferences.isEnableAutodownloadWifiFilter());
|
setSelectedNetworksEnabled((Boolean) newValue && UserPreferences.isEnableAutodownloadWifiFilter());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER)
|
findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER)
|
||||||
.setOnPreferenceChangeListener(
|
.setOnPreferenceChangeListener(
|
||||||
new OnPreferenceChangeListener() {
|
new OnPreferenceChangeListener() {
|
||||||
|
@ -179,7 +187,8 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE)
|
findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE)
|
||||||
.setOnPreferenceChangeListener(
|
.setOnPreferenceChangeListener(
|
||||||
new OnPreferenceChangeListener() {
|
new OnPreferenceChangeListener() {
|
||||||
|
@ -190,7 +199,8 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
findPreference(PREF_PLAYBACK_SPEED_LAUNCHER)
|
findPreference(PREF_PLAYBACK_SPEED_LAUNCHER)
|
||||||
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -343,12 +353,14 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
|
Intent destIntent = new Intent(this, MainActivity.class);
|
||||||
|
destIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
startActivity(destIntent);
|
||||||
finish();
|
finish();
|
||||||
break;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -389,7 +401,8 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
String key = preference.getKey();
|
String key = preference.getKey();
|
||||||
ArrayList<String> prefValuesList = new ArrayList<String>(
|
ArrayList<String> prefValuesList = new ArrayList<String>(
|
||||||
Arrays.asList(UserPreferences
|
Arrays.asList(UserPreferences
|
||||||
.getAutodownloadSelectedNetworks()));
|
.getAutodownloadSelectedNetworks())
|
||||||
|
);
|
||||||
boolean newValue = ((CheckBoxPreference) preference)
|
boolean newValue = ((CheckBoxPreference) preference)
|
||||||
.isChecked();
|
.isChecked();
|
||||||
if (BuildConfig.DEBUG)
|
if (BuildConfig.DEBUG)
|
||||||
|
@ -406,8 +419,9 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
|
|
||||||
UserPreferences.setAutodownloadSelectedNetworks(
|
UserPreferences.setAutodownloadSelectedNetworks(
|
||||||
PreferenceActivity.this, prefValuesList
|
PreferenceActivity.this, prefValuesList
|
||||||
.toArray(new String[prefValuesList
|
.toArray(new String[prefValuesList
|
||||||
.size()]));
|
.size()])
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -461,7 +475,17 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
.setBackgroundDrawable(
|
.setBackgroundDrawable(
|
||||||
this.getWindow().getDecorView()
|
this.getWindow().getDecorView()
|
||||||
.getBackground().getConstantState()
|
.getBackground().getConstantState()
|
||||||
.newDrawable());
|
.newDrawable()
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
// The default back button behavior has to be overwritten because changing the theme clears the back stack
|
||||||
|
Intent destIntent = new Intent(this, MainActivity.class);
|
||||||
|
destIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
startActivity(destIntent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package de.danoeh.antennapod.adapter;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.feed.FeedItem;
|
||||||
|
import de.danoeh.antennapod.feed.FeedMedia;
|
||||||
|
import de.danoeh.antennapod.util.Converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for adapters
|
||||||
|
*/
|
||||||
|
public class AdapterUtils {
|
||||||
|
|
||||||
|
private AdapterUtils() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the contents of the TextView that shows the current playback position and the ProgressBar.
|
||||||
|
*/
|
||||||
|
public static void updateEpisodePlaybackProgress(FeedItem item, Resources res, TextView txtvPos, ProgressBar episodeProgress) {
|
||||||
|
FeedMedia media = item.getMedia();
|
||||||
|
episodeProgress.setVisibility(View.GONE);
|
||||||
|
if (media == null) {
|
||||||
|
txtvPos.setVisibility(View.GONE);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
txtvPos.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FeedItem.State state = item.getState();
|
||||||
|
if (state == FeedItem.State.PLAYING
|
||||||
|
|| state == FeedItem.State.IN_PROGRESS) {
|
||||||
|
if (media.getDuration() > 0) {
|
||||||
|
episodeProgress.setVisibility(View.VISIBLE);
|
||||||
|
episodeProgress
|
||||||
|
.setProgress((int) (((double) media
|
||||||
|
.getPosition()) / media.getDuration() * 100));
|
||||||
|
txtvPos.setText(Converter
|
||||||
|
.getDurationStringLong(media.getDuration()
|
||||||
|
- media.getPosition()));
|
||||||
|
}
|
||||||
|
} else if (!media.isDownloaded()) {
|
||||||
|
txtvPos.setText(res.getString(
|
||||||
|
R.string.size_prefix)
|
||||||
|
+ Converter.byteToString(media.getSize()));
|
||||||
|
} else {
|
||||||
|
txtvPos.setText(res.getString(
|
||||||
|
R.string.length_prefix)
|
||||||
|
+ Converter.getDurationStringLong(media
|
||||||
|
.getDuration()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -134,28 +134,8 @@ public class FeedItemlistAdapter extends BaseAdapter {
|
||||||
holder.lenSize.setVisibility(View.INVISIBLE);
|
holder.lenSize.setVisibility(View.INVISIBLE);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (state == FeedItem.State.PLAYING
|
AdapterUtils.updateEpisodePlaybackProgress(item, context.getResources(), holder.lenSize, holder.episodeProgress);
|
||||||
|| state == FeedItem.State.IN_PROGRESS) {
|
|
||||||
if (media.getDuration() > 0) {
|
|
||||||
holder.episodeProgress
|
|
||||||
.setProgress((int) (((double) media
|
|
||||||
.getPosition()) / media.getDuration() * 100));
|
|
||||||
holder.lenSize.setText(Converter
|
|
||||||
.getDurationStringLong(media.getDuration()
|
|
||||||
- media.getPosition()));
|
|
||||||
}
|
|
||||||
} else if (!media.isDownloaded()) {
|
|
||||||
holder.lenSize.setText(context.getString(
|
|
||||||
R.string.size_prefix)
|
|
||||||
+ Converter.byteToString(media.getSize()));
|
|
||||||
} else {
|
|
||||||
holder.lenSize.setText(context.getString(
|
|
||||||
R.string.length_prefix)
|
|
||||||
+ Converter.getDurationStringLong(media
|
|
||||||
.getDuration()));
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.lenSize.setVisibility(View.VISIBLE);
|
|
||||||
if (((ItemAccess) itemAccess).isInQueue(item)) {
|
if (((ItemAccess) itemAccess).isInQueue(item)) {
|
||||||
holder.inPlaylist.setVisibility(View.VISIBLE);
|
holder.inPlaylist.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -166,9 +146,6 @@ public class FeedItemlistAdapter extends BaseAdapter {
|
||||||
item.getMedia())) {
|
item.getMedia())) {
|
||||||
holder.episodeProgress.setVisibility(View.VISIBLE);
|
holder.episodeProgress.setVisibility(View.VISIBLE);
|
||||||
holder.episodeProgress.setProgress(((ItemAccess) itemAccess).getItemDownloadProgressPercent(item));
|
holder.episodeProgress.setProgress(((ItemAccess) itemAccess).getItemDownloadProgressPercent(item));
|
||||||
} else if (!(state == FeedItem.State.IN_PROGRESS
|
|
||||||
|| state == FeedItem.State.PLAYING)) {
|
|
||||||
holder.episodeProgress.setVisibility(View.GONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedArray typeDrawables = context.obtainStyledAttributes(
|
TypedArray typeDrawables = context.obtainStyledAttributes(
|
||||||
|
|
|
@ -1,174 +0,0 @@
|
||||||
package de.danoeh.antennapod.adapter;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.text.format.DateUtils;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.BaseAdapter;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import de.danoeh.antennapod.R;
|
|
||||||
import de.danoeh.antennapod.asynctask.ImageLoader;
|
|
||||||
import de.danoeh.antennapod.feed.Feed;
|
|
||||||
import de.danoeh.antennapod.storage.DownloadRequester;
|
|
||||||
import de.danoeh.antennapod.storage.FeedItemStatistics;
|
|
||||||
import de.danoeh.antennapod.util.ThemeUtils;
|
|
||||||
|
|
||||||
public class FeedlistAdapter extends BaseAdapter {
|
|
||||||
private static final String TAG = "FeedlistAdapter";
|
|
||||||
|
|
||||||
private Context context;
|
|
||||||
protected ItemAccess itemAccess;
|
|
||||||
|
|
||||||
private int selectedItemIndex;
|
|
||||||
private ImageLoader imageLoader;
|
|
||||||
public static final int SELECTION_NONE = -1;
|
|
||||||
|
|
||||||
public FeedlistAdapter(Context context, ItemAccess itemAccess) {
|
|
||||||
super();
|
|
||||||
if (context == null) {
|
|
||||||
throw new IllegalArgumentException("context must not be null");
|
|
||||||
}
|
|
||||||
if (itemAccess == null) {
|
|
||||||
throw new IllegalArgumentException("itemAccess must not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.context = context;
|
|
||||||
this.itemAccess = itemAccess;
|
|
||||||
selectedItemIndex = SELECTION_NONE;
|
|
||||||
imageLoader = ImageLoader.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
|
||||||
final Holder holder;
|
|
||||||
final Feed feed = getItem(position);
|
|
||||||
final FeedItemStatistics feedItemStatistics = itemAccess.getFeedItemStatistics(position);
|
|
||||||
|
|
||||||
// Inflate Layout
|
|
||||||
if (convertView == null) {
|
|
||||||
holder = new Holder();
|
|
||||||
LayoutInflater inflater = (LayoutInflater) context
|
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
|
|
||||||
convertView = inflater.inflate(R.layout.feedlist_item, null);
|
|
||||||
holder.title = (TextView) convertView
|
|
||||||
.findViewById(R.id.txtvFeedname);
|
|
||||||
|
|
||||||
holder.newEpisodes = (TextView) convertView
|
|
||||||
.findViewById(R.id.txtvNewEps);
|
|
||||||
holder.inProgressEpisodes = (TextView) convertView
|
|
||||||
.findViewById(R.id.txtvProgressEps);
|
|
||||||
holder.newEpisodesLabel = (View) convertView
|
|
||||||
.findViewById(R.id.lNewStatusLabel);
|
|
||||||
holder.inProgressEpisodesLabel = (View) convertView
|
|
||||||
.findViewById(R.id.lProgressStatusLabel);
|
|
||||||
holder.image = (ImageView) convertView
|
|
||||||
.findViewById(R.id.imgvFeedimage);
|
|
||||||
holder.lastUpdate = (TextView) convertView
|
|
||||||
.findViewById(R.id.txtvLastUpdate);
|
|
||||||
holder.numberOfEpisodes = (TextView) convertView
|
|
||||||
.findViewById(R.id.txtvNumEpisodes);
|
|
||||||
convertView.setTag(holder);
|
|
||||||
} else {
|
|
||||||
holder = (Holder) convertView.getTag();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position == selectedItemIndex) {
|
|
||||||
convertView.setBackgroundColor(convertView.getResources().getColor(
|
|
||||||
ThemeUtils.getSelectionBackgroundColor()));
|
|
||||||
} else {
|
|
||||||
convertView.setBackgroundResource(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.title.setText(feed.getTitle());
|
|
||||||
|
|
||||||
if (feedItemStatistics != null) {
|
|
||||||
if (DownloadRequester.getInstance().isDownloadingFile(feed)) {
|
|
||||||
holder.lastUpdate.setText(R.string.refreshing_label);
|
|
||||||
} else {
|
|
||||||
if (feedItemStatistics.lastUpdateKnown()) {
|
|
||||||
holder.lastUpdate.setText(convertView.getResources().getString(
|
|
||||||
R.string.most_recent_prefix)
|
|
||||||
+ DateUtils.getRelativeTimeSpanString(
|
|
||||||
feedItemStatistics.getLastUpdate().getTime(),
|
|
||||||
System.currentTimeMillis(), 0, 0));
|
|
||||||
} else {
|
|
||||||
holder.lastUpdate.setText("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
holder.numberOfEpisodes.setText(feedItemStatistics.getNumberOfItems()
|
|
||||||
+ convertView.getResources()
|
|
||||||
.getString(R.string.episodes_suffix));
|
|
||||||
|
|
||||||
if (feedItemStatistics.getNumberOfNewItems() > 0) {
|
|
||||||
holder.newEpisodes.setText(Integer.toString(feedItemStatistics.getNumberOfNewItems()));
|
|
||||||
holder.newEpisodesLabel.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
holder.newEpisodesLabel.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (feedItemStatistics.getNumberOfInProgressItems() > 0) {
|
|
||||||
holder.inProgressEpisodes
|
|
||||||
.setText(Integer.toString(feedItemStatistics.getNumberOfInProgressItems()));
|
|
||||||
holder.inProgressEpisodesLabel.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
holder.inProgressEpisodesLabel.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final String imageUrl = (feed.getImage() != null && feed.getImage().isDownloaded()) ? feed.getImage()
|
|
||||||
.getFile_url() : null;
|
|
||||||
imageLoader.loadThumbnailBitmap(
|
|
||||||
feed.getImage(),
|
|
||||||
holder.image,
|
|
||||||
(int) convertView.getResources().getDimension(
|
|
||||||
R.dimen.thumbnail_length));
|
|
||||||
|
|
||||||
return convertView;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Holder {
|
|
||||||
TextView title;
|
|
||||||
TextView lastUpdate;
|
|
||||||
TextView numberOfEpisodes;
|
|
||||||
TextView newEpisodes;
|
|
||||||
TextView inProgressEpisodes;
|
|
||||||
ImageView image;
|
|
||||||
View newEpisodesLabel;
|
|
||||||
View inProgressEpisodesLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSelectedItemIndex() {
|
|
||||||
return selectedItemIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectedItemIndex(int selectedItemIndex) {
|
|
||||||
this.selectedItemIndex = selectedItemIndex;
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
return itemAccess.getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Feed getItem(int position) {
|
|
||||||
return itemAccess.getItem(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getItemId(int position) {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ItemAccess {
|
|
||||||
int getCount();
|
|
||||||
|
|
||||||
Feed getItem(int position);
|
|
||||||
|
|
||||||
FeedItemStatistics getFeedItemStatistics(int position);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -36,9 +36,9 @@ public class NavListAdapter extends BaseAdapter {
|
||||||
this.itemAccess = itemAccess;
|
this.itemAccess = itemAccess;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
TypedArray ta = context.obtainStyledAttributes(new int[] {R.attr.ic_new, R.attr.stat_playlist,
|
TypedArray ta = context.obtainStyledAttributes(new int[]{R.attr.ic_new, R.attr.stat_playlist,
|
||||||
R.attr.av_download, R.attr.device_access_time, R.attr.content_new});
|
R.attr.av_download, R.attr.device_access_time, R.attr.content_new});
|
||||||
drawables = new Drawable[] {ta.getDrawable(0), ta.getDrawable(1), ta.getDrawable(2),
|
drawables = new Drawable[]{ta.getDrawable(0), ta.getDrawable(1), ta.getDrawable(2),
|
||||||
ta.getDrawable(3), ta.getDrawable(4)};
|
ta.getDrawable(3), ta.getDrawable(4)};
|
||||||
ta.recycle();
|
ta.recycle();
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,7 @@ public class NavListAdapter extends BaseAdapter {
|
||||||
convertView = inflater.inflate(R.layout.nav_listitem, null);
|
convertView = inflater.inflate(R.layout.nav_listitem, null);
|
||||||
|
|
||||||
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
|
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
|
||||||
|
holder.count = (TextView) convertView.findViewById(R.id.txtvCount);
|
||||||
holder.image = (ImageView) convertView.findViewById(R.id.imgvCover);
|
holder.image = (ImageView) convertView.findViewById(R.id.imgvCover);
|
||||||
convertView.setTag(holder);
|
convertView.setTag(holder);
|
||||||
} else {
|
} else {
|
||||||
|
@ -120,6 +121,27 @@ public class NavListAdapter extends BaseAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.title.setText(title);
|
holder.title.setText(title);
|
||||||
|
|
||||||
|
if (NAV_TITLES[position] == R.string.queue_label) {
|
||||||
|
int queueSize = itemAccess.getQueueSize();
|
||||||
|
if (queueSize > 0) {
|
||||||
|
holder.count.setVisibility(View.VISIBLE);
|
||||||
|
holder.count.setText(String.valueOf(queueSize));
|
||||||
|
} else {
|
||||||
|
holder.count.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
} else if (NAV_TITLES[position] == R.string.all_episodes_label) {
|
||||||
|
int unreadItems = itemAccess.getNumberOfUnreadItems();
|
||||||
|
if (unreadItems > 0) {
|
||||||
|
holder.count.setVisibility(View.VISIBLE);
|
||||||
|
holder.count.setText(String.valueOf(unreadItems));
|
||||||
|
} else {
|
||||||
|
holder.count.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
holder.count.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
holder.image.setImageDrawable(drawables[position]);
|
holder.image.setImageDrawable(drawables[position]);
|
||||||
|
|
||||||
return convertView;
|
return convertView;
|
||||||
|
@ -174,6 +196,7 @@ public class NavListAdapter extends BaseAdapter {
|
||||||
|
|
||||||
static class NavHolder {
|
static class NavHolder {
|
||||||
TextView title;
|
TextView title;
|
||||||
|
TextView count;
|
||||||
ImageView image;
|
ImageView image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +216,10 @@ public class NavListAdapter extends BaseAdapter {
|
||||||
public Feed getItem(int position);
|
public Feed getItem(int position);
|
||||||
|
|
||||||
public int getSelectedItemIndex();
|
public int getSelectedItemIndex();
|
||||||
|
|
||||||
|
public int getQueueSize();
|
||||||
|
|
||||||
|
public int getNumberOfUnreadItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ public class NewEpisodesListAdapter extends BaseAdapter {
|
||||||
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
|
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
|
||||||
holder.pubDate = (TextView) convertView
|
holder.pubDate = (TextView) convertView
|
||||||
.findViewById(R.id.txtvPublished);
|
.findViewById(R.id.txtvPublished);
|
||||||
|
holder.statusUnread = convertView.findViewById(R.id.statusUnread);
|
||||||
holder.butSecondary = (ImageButton) convertView
|
holder.butSecondary = (ImageButton) convertView
|
||||||
.findViewById(R.id.butSecondaryAction);
|
.findViewById(R.id.butSecondaryAction);
|
||||||
holder.queueStatus = (ImageView) convertView
|
holder.queueStatus = (ImageView) convertView
|
||||||
|
@ -81,6 +82,11 @@ public class NewEpisodesListAdapter extends BaseAdapter {
|
||||||
|
|
||||||
holder.title.setText(item.getTitle());
|
holder.title.setText(item.getTitle());
|
||||||
holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_SHOW_DATE));
|
holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_SHOW_DATE));
|
||||||
|
if (item.isRead()) {
|
||||||
|
holder.statusUnread.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
holder.statusUnread.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
FeedMedia media = item.getMedia();
|
FeedMedia media = item.getMedia();
|
||||||
if (media != null) {
|
if (media != null) {
|
||||||
|
@ -140,6 +146,7 @@ public class NewEpisodesListAdapter extends BaseAdapter {
|
||||||
static class Holder {
|
static class Holder {
|
||||||
TextView title;
|
TextView title;
|
||||||
TextView pubDate;
|
TextView pubDate;
|
||||||
|
View statusUnread;
|
||||||
ImageView queueStatus;
|
ImageView queueStatus;
|
||||||
ImageView imageView;
|
ImageView imageView;
|
||||||
ProgressBar downloadProgress;
|
ProgressBar downloadProgress;
|
||||||
|
|
|
@ -61,7 +61,8 @@ public class QueueListAdapter extends BaseAdapter {
|
||||||
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
|
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
|
||||||
holder.butSecondary = (ImageButton) convertView
|
holder.butSecondary = (ImageButton) convertView
|
||||||
.findViewById(R.id.butSecondaryAction);
|
.findViewById(R.id.butSecondaryAction);
|
||||||
holder.downloadProgress = (ProgressBar) convertView
|
holder.position = (TextView) convertView.findViewById(R.id.txtvPosition);
|
||||||
|
holder.progress = (ProgressBar) convertView
|
||||||
.findViewById(R.id.pbar_download_progress);
|
.findViewById(R.id.pbar_download_progress);
|
||||||
holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage);
|
holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage);
|
||||||
convertView.setTag(holder);
|
convertView.setTag(holder);
|
||||||
|
@ -71,20 +72,17 @@ public class QueueListAdapter extends BaseAdapter {
|
||||||
|
|
||||||
holder.title.setText(item.getTitle());
|
holder.title.setText(item.getTitle());
|
||||||
|
|
||||||
|
AdapterUtils.updateEpisodePlaybackProgress(item, context.getResources(), holder.position, holder.progress);
|
||||||
|
|
||||||
FeedMedia media = item.getMedia();
|
FeedMedia media = item.getMedia();
|
||||||
if (media != null) {
|
if (media != null) {
|
||||||
final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
|
final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
|
||||||
|
|
||||||
|
|
||||||
if (isDownloadingMedia) {
|
|
||||||
holder.downloadProgress.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
holder.downloadProgress.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
if (!media.isDownloaded()) {
|
if (!media.isDownloaded()) {
|
||||||
if (isDownloadingMedia) {
|
if (isDownloadingMedia) {
|
||||||
// item is being downloaded
|
// item is being downloaded
|
||||||
holder.downloadProgress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
|
holder.progress.setVisibility(View.VISIBLE);
|
||||||
|
holder.progress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +114,8 @@ public class QueueListAdapter extends BaseAdapter {
|
||||||
static class Holder {
|
static class Holder {
|
||||||
TextView title;
|
TextView title;
|
||||||
ImageView imageView;
|
ImageView imageView;
|
||||||
ProgressBar downloadProgress;
|
TextView position;
|
||||||
|
ProgressBar progress;
|
||||||
ImageButton butSecondary;
|
ImageButton butSecondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,10 @@ public class ImageDiskCache {
|
||||||
* The image will be stored in the thumbnail cache.
|
* The image will be stored in the thumbnail cache.
|
||||||
*/
|
*/
|
||||||
public void loadThumbnailBitmap(final String url, final ImageView target, final int length) {
|
public void loadThumbnailBitmap(final String url, final ImageView target, final int length) {
|
||||||
|
if (url == null) {
|
||||||
|
Log.w(TAG, "loadThumbnailBitmap: Call was ignored because url = null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
final ImageLoader il = ImageLoader.getInstance();
|
final ImageLoader il = ImageLoader.getInstance();
|
||||||
target.setTag(R.id.image_disk_cache_key, url);
|
target.setTag(R.id.image_disk_cache_key, url);
|
||||||
if (diskCache != null) {
|
if (diskCache != null) {
|
||||||
|
@ -217,6 +221,10 @@ public class ImageDiskCache {
|
||||||
* The image will be stored in the cover cache.
|
* The image will be stored in the cover cache.
|
||||||
*/
|
*/
|
||||||
public void loadCoverBitmap(final String url, final ImageView target, final int length) {
|
public void loadCoverBitmap(final String url, final ImageView target, final int length) {
|
||||||
|
if (url == null) {
|
||||||
|
Log.w(TAG, "loadCoverBitmap: Call was ignored because url = null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
final ImageLoader il = ImageLoader.getInstance();
|
final ImageLoader il = ImageLoader.getInstance();
|
||||||
target.setTag(R.id.image_disk_cache_key, url);
|
target.setTag(R.id.image_disk_cache_key, url);
|
||||||
if (diskCache != null) {
|
if (diskCache != null) {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.support.v7.widget.SearchView;
|
import android.support.v7.widget.SearchView;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
|
@ -55,7 +54,6 @@ public class NewEpisodesFragment extends Fragment {
|
||||||
|
|
||||||
|
|
||||||
private DragSortListView listView;
|
private DragSortListView listView;
|
||||||
private SwipeRefreshLayout swipeRefreshLayout;
|
|
||||||
private NewEpisodesListAdapter listAdapter;
|
private NewEpisodesListAdapter listAdapter;
|
||||||
private TextView txtvEmpty;
|
private TextView txtvEmpty;
|
||||||
private ProgressBar progLoading;
|
private ProgressBar progLoading;
|
||||||
|
@ -202,7 +200,6 @@ public class NewEpisodesFragment extends Fragment {
|
||||||
|
|
||||||
View root = inflater.inflate(R.layout.new_episodes_fragment, container, false);
|
View root = inflater.inflate(R.layout.new_episodes_fragment, container, false);
|
||||||
|
|
||||||
swipeRefreshLayout = (SwipeRefreshLayout) root.findViewById(R.id.swipeRefreshLayout);
|
|
||||||
listView = (DragSortListView) root.findViewById(android.R.id.list);
|
listView = (DragSortListView) root.findViewById(android.R.id.list);
|
||||||
txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
|
txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
|
||||||
progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
|
progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
|
||||||
|
@ -220,16 +217,6 @@ public class NewEpisodesFragment extends Fragment {
|
||||||
});
|
});
|
||||||
|
|
||||||
final int secondColor = (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) ? R.color.swipe_refresh_secondary_color_dark : R.color.swipe_refresh_secondary_color_light;
|
final int secondColor = (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) ? R.color.swipe_refresh_secondary_color_dark : R.color.swipe_refresh_secondary_color_light;
|
||||||
swipeRefreshLayout.setColorScheme(R.color.bright_blue, secondColor, R.color.bright_blue, secondColor);
|
|
||||||
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
|
||||||
@Override
|
|
||||||
public void onRefresh() {
|
|
||||||
List<Feed> feeds = ((MainActivity) getActivity()).getFeeds();
|
|
||||||
if (feeds != null) {
|
|
||||||
DBTasks.refreshAllFeeds(getActivity(), feeds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!itemsLoaded) {
|
if (!itemsLoaded) {
|
||||||
progLoading.setVisibility(View.VISIBLE);
|
progLoading.setVisibility(View.VISIBLE);
|
||||||
|
@ -331,18 +318,9 @@ public class NewEpisodesFragment extends Fragment {
|
||||||
if (!viewsCreated) {
|
if (!viewsCreated) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
((ActionBarActivity) getActivity())
|
||||||
if (DownloadService.isRunning
|
.setSupportProgressBarIndeterminateVisibility(DownloadService.isRunning
|
||||||
&& DownloadRequester.getInstance().isDownloadingFeeds()) {
|
&& DownloadRequester.getInstance().isDownloadingFeeds());
|
||||||
swipeRefreshLayout.setRefreshing(true);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
swipeRefreshLayout.setRefreshing(false);
|
|
||||||
|
|
||||||
// if case other fragments have set this to true, this fragment should remove the progress indicator
|
|
||||||
((ActionBarActivity) getActivity())
|
|
||||||
.setSupportProgressBarIndeterminateVisibility(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||||
|
|
|
@ -890,6 +890,7 @@ public class DownloadService extends Service {
|
||||||
if (successful) {
|
if (successful) {
|
||||||
return savedFeed;
|
return savedFeed;
|
||||||
} else {
|
} else {
|
||||||
|
numberOfDownloads.decrementAndGet();
|
||||||
saveDownloadStatus(new DownloadStatus(savedFeed,
|
saveDownloadStatus(new DownloadStatus(savedFeed,
|
||||||
savedFeed.getHumanReadableIdentifier(), reason, successful,
|
savedFeed.getHumanReadableIdentifier(), reason, successful,
|
||||||
reasonDetailed));
|
reasonDetailed));
|
||||||
|
|
|
@ -541,6 +541,7 @@ public class PlaybackService extends Service {
|
||||||
(nextMedia.getMediaType() == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO);
|
(nextMedia.getMediaType() == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO);
|
||||||
} else {
|
} else {
|
||||||
sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0);
|
sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0);
|
||||||
|
mediaPlayer.stop();
|
||||||
//stopSelf();
|
//stopSelf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,8 @@ public class PlaybackServiceMediaPlayer {
|
||||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
||||||
if (BuildConfig.DEBUG) Log.d(TAG, "Rejected execution of runnable");
|
if (BuildConfig.DEBUG) Log.d(TAG, "Rejected execution of runnable");
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
mediaPlayer = null;
|
mediaPlayer = null;
|
||||||
statusBeforeSeeking = null;
|
statusBeforeSeeking = null;
|
||||||
|
@ -150,6 +151,8 @@ public class PlaybackServiceMediaPlayer {
|
||||||
if (media != null) {
|
if (media != null) {
|
||||||
if (!forceReset && media.getIdentifier().equals(playable.getIdentifier())) {
|
if (!forceReset && media.getIdentifier().equals(playable.getIdentifier())) {
|
||||||
// episode is already playing -> ignore method call
|
// episode is already playing -> ignore method call
|
||||||
|
if (BuildConfig.DEBUG)
|
||||||
|
Log.d(TAG, "Method call to playMediaObject was ignored: media file already playing.");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// stop playback of this episode
|
// stop playback of this episode
|
||||||
|
@ -284,7 +287,8 @@ public class PlaybackServiceMediaPlayer {
|
||||||
reinit();
|
reinit();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (BuildConfig.DEBUG) Log.d(TAG, "Ignoring call to pause: Player is in " + playerStatus + " state");
|
if (BuildConfig.DEBUG)
|
||||||
|
Log.d(TAG, "Ignoring call to pause: Player is in " + playerStatus + " state");
|
||||||
}
|
}
|
||||||
|
|
||||||
playerLock.unlock();
|
playerLock.unlock();
|
||||||
|
@ -385,9 +389,10 @@ public class PlaybackServiceMediaPlayer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seeks to the specified position. If the PSMP object is in an invalid state, this method will do nothing.
|
* Seeks to the specified position. If the PSMP object is in an invalid state, this method will do nothing.
|
||||||
|
*
|
||||||
* @param t The position to seek to in milliseconds. t < 0 will be interpreted as t = 0
|
* @param t The position to seek to in milliseconds. t < 0 will be interpreted as t = 0
|
||||||
* <p/>
|
* <p/>
|
||||||
* This method is executed on the caller's thread.
|
* This method is executed on the caller's thread.
|
||||||
*/
|
*/
|
||||||
private void seekToSync(int t) {
|
private void seekToSync(int t) {
|
||||||
if (t < 0) {
|
if (t < 0) {
|
||||||
|
@ -757,6 +762,29 @@ public class PlaybackServiceMediaPlayer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the PlaybackServiceMediaPlayer into STOPPED state. This call is only valid if the player is currently in
|
||||||
|
* INDETERMINATE state, for example after a call to endPlayback.
|
||||||
|
* This method will only take care of changing the PlayerStatus of this object! Other tasks like
|
||||||
|
* abandoning audio focus have to be done with other methods.
|
||||||
|
*/
|
||||||
|
public void stop() {
|
||||||
|
executor.submit(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
playerLock.lock();
|
||||||
|
|
||||||
|
if (playerStatus == PlayerStatus.INDETERMINATE) {
|
||||||
|
setPlayerStatus(PlayerStatus.STOPPED, null);
|
||||||
|
} else {
|
||||||
|
if (BuildConfig.DEBUG) Log.d(TAG, "Ignored call to stop: Current player state is: " + playerStatus);
|
||||||
|
}
|
||||||
|
playerLock.unlock();
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds information about a PSMP object.
|
* Holds information about a PSMP object.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -56,6 +56,14 @@ public final class DBReader {
|
||||||
|
|
||||||
PodDBAdapter adapter = new PodDBAdapter(context);
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
adapter.open();
|
adapter.open();
|
||||||
|
List<Feed> result = getFeedList(adapter);
|
||||||
|
adapter.close();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Feed> getFeedList(PodDBAdapter adapter) {
|
||||||
|
if (BuildConfig.DEBUG)
|
||||||
|
Log.d(TAG, "Extracting Feedlist");
|
||||||
|
|
||||||
Cursor feedlistCursor = adapter.getAllFeedsCursor();
|
Cursor feedlistCursor = adapter.getAllFeedsCursor();
|
||||||
List<Feed> feeds = new ArrayList<Feed>(feedlistCursor.getCount());
|
List<Feed> feeds = new ArrayList<Feed>(feedlistCursor.getCount());
|
||||||
|
@ -509,8 +517,8 @@ public final class DBReader {
|
||||||
* Loads a list of FeedItems sorted by pubDate in descending order.
|
* Loads a list of FeedItems sorted by pubDate in descending order.
|
||||||
*
|
*
|
||||||
* @param context A context that is used for opening a database connection.
|
* @param context A context that is used for opening a database connection.
|
||||||
* @param limit The maximum number of episodes that should be loaded.
|
* @param limit The maximum number of episodes that should be loaded.
|
||||||
* */
|
*/
|
||||||
public static List<FeedItem> getRecentlyPublishedEpisodes(Context context, int limit) {
|
public static List<FeedItem> getRecentlyPublishedEpisodes(Context context, int limit) {
|
||||||
if (BuildConfig.DEBUG)
|
if (BuildConfig.DEBUG)
|
||||||
Log.d(TAG, "Extracting recently published items list");
|
Log.d(TAG, "Extracting recently published items list");
|
||||||
|
@ -596,7 +604,8 @@ public final class DBReader {
|
||||||
.getString(PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE_INDEX);
|
.getString(PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE_INDEX);
|
||||||
Date completionDate = new Date(
|
Date completionDate = new Date(
|
||||||
logCursor
|
logCursor
|
||||||
.getLong(PodDBAdapter.KEY_COMPLETION_DATE_INDEX));
|
.getLong(PodDBAdapter.KEY_COMPLETION_DATE_INDEX)
|
||||||
|
);
|
||||||
downloadLog.add(new DownloadStatus(id, title, feedfileId,
|
downloadLog.add(new DownloadStatus(id, title, feedfileId,
|
||||||
feedfileType, successful, DownloadError.fromCode(reason), completionDate,
|
feedfileType, successful, DownloadError.fromCode(reason), completionDate,
|
||||||
reasonDetailed));
|
reasonDetailed));
|
||||||
|
@ -787,7 +796,8 @@ public final class DBReader {
|
||||||
cursor.getString(cursor
|
cursor.getString(cursor
|
||||||
.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL)),
|
.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL)),
|
||||||
cursor.getInt(cursor
|
cursor.getInt(cursor
|
||||||
.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED)) > 0);
|
.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED)) > 0
|
||||||
|
);
|
||||||
cursor.close();
|
cursor.close();
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
@ -865,4 +875,34 @@ public final class DBReader {
|
||||||
adapter.close();
|
adapter.close();
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns data necessary for displaying the navigation drawer. This includes
|
||||||
|
* the list of subscriptions, the number of items in the queue and the number of unread
|
||||||
|
* items.
|
||||||
|
*
|
||||||
|
* @param context A context that is used for opening a database connection.
|
||||||
|
*/
|
||||||
|
public static NavDrawerData getNavDrawerData(Context context) {
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
adapter.open();
|
||||||
|
List<Feed> feeds = getFeedList(adapter);
|
||||||
|
int queueSize = adapter.getQueueSize();
|
||||||
|
int numUnreadItems = adapter.getNumberOfUnreadItems();
|
||||||
|
NavDrawerData result = new NavDrawerData(feeds, queueSize, numUnreadItems);
|
||||||
|
adapter.close();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NavDrawerData {
|
||||||
|
public List<Feed> feeds;
|
||||||
|
public int queueSize;
|
||||||
|
public int numUnreadItems;
|
||||||
|
|
||||||
|
public NavDrawerData(List<Feed> feeds, int queueSize, int numUnreadItems) {
|
||||||
|
this.feeds = feeds;
|
||||||
|
this.queueSize = queueSize;
|
||||||
|
this.numUnreadItems = numUnreadItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package de.danoeh.antennapod.storage;
|
package de.danoeh.antennapod.storage;
|
||||||
|
|
||||||
import android.app.backup.BackupManager;
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
@ -1107,6 +1106,17 @@ public class PodDBAdapter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getQueueSize() {
|
||||||
|
final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_QUEUE);
|
||||||
|
Cursor c = db.rawQuery(query, null);
|
||||||
|
int result = 0;
|
||||||
|
if (c.moveToFirst()) {
|
||||||
|
result = c.getInt(0);
|
||||||
|
}
|
||||||
|
c.close();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public final int getNumberOfUnreadItems() {
|
public final int getNumberOfUnreadItems() {
|
||||||
final String query = "SELECT COUNT(DISTINCT " + KEY_ID + ") AS count FROM " + TABLE_NAME_FEED_ITEMS +
|
final String query = "SELECT COUNT(DISTINCT " + KEY_ID + ") AS count FROM " + TABLE_NAME_FEED_ITEMS +
|
||||||
" WHERE " + KEY_READ + " = 0";
|
" WHERE " + KEY_READ + " = 0";
|
||||||
|
|
|
@ -22,7 +22,6 @@ public class HttpDownloaderTest extends InstrumentationTestCase {
|
||||||
private File destDir;
|
private File destDir;
|
||||||
|
|
||||||
private HTTPBin httpServer;
|
private HTTPBin httpServer;
|
||||||
private static final String BASE_URL = "http://127.0.0.1:" + HTTPBin.PORT;
|
|
||||||
|
|
||||||
public HttpDownloaderTest() {
|
public HttpDownloaderTest() {
|
||||||
super();
|
super();
|
||||||
|
@ -79,15 +78,15 @@ public class HttpDownloaderTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static final String URL_404 = BASE_URL + "/status/404";
|
private static final String URL_404 = HTTPBin.BASE_URL + "/status/404";
|
||||||
private static final String URL_AUTH = BASE_URL + "/basic-auth/user/passwd";
|
private static final String URL_AUTH = HTTPBin.BASE_URL + "/basic-auth/user/passwd";
|
||||||
|
|
||||||
public void testPassingHttp() {
|
public void testPassingHttp() {
|
||||||
download(BASE_URL + "/status/200", "test200", true);
|
download(HTTPBin.BASE_URL + "/status/200", "test200", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRedirect() {
|
public void testRedirect() {
|
||||||
download(BASE_URL + "/redirect/4", "testRedirect", true);
|
download(HTTPBin.BASE_URL + "/redirect/4", "testRedirect", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGzip() {
|
public void testGzip() {
|
||||||
|
@ -99,7 +98,7 @@ public class HttpDownloaderTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCancel() {
|
public void testCancel() {
|
||||||
final String url = BASE_URL + "/delay/3";
|
final String url = HTTPBin.BASE_URL + "/delay/3";
|
||||||
FeedFileImpl feedFile = setupFeedFile(url, "delay", true);
|
FeedFileImpl feedFile = setupFeedFile(url, "delay", true);
|
||||||
final Downloader downloader = new HttpDownloader(new DownloadRequest(feedFile.getFile_url(), url, "delay", 0, feedFile.getTypeAsInt()));
|
final Downloader downloader = new HttpDownloader(new DownloadRequest(feedFile.getFile_url(), url, "delay", 0, feedFile.getTypeAsInt()));
|
||||||
Thread t = new Thread() {
|
Thread t = new Thread() {
|
||||||
|
|
|
@ -365,4 +365,44 @@ public class DBReaderTest extends InstrumentationTestCase {
|
||||||
assertEquals("Wrong entry at index " + i, feeds.get(i).getId(), statistics.get(i).getFeedID());
|
assertEquals("Wrong entry at index " + i, feeds.get(i).getId(), statistics.get(i).getFeedID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGetNavDrawerDataQueueEmptyNoUnreadItems() {
|
||||||
|
final Context context = getInstrumentation().getTargetContext();
|
||||||
|
final int NUM_FEEDS = 10;
|
||||||
|
final int NUM_ITEMS = 10;
|
||||||
|
List<Feed> feeds = DBTestUtils.saveFeedlist(context, NUM_FEEDS, NUM_ITEMS, true);
|
||||||
|
DBReader.NavDrawerData navDrawerData = DBReader.getNavDrawerData(context);
|
||||||
|
assertEquals(NUM_FEEDS, navDrawerData.feeds.size());
|
||||||
|
assertEquals(0, navDrawerData.numUnreadItems);
|
||||||
|
assertEquals(0, navDrawerData.queueSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetNavDrawerDataQueueNotEmptyWithUnreadItems() {
|
||||||
|
final Context context = getInstrumentation().getTargetContext();
|
||||||
|
final int NUM_FEEDS = 10;
|
||||||
|
final int NUM_ITEMS = 10;
|
||||||
|
final int NUM_QUEUE = 1;
|
||||||
|
final int NUM_UNREAD = 2;
|
||||||
|
List<Feed> feeds = DBTestUtils.saveFeedlist(context, NUM_FEEDS, NUM_ITEMS, true);
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
adapter.open();
|
||||||
|
for (int i = 0; i < NUM_UNREAD; i++) {
|
||||||
|
FeedItem item = feeds.get(0).getItems().get(i);
|
||||||
|
item.setRead(false);
|
||||||
|
adapter.setSingleFeedItem(item);
|
||||||
|
}
|
||||||
|
List<FeedItem> queue = new ArrayList<FeedItem>();
|
||||||
|
for (int i = 0; i < NUM_QUEUE; i++) {
|
||||||
|
FeedItem item = feeds.get(1).getItems().get(i);
|
||||||
|
queue.add(item);
|
||||||
|
}
|
||||||
|
adapter.setQueue(queue);
|
||||||
|
|
||||||
|
adapter.close();
|
||||||
|
|
||||||
|
DBReader.NavDrawerData navDrawerData = DBReader.getNavDrawerData(context);
|
||||||
|
assertEquals(NUM_FEEDS, navDrawerData.feeds.size());
|
||||||
|
assertEquals(NUM_UNREAD, navDrawerData.numUnreadItems);
|
||||||
|
assertEquals(NUM_QUEUE, navDrawerData.queueSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
package instrumentationTest.de.test.antennapod.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.test.ActivityInstrumentationTestCase2;
|
||||||
|
import android.view.View;
|
||||||
|
import com.robotium.solo.Solo;
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.activity.DefaultOnlineFeedViewActivity;
|
||||||
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
|
import de.danoeh.antennapod.activity.PreferenceActivity;
|
||||||
|
import de.danoeh.antennapod.feed.EventDistributor;
|
||||||
|
import de.danoeh.antennapod.feed.Feed;
|
||||||
|
import de.danoeh.antennapod.storage.PodDBAdapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interface tests for MainActivity
|
||||||
|
*/
|
||||||
|
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
|
||||||
|
|
||||||
|
private Solo solo;
|
||||||
|
private UITestUtils uiTestUtils;
|
||||||
|
|
||||||
|
public MainActivityTest() {
|
||||||
|
super(MainActivity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
solo = new Solo(getInstrumentation(), getActivity());
|
||||||
|
uiTestUtils = new UITestUtils(getInstrumentation().getTargetContext());
|
||||||
|
uiTestUtils.setup();
|
||||||
|
// create database
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getTargetContext());
|
||||||
|
adapter.open();
|
||||||
|
adapter.close();
|
||||||
|
|
||||||
|
// override first launch preference
|
||||||
|
SharedPreferences prefs = getInstrumentation().getTargetContext().getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE);
|
||||||
|
prefs.edit().putBoolean(MainActivity.PREF_IS_FIRST_LAUNCH, false).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
uiTestUtils.tearDown();
|
||||||
|
solo.finishOpenedActivities();
|
||||||
|
PodDBAdapter.deleteDatabase(getInstrumentation().getTargetContext());
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddFeed() throws Exception {
|
||||||
|
uiTestUtils.addHostedFeedData();
|
||||||
|
final Feed feed = uiTestUtils.hostedFeeds.get(0);
|
||||||
|
solo.setNavigationDrawer(Solo.OPENED);
|
||||||
|
solo.clickOnText(solo.getString(R.string.add_feed_label));
|
||||||
|
solo.enterText(0, feed.getDownload_url());
|
||||||
|
solo.clickOnButton(0);
|
||||||
|
solo.waitForActivity(DefaultOnlineFeedViewActivity.class);
|
||||||
|
solo.waitForView(R.id.butSubscribe);
|
||||||
|
assertEquals(solo.getString(R.string.subscribe_label), solo.getButton(0).getText().toString());
|
||||||
|
solo.clickOnButton(0);
|
||||||
|
solo.waitForText(solo.getString(R.string.subscribed_label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testClickNavDrawer() throws Exception {
|
||||||
|
uiTestUtils.addLocalFeedData(false);
|
||||||
|
|
||||||
|
final View home = solo.getView(android.R.id.home);
|
||||||
|
|
||||||
|
// all episodes
|
||||||
|
solo.waitForView(android.R.id.list);
|
||||||
|
assertEquals(solo.getString(R.string.all_episodes_label), getActionbarTitle());
|
||||||
|
// queue
|
||||||
|
solo.clickOnView(home);
|
||||||
|
solo.clickOnText(solo.getString(R.string.queue_label));
|
||||||
|
solo.waitForView(android.R.id.list);
|
||||||
|
assertEquals(solo.getString(R.string.queue_label), getActionbarTitle());
|
||||||
|
|
||||||
|
// downloads
|
||||||
|
solo.clickOnView(home);
|
||||||
|
solo.clickOnText(solo.getString(R.string.downloads_label));
|
||||||
|
solo.waitForView(android.R.id.list);
|
||||||
|
assertEquals(solo.getString(R.string.downloads_label), getActionbarTitle());
|
||||||
|
|
||||||
|
// playback history
|
||||||
|
solo.clickOnView(home);
|
||||||
|
solo.clickOnText(solo.getString(R.string.playback_history_label));
|
||||||
|
solo.waitForView(android.R.id.list);
|
||||||
|
assertEquals(solo.getString(R.string.playback_history_label), getActionbarTitle());
|
||||||
|
|
||||||
|
// add podcast
|
||||||
|
solo.clickOnView(home);
|
||||||
|
solo.clickOnText(solo.getString(R.string.add_feed_label));
|
||||||
|
solo.waitForView(R.id.txtvFeedurl);
|
||||||
|
assertEquals(solo.getString(R.string.add_feed_label), getActionbarTitle());
|
||||||
|
|
||||||
|
// podcasts
|
||||||
|
for (int i = 0; i < uiTestUtils.hostedFeeds.size(); i++) {
|
||||||
|
Feed f = uiTestUtils.hostedFeeds.get(i);
|
||||||
|
solo.clickOnView(home);
|
||||||
|
solo.clickOnText(f.getTitle());
|
||||||
|
solo.waitForView(android.R.id.list);
|
||||||
|
assertEquals("", getActionbarTitle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getActionbarTitle() {
|
||||||
|
return ((MainActivity)solo.getCurrentActivity()).getMainActivtyActionBar().getTitle().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGoToPreferences() {
|
||||||
|
solo.setNavigationDrawer(Solo.CLOSED);
|
||||||
|
solo.clickOnMenuItem(solo.getString(R.string.settings_label));
|
||||||
|
solo.waitForActivity(PreferenceActivity.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
package instrumentationTest.de.test.antennapod.ui;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.test.ActivityInstrumentationTestCase2;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.robotium.solo.Solo;
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.activity.AudioplayerActivity;
|
||||||
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
|
import de.danoeh.antennapod.feed.FeedItem;
|
||||||
|
import de.danoeh.antennapod.preferences.UserPreferences;
|
||||||
|
import de.danoeh.antennapod.service.playback.PlaybackService;
|
||||||
|
import de.danoeh.antennapod.storage.DBReader;
|
||||||
|
import de.danoeh.antennapod.storage.DBWriter;
|
||||||
|
import de.danoeh.antennapod.storage.PodDBAdapter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test cases for starting and ending playback from the MainActivity and AudioPlayerActivity
|
||||||
|
*/
|
||||||
|
public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity> {
|
||||||
|
|
||||||
|
private Solo solo;
|
||||||
|
private UITestUtils uiTestUtils;
|
||||||
|
|
||||||
|
public PlaybackTest() {
|
||||||
|
super(MainActivity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
solo = new Solo(getInstrumentation(), getActivity());
|
||||||
|
uiTestUtils = new UITestUtils(getInstrumentation().getTargetContext());
|
||||||
|
uiTestUtils.setup();
|
||||||
|
// create database
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getTargetContext());
|
||||||
|
adapter.open();
|
||||||
|
adapter.close();
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getInstrumentation().getTargetContext());
|
||||||
|
prefs.edit().putBoolean(UserPreferences.PREF_PAUSE_ON_HEADSET_DISCONNECT, false).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
uiTestUtils.tearDown();
|
||||||
|
solo.finishOpenedActivities();
|
||||||
|
PodDBAdapter.deleteDatabase(getInstrumentation().getTargetContext());
|
||||||
|
|
||||||
|
// shut down playback service
|
||||||
|
skipEpisode();
|
||||||
|
getInstrumentation().getTargetContext().sendBroadcast(
|
||||||
|
new Intent(PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
|
||||||
|
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setContinuousPlaybackPreference(boolean value) {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getInstrumentation().getTargetContext());
|
||||||
|
prefs.edit().putBoolean(UserPreferences.PREF_FOLLOW_QUEUE, value).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void skipEpisode() {
|
||||||
|
Intent skipIntent = new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE);
|
||||||
|
getInstrumentation().getTargetContext().sendBroadcast(skipIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLocalPlayback() {
|
||||||
|
assertTrue(solo.waitForActivity(MainActivity.class));
|
||||||
|
solo.setNavigationDrawer(Solo.CLOSED);
|
||||||
|
solo.clickOnView(solo.getView(R.id.butSecondaryAction));
|
||||||
|
assertTrue(solo.waitForActivity(AudioplayerActivity.class));
|
||||||
|
assertTrue(solo.waitForView(solo.getView(R.id.butPlay)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLocalPlaybackFromQueue() {
|
||||||
|
assertTrue(solo.waitForActivity(MainActivity.class));
|
||||||
|
solo.clickOnView(solo.getView(android.R.id.home));
|
||||||
|
solo.clickOnText(solo.getString(R.string.queue_label));
|
||||||
|
assertTrue(solo.waitForView(solo.getView(R.id.butSecondaryAction)));
|
||||||
|
solo.clickOnImageButton(0);
|
||||||
|
assertTrue(solo.waitForActivity(AudioplayerActivity.class));
|
||||||
|
assertTrue(solo.waitForView(solo.getView(R.id.butPlay)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStartLocal() throws Exception {
|
||||||
|
uiTestUtils.addLocalFeedData(true);
|
||||||
|
DBWriter.clearQueue(getInstrumentation().getTargetContext()).get();
|
||||||
|
startLocalPlayback();
|
||||||
|
|
||||||
|
solo.clickOnView(solo.getView(R.id.butPlay));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testContinousPlaybackOffSingleEpisode() throws Exception {
|
||||||
|
setContinuousPlaybackPreference(false);
|
||||||
|
uiTestUtils.addLocalFeedData(true);
|
||||||
|
DBWriter.clearQueue(getInstrumentation().getTargetContext()).get();
|
||||||
|
startLocalPlayback();
|
||||||
|
assertTrue(solo.waitForActivity(MainActivity.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testContinousPlaybackOffMultipleEpisodes() throws Exception {
|
||||||
|
setContinuousPlaybackPreference(false);
|
||||||
|
uiTestUtils.addLocalFeedData(true);
|
||||||
|
List<FeedItem> queue = DBReader.getQueue(getInstrumentation().getTargetContext());
|
||||||
|
FeedItem second = queue.get(1);
|
||||||
|
|
||||||
|
startLocalPlaybackFromQueue();
|
||||||
|
assertTrue(solo.waitForText(second.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testContinuousPlaybackOnMultipleEpisodes() throws Exception {
|
||||||
|
setContinuousPlaybackPreference(true);
|
||||||
|
uiTestUtils.addLocalFeedData(true);
|
||||||
|
List<FeedItem> queue = DBReader.getQueue(getInstrumentation().getTargetContext());
|
||||||
|
FeedItem second = queue.get(1);
|
||||||
|
|
||||||
|
startLocalPlaybackFromQueue();
|
||||||
|
assertTrue(solo.waitForText(second.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an episode can be played twice without problems.
|
||||||
|
*/
|
||||||
|
private void replayEpisodeCheck(boolean followQueue) throws Exception {
|
||||||
|
setContinuousPlaybackPreference(followQueue);
|
||||||
|
uiTestUtils.addLocalFeedData(true);
|
||||||
|
DBWriter.clearQueue(getInstrumentation().getTargetContext()).get();
|
||||||
|
String title = ((TextView) solo.getView(R.id.txtvTitle)).getText().toString();
|
||||||
|
startLocalPlayback();
|
||||||
|
assertTrue(solo.waitForText(title));
|
||||||
|
assertTrue(solo.waitForActivity(MainActivity.class));
|
||||||
|
startLocalPlayback();
|
||||||
|
assertTrue(solo.waitForText(title));
|
||||||
|
assertTrue(solo.waitForActivity(MainActivity.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReplayEpisodeContinuousPlaybackOn() throws Exception {
|
||||||
|
replayEpisodeCheck(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReplayEpisodeContinuousPlaybackOff() throws Exception {
|
||||||
|
replayEpisodeCheck(false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
package instrumentationTest.de.test.antennapod.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import de.danoeh.antennapod.feed.*;
|
||||||
|
import de.danoeh.antennapod.storage.DBWriter;
|
||||||
|
import de.danoeh.antennapod.storage.PodDBAdapter;
|
||||||
|
import instrumentationTest.de.test.antennapod.util.service.download.HTTPBin;
|
||||||
|
import instrumentationTest.de.test.antennapod.util.syndication.feedgenerator.RSS2Generator;
|
||||||
|
import junit.framework.Assert;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for UI tests.
|
||||||
|
* Starts a web server that hosts feeds, episodes and images.
|
||||||
|
*/
|
||||||
|
public class UITestUtils {
|
||||||
|
|
||||||
|
private static final String DATA_FOLDER = "test/UITestUtils";
|
||||||
|
|
||||||
|
public static final int NUM_FEEDS = 5;
|
||||||
|
public static final int NUM_ITEMS_PER_FEED = 10;
|
||||||
|
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private HTTPBin server = new HTTPBin();
|
||||||
|
private File destDir;
|
||||||
|
private File hostedFeedDir;
|
||||||
|
private File hostedMediaDir;
|
||||||
|
|
||||||
|
public List<Feed> hostedFeeds = new ArrayList<Feed>();
|
||||||
|
|
||||||
|
public UITestUtils(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setup() throws IOException {
|
||||||
|
destDir = context.getExternalFilesDir(DATA_FOLDER);
|
||||||
|
destDir.mkdir();
|
||||||
|
hostedFeedDir = new File(destDir, "hostedFeeds");
|
||||||
|
hostedFeedDir.mkdir();
|
||||||
|
hostedMediaDir = new File(destDir, "hostedMediaDir");
|
||||||
|
hostedMediaDir.mkdir();
|
||||||
|
Assert.assertTrue(destDir.exists());
|
||||||
|
Assert.assertTrue(hostedFeedDir.exists());
|
||||||
|
Assert.assertTrue(hostedMediaDir.exists());
|
||||||
|
server.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tearDown() throws IOException {
|
||||||
|
FileUtils.deleteDirectory(destDir);
|
||||||
|
FileUtils.deleteDirectory(hostedMediaDir);
|
||||||
|
FileUtils.deleteDirectory(hostedFeedDir);
|
||||||
|
server.stop();
|
||||||
|
|
||||||
|
if (localFeedDataAdded) {
|
||||||
|
PodDBAdapter.deleteDatabase(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String hostFeed(Feed feed) throws IOException {
|
||||||
|
File feedFile = new File(hostedFeedDir, feed.getTitle());
|
||||||
|
FileOutputStream out = new FileOutputStream(feedFile);
|
||||||
|
RSS2Generator generator = new RSS2Generator();
|
||||||
|
generator.writeFeed(feed, out, "UTF-8", 0);
|
||||||
|
out.close();
|
||||||
|
int id = server.serveFile(feedFile);
|
||||||
|
Assert.assertTrue(id != -1);
|
||||||
|
return String.format("%s/files/%d", HTTPBin.BASE_URL, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String hostFile(File file) {
|
||||||
|
int id = server.serveFile(file);
|
||||||
|
Assert.assertTrue(id != -1);
|
||||||
|
return String.format("%s/files/%d", HTTPBin.BASE_URL, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File newBitmapFile(String name) throws IOException {
|
||||||
|
File imgFile = new File(destDir, name);
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(128, 128, Bitmap.Config.ARGB_8888);
|
||||||
|
FileOutputStream out = new FileOutputStream(imgFile);
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.PNG, 1, out);
|
||||||
|
out.close();
|
||||||
|
return imgFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File newMediaFile(String name) throws IOException {
|
||||||
|
File mediaFile = new File(hostedMediaDir, name);
|
||||||
|
Assert.assertFalse(mediaFile.exists());
|
||||||
|
|
||||||
|
InputStream in = context.getAssets().open("testfile.mp3");
|
||||||
|
Assert.assertNotNull(in);
|
||||||
|
|
||||||
|
FileOutputStream out = new FileOutputStream(mediaFile);
|
||||||
|
IOUtils.copy(in, out);
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
return mediaFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean feedDataHosted = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds feeds, images and episodes to the webserver for testing purposes.
|
||||||
|
*/
|
||||||
|
public void addHostedFeedData() throws IOException {
|
||||||
|
if (feedDataHosted) throw new IllegalStateException("addHostedFeedData was called twice on the same instance");
|
||||||
|
for (int i = 0; i < NUM_FEEDS; i++) {
|
||||||
|
File bitmapFile = newBitmapFile("image" + i);
|
||||||
|
FeedImage image = new FeedImage(0, "image " + i, null, hostFile(bitmapFile), false);
|
||||||
|
Feed feed = new Feed(0, new Date(), "Title " + i, "http://example.com/" + i, "Description of feed " + i,
|
||||||
|
"http://example.com/pay/feed" + i, "author " + i, "en", Feed.TYPE_RSS2, "feed" + i, image, null,
|
||||||
|
"http://example.com/feed/src/" + i, false);
|
||||||
|
image.setOwner(feed);
|
||||||
|
|
||||||
|
// create items
|
||||||
|
List<FeedItem> items = new ArrayList<FeedItem>();
|
||||||
|
for (int j = 0; j < NUM_ITEMS_PER_FEED; j++) {
|
||||||
|
FeedItem item = new FeedItem(0, "item" + j, "item" + j, "http://example.com/feed" + i + "/item/" + j, new Date(), true, feed);
|
||||||
|
items.add(item);
|
||||||
|
|
||||||
|
File mediaFile = newMediaFile("feed-" + i + "-episode-" + j + ".mp3");
|
||||||
|
item.setMedia(new FeedMedia(0, item, 0, 0, mediaFile.length(), "audio/mp3", null, hostFile(mediaFile), false, null, 0));
|
||||||
|
|
||||||
|
}
|
||||||
|
feed.setItems(items);
|
||||||
|
feed.setDownload_url(hostFeed(feed));
|
||||||
|
hostedFeeds.add(feed);
|
||||||
|
}
|
||||||
|
feedDataHosted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean localFeedDataAdded = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds feeds, images and episodes to the local database. This method will also call addHostedFeedData if it has not
|
||||||
|
* been called yet.
|
||||||
|
*
|
||||||
|
* Adds one item of each feed to the queue and to the playback history.
|
||||||
|
*
|
||||||
|
* This method should NOT be called if the testing class wants to download the hosted feed data.
|
||||||
|
*
|
||||||
|
* @param downloadEpisodes true if episodes should also be marked as downloaded.
|
||||||
|
*/
|
||||||
|
public void addLocalFeedData(boolean downloadEpisodes) throws Exception {
|
||||||
|
if (localFeedDataAdded) throw new IllegalStateException("addLocalFeedData was called twice on the same instance");
|
||||||
|
if (!feedDataHosted) {
|
||||||
|
addHostedFeedData();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FeedItem> queue = new ArrayList<FeedItem>();
|
||||||
|
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
adapter.open();
|
||||||
|
for (Feed feed : hostedFeeds) {
|
||||||
|
feed.setDownloaded(true);
|
||||||
|
if (feed.getImage() != null) {
|
||||||
|
FeedImage image = feed.getImage();
|
||||||
|
image.setFile_url(image.getDownload_url());
|
||||||
|
image.setDownloaded(true);
|
||||||
|
}
|
||||||
|
if (downloadEpisodes) {
|
||||||
|
for (FeedItem item : feed.getItems()) {
|
||||||
|
if (item.hasMedia()) {
|
||||||
|
FeedMedia media = item.getMedia();
|
||||||
|
int fileId = Integer.parseInt(StringUtils.substringAfter(media.getDownload_url(), "files/"));
|
||||||
|
media.setFile_url(server.accessFile(fileId).getAbsolutePath());
|
||||||
|
media.setDownloaded(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.add(feed.getItems().get(0));
|
||||||
|
feed.getItems().get(1).getMedia().setPlaybackCompletionDate(new Date());
|
||||||
|
}
|
||||||
|
adapter.setCompleteFeed(hostedFeeds.toArray(new Feed[hostedFeeds.size()]));
|
||||||
|
adapter.setQueue(queue);
|
||||||
|
adapter.close();
|
||||||
|
EventDistributor.getInstance().sendFeedUpdateBroadcast();
|
||||||
|
EventDistributor.getInstance().sendQueueUpdateBroadcast();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
package instrumentationTest.de.test.antennapod.ui;
|
||||||
|
|
||||||
|
import android.test.InstrumentationTestCase;
|
||||||
|
import de.danoeh.antennapod.feed.Feed;
|
||||||
|
import de.danoeh.antennapod.feed.FeedItem;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for the UITestUtils. Makes sure that all URLs are reachable and that the class does not cause any crashes.
|
||||||
|
*/
|
||||||
|
public class UITestUtilsTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
|
private UITestUtils uiTestUtils;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
uiTestUtils = new UITestUtils(getInstrumentation().getTargetContext());
|
||||||
|
uiTestUtils.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
super.tearDown();
|
||||||
|
uiTestUtils.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddHostedFeeds() throws Exception {
|
||||||
|
uiTestUtils.addHostedFeedData();
|
||||||
|
final List<Feed> feeds = uiTestUtils.hostedFeeds;
|
||||||
|
assertNotNull(feeds);
|
||||||
|
assertFalse(feeds.isEmpty());
|
||||||
|
|
||||||
|
for (Feed feed : feeds) {
|
||||||
|
testUrlReachable(feed.getDownload_url());
|
||||||
|
if (feed.getImage() != null) {
|
||||||
|
testUrlReachable(feed.getImage().getDownload_url());
|
||||||
|
}
|
||||||
|
for (FeedItem item : feed.getItems()) {
|
||||||
|
if (item.hasMedia()) {
|
||||||
|
testUrlReachable(item.getMedia().getDownload_url());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testUrlReachable(String strUtl) throws Exception {
|
||||||
|
URL url = new URL(strUtl);
|
||||||
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
conn.connect();
|
||||||
|
int rc = conn.getResponseCode();
|
||||||
|
assertEquals(HttpStatus.SC_OK, rc);
|
||||||
|
conn.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addLocalFeedDataCheck(boolean downloadEpisodes) throws Exception {
|
||||||
|
uiTestUtils.addLocalFeedData(downloadEpisodes);
|
||||||
|
assertNotNull(uiTestUtils.hostedFeeds);
|
||||||
|
assertFalse(uiTestUtils.hostedFeeds.isEmpty());
|
||||||
|
|
||||||
|
for (Feed feed : uiTestUtils.hostedFeeds) {
|
||||||
|
assertTrue(feed.getId() != 0);
|
||||||
|
if (feed.getImage() != null) {
|
||||||
|
assertTrue(feed.getImage().getId() != 0);
|
||||||
|
}
|
||||||
|
for (FeedItem item : feed.getItems()) {
|
||||||
|
assertTrue(item.getId() != 0);
|
||||||
|
if (item.hasMedia()) {
|
||||||
|
assertTrue(item.getMedia().getId() != 0);
|
||||||
|
if (downloadEpisodes) {
|
||||||
|
assertTrue(item.getMedia().isDownloaded());
|
||||||
|
assertNotNull(item.getMedia().getFile_url());
|
||||||
|
File file = new File(item.getMedia().getFile_url());
|
||||||
|
assertTrue(file.exists());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddLocalFeedDataNoDownload() throws Exception {
|
||||||
|
addLocalFeedDataCheck(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddLocalFeedDataDownload() throws Exception {
|
||||||
|
addLocalFeedDataCheck(true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,8 @@ import java.util.zip.GZIPOutputStream;
|
||||||
public class HTTPBin extends NanoHTTPD {
|
public class HTTPBin extends NanoHTTPD {
|
||||||
private static final String TAG = "HTTPBin";
|
private static final String TAG = "HTTPBin";
|
||||||
public static final int PORT = 8124;
|
public static final int PORT = 8124;
|
||||||
|
public static final String BASE_URL = "http://127.0.0.1:" + HTTPBin.PORT;
|
||||||
|
|
||||||
|
|
||||||
private static final String MIME_HTML = "text/html";
|
private static final String MIME_HTML = "text/html";
|
||||||
private static final String MIME_PLAIN = "text/plain";
|
private static final String MIME_PLAIN = "text/plain";
|
||||||
|
@ -70,7 +72,7 @@ public class HTTPBin extends NanoHTTPD {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized File accessFile(int id) {
|
public synchronized File accessFile(int id) {
|
||||||
if (id < 0 || id >= servedFiles.size()) {
|
if (id < 0 || id >= servedFiles.size()) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue