diff options
author | Martin Fietz <Martin.Fietz@gmail.com> | 2016-01-08 00:16:32 +0100 |
---|---|---|
committer | Martin Fietz <Martin.Fietz@gmail.com> | 2016-01-08 00:16:32 +0100 |
commit | a6a7310a387db39c44bd0db53f639c9f843c31df (patch) | |
tree | 3727465902d3776086c569bfc63e5c3bf955a87a | |
parent | 0c973e3ea79d0891cbc1d1ba102878996797205f (diff) | |
parent | 754ff931b1c92cf5721503bb9ec107b28df1524f (diff) | |
download | AntennaPod-a6a7310a387db39c44bd0db53f639c9f843c31df.zip |
Merge pull request #1498 from mfietz/v23
Support libraries v23
42 files changed, 564 insertions, 587 deletions
diff --git a/app/build.gradle b/app/build.gradle index eb4b25de8..2fe94d576 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,7 +14,7 @@ dependencies { compile "com.android.support:gridlayout-v7:$supportVersion" compile "com.android.support:cardview-v7:$supportVersion" compile "com.android.support:design:$supportVersion" - compile "com.android.support:recyclerview-v7:22.2.+" + compile "com.android.support:recyclerview-v7:$supportVersion" compile "org.apache.commons:commons-lang3:$commonslangVersion" compile("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") { exclude group: "org.json", module: "json" @@ -31,9 +31,12 @@ dependencies { compile "io.reactivex:rxjava:$rxJavaVersion" // And ProGuard rules for RxJava! compile "com.artemzin.rxjava:proguard-rules:$rxJavaRulesVersion" - compile "com.joanzapata.iconify:android-iconify-fontawesome:2.1.0" - compile "com.afollestad:material-dialogs:0.7.8.1" - compile "com.yqritc:recyclerview-flexibledivider:1.2.6" + compile "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyFontawesomeVersion" + compile "com.joanzapata.iconify:android-iconify-material:$iconifyFontawesomeVersion" + compile("com.github.afollestad.material-dialogs:commons:$materialDialogsVersion") { + transitive = true + } + compile "com.yqritc:recyclerview-flexibledivider:$recyclerviewFlexibledividerVersion" compile "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion" diff --git a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java index 4dae53a15..e456f3891 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java @@ -51,6 +51,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv adapter.close(); // override first launch preference + // do this BEFORE calling getActivity()! prefs = getInstrumentation().getTargetContext().getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE); prefs.edit().putBoolean(MainActivity.PREF_IS_FIRST_LAUNCH, false).commit(); @@ -71,7 +72,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv } private void openNavDrawer() { - solo.clickOnScreen(50, 50); + solo.clickOnImageButton(0); + getInstrumentation().waitForIdleSync(); } public void testAddFeed() throws Exception { @@ -125,7 +127,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv assertEquals(solo.getString(R.string.add_feed_label), getActionbarTitle()); // podcasts - ListView list = (ListView)solo.getView(R.id.nav_list); + ListView list = (ListView) solo.getView(R.id.nav_list); for (int i = 0; i < uiTestUtils.hostedFeeds.size(); i++) { Feed f = uiTestUtils.hostedFeeds.get(i); solo.clickOnScreen(50, 50); // open nav drawer @@ -137,7 +139,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv } private String getActionbarTitle() { - return ((MainActivity)solo.getCurrentActivity()).getMainActivtyActionBar().getTitle().toString(); + return ((MainActivity) solo.getCurrentActivity()).getSupportActionBar().getTitle().toString(); } @FlakyTest(tolerance = 3) @@ -185,14 +187,14 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv openNavDrawer(); solo.clickLongOnText(solo.getString(R.string.queue_label)); solo.waitForDialogToOpen(); - for(String title : titles) { + for (String title : titles) { solo.clickOnText(title); } solo.clickOnText(solo.getString(R.string.confirm_label)); solo.waitForDialogToClose(); List<String> hidden = UserPreferences.getHiddenDrawerItems(); assertEquals(titles.length, hidden.size()); - for(String tag : MainActivity.NAV_DRAWER_TAGS) { + for (String tag : MainActivity.NAV_DRAWER_TAGS) { assertTrue(hidden.contains(tag)); } } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java index c43757546..d65925703 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java @@ -1,7 +1,6 @@ package de.test.antennapod.ui; import android.annotation.TargetApi; -import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -10,7 +9,6 @@ import android.preference.PreferenceManager; import android.test.ActivityInstrumentationTestCase2; import android.test.FlakyTest; import android.view.View; -import android.widget.ImageButton; import android.widget.ListView; import com.robotium.solo.Solo; @@ -21,15 +19,12 @@ import java.util.List; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlayerStatus; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.PodDBAdapter; -import de.danoeh.antennapod.core.util.playback.Playable; -import de.danoeh.antennapod.core.util.playback.PlaybackController; /** * test cases for starting and ending playback from the MainActivity and AudioPlayerActivity @@ -90,7 +85,7 @@ public class PlaybackSonicTest extends ActivityInstrumentationTestCase2<MainActi } private void openNavDrawer() { - solo.clickOnScreen(50, 50); + solo.clickOnImageButton(0); getInstrumentation().waitForIdleSync(); } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java index 195e3d250..016c868b4 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java @@ -79,9 +79,9 @@ public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity> super.tearDown(); } - private void openNavDrawer() { - solo.clickOnScreen(50, 50); + solo.clickOnImageButton(0); + getInstrumentation().waitForIdleSync(); } private void setContinuousPlaybackPreference(boolean value) { diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java index 6c5a350de..53fd7d7fd 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java @@ -1,15 +1,15 @@ package de.test.antennapod.ui; import android.test.InstrumentationTestCase; -import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedItem; -import org.apache.http.HttpStatus; import java.io.File; import java.net.HttpURLConnection; import java.net.URL; import java.util.List; +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedItem; + /** * Test for the UITestUtils. Makes sure that all URLs are reachable and that the class does not cause any crashes. */ @@ -55,7 +55,7 @@ public class UITestUtilsTest extends InstrumentationTestCase { conn.setRequestMethod("GET"); conn.connect(); int rc = conn.getResponseCode(); - assertEquals(HttpStatus.SC_OK, rc); + assertEquals(HttpURLConnection.HTTP_OK, rc); conn.disconnect(); } diff --git a/app/src/androidTest/java/de/test/antennapod/util/service/download/NanoHTTPD.java b/app/src/androidTest/java/de/test/antennapod/util/service/download/NanoHTTPD.java index 4a5818479..28ff6694e 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/service/download/NanoHTTPD.java +++ b/app/src/androidTest/java/de/test/antennapod/util/service/download/NanoHTTPD.java @@ -1,6 +1,21 @@ package de.test.antennapod.util.service.download; -import java.io.*; +import android.support.v4.util.ArrayMap; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.PushbackInputStream; +import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; @@ -14,7 +29,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -281,7 +295,7 @@ public abstract class NanoHTTPD { * @return HTTP response, see class Response for details */ public Response serve(IHTTPSession session) { - Map<String, String> files = new HashMap<String, String>(); + Map<String, String> files = new ArrayMap<>(); Method method = session.getMethod(); if (Method.PUT.equals(method) || Method.POST.equals(method)) { try { @@ -334,7 +348,7 @@ public abstract class NanoHTTPD { * @return a map of <code>String</code> (parameter name) to <code>List<String></code> (a list of the values supplied). */ protected Map<String, List<String>> decodeParameters(String queryString) { - Map<String, List<String>> parms = new HashMap<String, List<String>>(); + Map<String, List<String>> parms = new ArrayMap<String, List<String>>(); if (queryString != null) { StringTokenizer st = new StringTokenizer(queryString, "&"); while (st.hasMoreTokens()) { @@ -549,7 +563,7 @@ public abstract class NanoHTTPD { /** * Headers for the HTTP response. Use addHeader() to add lines. */ - private Map<String, String> header = new HashMap<String, String>(); + private Map<String, String> header = new ArrayMap<String, String>(); /** * The request method that spawned this response. */ @@ -851,7 +865,7 @@ public abstract class NanoHTTPD { this.inputStream = new PushbackInputStream(inputStream, BUFSIZE); this.outputStream = outputStream; String remoteIp = inetAddress.isLoopbackAddress() || inetAddress.isAnyLocalAddress() ? "127.0.0.1" : inetAddress.getHostAddress().toString(); - headers = new HashMap<String, String>(); + headers = new ArrayMap<String, String>(); headers.put("remote-addr", remoteIp); headers.put("http-client-ip", remoteIp); @@ -895,16 +909,16 @@ public abstract class NanoHTTPD { inputStream.unread(buf, splitbyte, rlen - splitbyte); } - parms = new HashMap<String, String>(); + parms = new ArrayMap<String, String>(); if(null == headers) { - headers = new HashMap<String, String>(); + headers = new ArrayMap<String, String>(); } // Create a BufferedReader for parsing the header. BufferedReader hin = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, rlen))); // Decode the header into parms and header java properties - Map<String, String> pre = new HashMap<String, String>(); + Map<String, String> pre = new ArrayMap<String, String>(); decodeHeader(hin, pre, parms, headers); method = Method.lookup(pre.get("method")); @@ -1102,7 +1116,7 @@ public abstract class NanoHTTPD { throw new ResponseException(Response.Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but next chunk does not start with boundary. Usage: GET /example/file.html"); } boundarycount++; - Map<String, String> item = new HashMap<String, String>(); + Map<String, String> item = new ArrayMap<String, String>(); mpline = in.readLine(); while (mpline != null && mpline.trim().length() > 0) { int p = mpline.indexOf(':'); @@ -1117,7 +1131,7 @@ public abstract class NanoHTTPD { throw new ResponseException(Response.Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but no content-disposition info found. Usage: GET /example/file.html"); } StringTokenizer st = new StringTokenizer(contentDisposition, ";"); - Map<String, String> disposition = new HashMap<String, String>(); + Map<String, String> disposition = new ArrayMap<String, String>(); while (st.hasMoreTokens()) { String token = st.nextToken().trim(); int p = token.indexOf('='); @@ -1352,7 +1366,7 @@ public abstract class NanoHTTPD { * @author LordFokas */ public class CookieHandler implements Iterable<String> { - private HashMap<String, String> cookies = new HashMap<String, String>(); + private ArrayMap<String, String> cookies = new ArrayMap<String, String>(); private ArrayList<Cookie> queue = new ArrayList<Cookie>(); public CookieHandler(Map<String, String> httpHeaders) { diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java index 835f43f40..c1d4bc4fd 100644 --- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java +++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java @@ -6,6 +6,7 @@ import android.os.StrictMode; import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.fonts.FontAwesomeModule; +import com.joanzapata.iconify.fonts.MaterialModule; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; @@ -62,6 +63,7 @@ public class PodcastApp extends Application { NetworkUtils.init(this); EventDistributor.getInstance(); Iconify.with(new FontAwesomeModule()); + Iconify.with(new MaterialModule()); SPAUtil.sendSPAppsQueryFeedsIntent(this); } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index 017c28dbf..17cd5ace3 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -15,12 +15,12 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; +import android.util.TypedValue; import android.view.ContextMenu; import android.view.MenuInflater; import android.view.MenuItem; @@ -71,7 +71,7 @@ import rx.schedulers.Schedulers; /** * The activity that is shown when the user launches the app. */ -public class MainActivity extends ActionBarActivity implements NavDrawerActivity { +public class MainActivity extends AppCompatActivity implements NavDrawerActivity { private static final String TAG = "MainActivity"; @@ -125,7 +125,13 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); - getSupportActionBar().setElevation(3.0f); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + findViewById(R.id.shadow).setVisibility(View.GONE); + int elevation = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, + getResources().getDisplayMetrics()); + getSupportActionBar().setElevation(elevation); + } currentTitle = getTitle(); @@ -252,10 +258,6 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity builder.create().show(); } - public ActionBar getMainActivtyActionBar() { - return getSupportActionBar(); - } - public boolean isDrawerOpen() { return drawerLayout != null && navDrawer != null && drawerLayout.isDrawerOpen(navDrawer); } @@ -363,10 +365,6 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity getSupportFragmentManager().popBackStack(); } - public Toolbar getToolbar() { - return toolbar; - } - private int getSelectedNavListIndex() { String currentFragment = getLastNavFragment(); if(currentFragment == null) { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java index 7f975b3c8..b02e82f0b 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java @@ -39,7 +39,7 @@ public class StorageErrorActivity extends ActionBarActivity { @Override protected void onResume() { super.onResume(); - if (StorageUtils.storageAvailable(this)) { + if (StorageUtils.storageAvailable()) { leaveErrorState(); } else { registerReceiver(mediaUpdate, new IntentFilter( diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java index e867540e4..16909cbb3 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java @@ -5,6 +5,7 @@ import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.ActivityCompat; import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -22,7 +23,6 @@ import com.joanzapata.iconify.fonts.FontAwesomeIcons; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -58,7 +58,7 @@ public class EpisodesApplyActionFragment extends Fragment { public EpisodesApplyActionFragment() { this.episodes = new ArrayList<>(); - this.idMap = new HashMap<>(); + this.idMap = new ArrayMap<>(); } public void setEpisodes(List<FeedItem> episodes) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java index f6c80aa7c..d979dc382 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java @@ -45,7 +45,7 @@ public class AddFeedFragment extends Fragment { Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes); final MainActivity activity = (MainActivity) getActivity(); - activity.getMainActivtyActionBar().setTitle(R.string.add_feed_label); + activity.getSupportActionBar().setTitle(R.string.add_feed_label); butSearchITunes.setOnClickListener(new View.OnClickListener() { @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index 091f4c843..9ccb0fbe3 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -10,6 +10,7 @@ import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; +import android.support.v7.widget.SimpleItemAnimator; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -303,7 +304,10 @@ public class AllEpisodesFragment extends Fragment { View root = inflater.inflate(fragmentResource, container, false); recyclerView = (RecyclerView) root.findViewById(android.R.id.list); - recyclerView.getItemAnimator().setSupportsChangeAnimations(false); + RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); + if (animator instanceof SimpleItemAnimator) { + ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); + } layoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(layoutManager); recyclerView.setHasFixedSize(true); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index 10d56d5cf..58cd6c40a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -4,35 +4,33 @@ import android.annotation.TargetApi; import android.content.ClipData; import android.content.Context; import android.content.Intent; -import android.content.res.TypedArray; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.util.Pair; -import android.support.v7.widget.PopupMenu; -import android.support.v7.widget.Toolbar; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; -import android.widget.Button; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; +import com.joanzapata.iconify.Iconify; +import com.joanzapata.iconify.widget.IconButton; import org.apache.commons.lang3.ArrayUtils; @@ -101,7 +99,6 @@ public class ItemFragment extends Fragment { private List<Downloader> downloaderList; private ViewGroup root; - private View header; private WebView webvDescription; private TextView txtvTitle; private TextView txtvDuration; @@ -109,10 +106,9 @@ public class ItemFragment extends Fragment { private ImageView imgvCover; private ProgressBar progbarDownload; private ProgressBar progbarLoading; - private Button butAction1; - private Button butAction2; - private ImageButton butMore; - private PopupMenu popupMenu; + private IconButton butAction1; + private IconButton butAction2; + private Menu popupMenu; private Subscription subscription; @@ -125,7 +121,7 @@ public class ItemFragment extends Fragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); - setHasOptionsMenu(false); + setHasOptionsMenu(true); itemID = getArguments().getLong(ARG_FEEDITEM, -1); } @@ -134,15 +130,12 @@ public class ItemFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); - ((MainActivity) getActivity()).getSupportActionBar().setTitle(""); - Toolbar toolbar = ((MainActivity) getActivity()).getToolbar(); View layout = inflater.inflate(R.layout.feeditem_fragment, container, false); - header = inflater.inflate(R.layout.feeditem_fragment_header, toolbar, false); root = (ViewGroup) layout.findViewById(R.id.content_root); - txtvTitle = (TextView) header.findViewById(R.id.txtvTitle); - txtvDuration = (TextView) header.findViewById(R.id.txtvDuration); - txtvPublished = (TextView) header.findViewById(R.id.txtvPublished); + txtvTitle = (TextView) layout.findViewById(R.id.txtvTitle); + txtvDuration = (TextView) layout.findViewById(R.id.txtvDuration); + txtvPublished = (TextView) layout.findViewById(R.id.txtvPublished); if (Build.VERSION.SDK_INT >= 14) { // ellipsize is causing problems on old versions, see #448 txtvTitle.setEllipsize(TextUtils.TruncateAt.END); } @@ -172,81 +165,43 @@ public class ItemFragment extends Fragment { }); registerForContextMenu(webvDescription); - imgvCover = (ImageView) header.findViewById(R.id.imgvCover); - progbarDownload = (ProgressBar) header.findViewById(R.id.progbarDownload); + imgvCover = (ImageView) layout.findViewById(R.id.imgvCover); + progbarDownload = (ProgressBar) layout.findViewById(R.id.progbarDownload); progbarLoading = (ProgressBar) layout.findViewById(R.id.progbarLoading); - butAction1 = (Button) header.findViewById(R.id.butAction1); - butAction2 = (Button) header.findViewById(R.id.butAction2); - butMore = (ImageButton) header.findViewById(R.id.butMoreActions); - popupMenu = new PopupMenu(getActivity(), butMore); - - butAction1.setOnClickListener(new View.OnClickListener() { - DefaultActionButtonCallback actionButtonCallback = new DefaultActionButtonCallback(getActivity()); - - @Override - - public void onClick(View v) { - if (item == null) { - return; - } - actionButtonCallback.onActionButtonPressed(item); - FeedMedia media = item.getMedia(); - if (media != null && media.isDownloaded()) { - // playback was started, dialog should close itself - ((MainActivity) getActivity()).dismissChildFragment(); - } - } - } - ); + butAction1 = (IconButton) layout.findViewById(R.id.butAction1); + butAction2 = (IconButton) layout.findViewById(R.id.butAction2); - butAction2.setOnClickListener(v -> { - if (item == null) { - return; - } - - if (item.hasMedia()) { - FeedMedia media = item.getMedia(); - if (!media.isDownloaded()) { - DBTasks.playMedia(getActivity(), media, true, true, true); - ((MainActivity) getActivity()).dismissChildFragment(); - } else { - DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId()); - } - } else if (item.getLink() != null) { - Uri uri = Uri.parse(item.getLink()); - getActivity().startActivity(new Intent(Intent.ACTION_VIEW, uri)); - } + butAction1.setOnClickListener(v -> { + if (item == null) { + return; } - ); - - butMore.setOnClickListener(v -> { - if (item == null) { - return; - } - popupMenu.getMenu().clear(); - popupMenu.inflate(R.menu.feeditem_options); - if (item.hasMedia()) { - FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue); - } else { - // these are already available via button1 and button2 - FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue, - R.id.mark_read_item, R.id.visit_website_item); - } - popupMenu.show(); + DefaultActionButtonCallback actionButtonCallback = new DefaultActionButtonCallback(getActivity()); + actionButtonCallback.onActionButtonPressed(item); + FeedMedia media = item.getMedia(); + if (media != null && media.isDownloaded()) { + // playback was started, dialog should close itself + ((MainActivity) getActivity()).dismissChildFragment(); } - ); + }); - popupMenu.setOnMenuItemClickListener(menuItem -> { + butAction2.setOnClickListener(v -> { + if (item == null) { + return; + } - try { - return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item); - } catch (DownloadRequestException e) { - e.printStackTrace(); - Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show(); - return true; + if (item.hasMedia()) { + FeedMedia media = item.getMedia(); + if (!media.isDownloaded()) { + DBTasks.playMedia(getActivity(), media, true, true, true); + ((MainActivity) getActivity()).dismissChildFragment(); + } else { + DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId()); } + } else if (item.getLink() != null) { + Uri uri = Uri.parse(item.getLink()); + getActivity().startActivity(new Intent(Intent.ACTION_VIEW, uri)); } - ); + }); return layout; } @@ -254,8 +209,6 @@ public class ItemFragment extends Fragment { @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - Toolbar toolbar = ((MainActivity) getActivity()).getToolbar(); - toolbar.addView(header); load(); } @@ -279,7 +232,6 @@ public class ItemFragment extends Fragment { @Override public void onDestroyView() { super.onDestroyView(); - resetViewState(); if(subscription != null) { subscription.unsubscribe(); } @@ -289,15 +241,37 @@ public class ItemFragment extends Fragment { } } - private void resetViewState() { - Toolbar toolbar = ((MainActivity) getActivity()).getToolbar(); - toolbar.removeView(header); + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if(item == null) { + return; + } + inflater.inflate(R.menu.feeditem_options, menu); + popupMenu = menu; + if (item.hasMedia()) { + FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue); + } else { + // these are already available via button1 and button2 + FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue, + R.id.mark_read_item, R.id.visit_website_item); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem menuItem) { + try { + return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item); + } catch (DownloadRequestException e) { + e.printStackTrace(); + Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show(); + return true; + } } private final FeedItemMenuHandler.MenuInterface popupMenuInterface = new FeedItemMenuHandler.MenuInterface() { @Override public void setItemVisibility(int id, boolean visible) { - MenuItem item = popupMenu.getMenu().findItem(id); + MenuItem item = popupMenu.findItem(id); if (item != null) { item.setVisible(visible); } @@ -319,7 +293,7 @@ public class ItemFragment extends Fragment { Log.d(TAG, "updateAppearance item is null"); return; } - + getActivity().supportInvalidateOptionsMenu(); txtvTitle.setText(item.getTitle()); if (item.getPubDate() != null) { @@ -347,54 +321,55 @@ public class ItemFragment extends Fragment { } FeedMedia media = item.getMedia(); + String butAction1Icon = null; + int butAction1Text = 0; + String butAction2Icon = null; + int butAction2Text = 0; if (media == null) { - TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.navigation_accept, - R.attr.location_web_site}); - if (!item.isPlayed()) { - butAction1.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(0), null, null, null); - butAction1.setText(getActivity().getString(R.string.mark_read_label)); - butAction1.setVisibility(View.VISIBLE); - } else { - butAction1.setVisibility(View.INVISIBLE); + butAction1Icon = "{fa-check 24sp}"; + butAction1Text = R.string.mark_read_label; } - if (item.getLink() != null) { - butAction2.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(1), null, null, null); - butAction2.setText(getActivity().getString(R.string.visit_website_label)); - } else { - butAction2.setEnabled(false); + butAction2Icon = "{ma-web 24sp}"; + butAction2Text = R.string.visit_website_label; } - - drawables.recycle(); - } else {if(media.getDuration() > 0) { + } else { + if(media.getDuration() > 0) { txtvDuration.setText(Converter.getDurationStringLong(media.getDuration())); } - boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media); - TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.av_play, - R.attr.av_download, R.attr.action_stream, R.attr.content_discard, R.attr.navigation_cancel}); - if (!media.isDownloaded()) { - butAction2.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(2), null, null, null); - butAction2.setText(getActivity().getString(R.string.stream_label)); + butAction2Icon = "{md-settings-input-antenna 24sp}"; + butAction2Text = R.string.stream_label; } else { - butAction2.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(3), null, null, null); - butAction2.setText(getActivity().getString(R.string.remove_episode_lable)); + butAction2Icon = "{md-delete 24sp}"; + butAction2Text = R.string.remove_label; } - if (isDownloading) { - butAction1.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(4), null, null, null); - butAction1.setText(getActivity().getString(R.string.cancel_download_label)); + butAction1Icon = "{md-cancel 24sp}"; + butAction1Text = R.string.cancel_label; } else if (media.isDownloaded()) { - butAction1.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(0), null, null, null); - butAction1.setText(getActivity().getString(R.string.play_label)); + butAction1Icon = "{md-play-arrow 24sp}"; + butAction1Text = R.string.play_label; } else { - butAction1.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(1), null, null, null); - butAction1.setText(getActivity().getString(R.string.download_label)); + butAction1Icon = "{md-file-download 24sp}"; + butAction1Text = R.string.download_label; } - - drawables.recycle(); + } + if(butAction1Icon != null && butAction1Text != 0) { + butAction1.setText(butAction1Icon +"\u0020\u0020" + getActivity().getString(butAction1Text)); + Iconify.addIcons(butAction1); + butAction1.setVisibility(View.VISIBLE); + } else { + butAction1.setVisibility(View.INVISIBLE); + } + if(butAction2Icon != null && butAction2Text != 0) { + butAction2.setText(butAction2Icon +"\u0020\u0020" + getActivity().getString(butAction2Text)); + Iconify.addIcons(butAction2); + butAction2.setVisibility(View.VISIBLE); + } else { + butAction2.setVisibility(View.INVISIBLE); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java index fbe2274a3..bc5024426 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -12,7 +12,6 @@ import android.os.Bundle; import android.support.v4.app.ListFragment; import android.support.v4.util.Pair; import android.support.v4.view.MenuItemCompat; -import android.support.v7.app.ActionBarActivity; import android.support.v7.widget.SearchView; import android.util.Log; import android.view.ContextMenu; @@ -145,34 +144,26 @@ public class ItemlistFragment extends ListFragment { @Override public void onStart() { super.onStart(); - EventDistributor.getInstance().register(contentUpdate); - EventBus.getDefault().registerSticky(this); if (viewsCreated && itemsLoaded) { onFragmentLoaded(); } } @Override - public void onStop() { - super.onStop(); - EventDistributor.getInstance().unregister(contentUpdate); - EventBus.getDefault().unregister(this); - if(subscription != null) { - subscription.unsubscribe(); - } - } - - @Override public void onResume() { super.onResume(); - Log.d(TAG, "onResume()"); + EventDistributor.getInstance().register(contentUpdate); + EventBus.getDefault().registerSticky(this); + ((MainActivity)getActivity()).getSupportActionBar().setTitle(""); updateProgressBarVisibility(); loadItems(); } @Override - public void onDetach() { - super.onDetach(); + public void onPause() { + super.onPause(); + EventDistributor.getInstance().unregister(contentUpdate); + EventBus.getDefault().unregister(this); if(subscription != null) { subscription.unsubscribe(); } @@ -368,7 +359,6 @@ public class ItemlistFragment extends ListFragment { @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(""); registerForContextMenu(getListView()); @@ -382,7 +372,9 @@ public class ItemlistFragment extends ListFragment { public void onListItemClick(ListView l, View v, int position, long id) { FeedItem selection = adapter.getItem(position - l.getHeaderViewsCount()); if (selection != null) { - ((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(selection.getId())); + MainActivity activity = (MainActivity) getActivity(); + activity.loadChildFragment(ItemFragment.newInstance(selection.getId())); + activity.getSupportActionBar().setTitle(feed.getTitle()); } } @@ -547,15 +539,12 @@ public class ItemlistFragment extends ListFragment { .dontAnimate() .into(imgvCover); - butShowInfo.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (viewsCreated && itemsLoaded) { - Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class); - startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID, - feed.getId()); - startActivity(startIntent); - } + butShowInfo.setOnClickListener(v -> { + if (viewsCreated && itemsLoaded) { + Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class); + startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID, + feed.getId()); + startActivity(startIntent); } }); } @@ -573,16 +562,13 @@ public class ItemlistFragment extends ListFragment { View header = inflater.inflate(R.layout.more_content_list_footer, lv, false); lv.addFooterView(header); listFooter = new MoreContentListFooterUtil(header); - listFooter.setClickListener(new MoreContentListFooterUtil.Listener() { - @Override - public void onClick() { - if (feed != null) { - try { - DBTasks.loadNextPageOfFeed(getActivity(), feed, false); - } catch (DownloadRequestException e) { - e.printStackTrace(); - DownloadRequestErrorDialogCreator.newRequestErrorDialog(getActivity(), e.getMessage()); - } + listFooter.setClickListener(() -> { + if (feed != null) { + try { + DBTasks.loadNextPageOfFeed(getActivity(), feed, false); + } catch (DownloadRequestException e) { + e.printStackTrace(); + DownloadRequestErrorDialogCreator.newRequestErrorDialog(getActivity(), e.getMessage()); } } }); @@ -629,7 +615,6 @@ public class ItemlistFragment extends ListFragment { if(subscription != null) { subscription.unsubscribe(); } - subscription = Observable.fromCallable(() -> loadData()) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java index 72704245f..e92df4885 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java @@ -2,21 +2,20 @@ package de.danoeh.antennapod.fragment; import android.content.Intent; import android.content.res.Resources; -import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v7.widget.SearchView; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.GridView; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.util.EntityUtils; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -30,13 +29,23 @@ import java.util.List; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.OnlineFeedViewActivity; import de.danoeh.antennapod.adapter.itunes.ItunesAdapter; +import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; +import rx.Observable; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; import static de.danoeh.antennapod.adapter.itunes.ItunesAdapter.Podcast; //Searches iTunes store for given string and displays results in a list public class ItunesSearchFragment extends Fragment { - final String TAG = "ItunesSearchFragment"; + + private static final String TAG = "ItunesSearchFragment"; + + private static final String API_URL = "https://itunes.apple.com/search?media=podcast&term=%s"; + /** * Search input field */ @@ -52,6 +61,8 @@ public class ItunesSearchFragment extends Fragment { */ private List<Podcast> searchResults; + private Subscription subscription; + /** * Replace adapter data with provided search results from SearchTask. * @param result List of Podcast objects containing search results @@ -117,7 +128,7 @@ public class ItunesSearchFragment extends Fragment { //This prevents onQueryTextSubmit() from being called twice when keyboard is used //to submit the query. searchView.clearFocus(); - new SearchTask(s).execute(); + search(s); return false; } @@ -137,77 +148,59 @@ public class ItunesSearchFragment extends Fragment { return view; } - /** - * Search the iTunes store for podcasts using the given query - */ - class SearchTask extends AsyncTask<Void,Void,Void> { - /** - * Incomplete iTunes API search URL - */ - final String apiUrl = "https://itunes.apple.com/search?media=podcast&term=%s"; - - /** - * Search terms - */ - final String query; - - /** - * Search result - */ - final List<Podcast> taskData = new ArrayList<>(); - - /** - * Constructor - * - * @param query Search string - */ - public SearchTask(String query) { - String encodedQuery = null; - try { - encodedQuery = URLEncoder.encode(query, "UTF-8"); - } catch(UnsupportedEncodingException e) { - // this won't ever be thrown - } - if(encodedQuery != null) { - this.query = encodedQuery; - } else { - this.query = query; // failsafe - } - } - - //Get the podcast data - @Override - protected Void doInBackground(Void... params) { - - //Spaces in the query need to be replaced with '+' character. - String formattedUrl = String.format(apiUrl, query).replace(' ', '+'); - - HttpClient client = new DefaultHttpClient(); - HttpGet get = new HttpGet(formattedUrl); - - try { - HttpResponse response = client.execute(get); - String resultString = EntityUtils.toString(response.getEntity()); - JSONObject result = new JSONObject(resultString); - JSONArray j = result.getJSONArray("results"); - - for (int i = 0; i < j.length(); i++){ - JSONObject podcastJson = j.getJSONObject(i); - Podcast podcast = new Podcast(podcastJson); - taskData.add(podcast); - } - - } catch (IOException | JSONException e) { - e.printStackTrace(); - } - return null; - } - - //Save the data and update the list - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - updateData(taskData); + private void search(String query) { + if (subscription != null) { + subscription.unsubscribe(); } + subscription = rx.Observable.create((Observable.OnSubscribe<List<Podcast>>) subscriber -> { + String encodedQuery = null; + try { + encodedQuery = URLEncoder.encode(query, "UTF-8"); + } catch (UnsupportedEncodingException e) { + // this won't ever be thrown + } + if (encodedQuery == null) { + encodedQuery = query; // failsafe + } + + //Spaces in the query need to be replaced with '+' character. + String formattedUrl = String.format(API_URL, query).replace(' ', '+'); + + OkHttpClient client = AntennapodHttpClient.getHttpClient(); + Request.Builder httpReq = new Request.Builder() + .url(formattedUrl) + .header("User-Agent", ClientConfig.USER_AGENT); + List<Podcast> podcasts = new ArrayList<>(); + try { + Response response = client.newCall(httpReq.build()).execute(); + + if(response.isSuccessful()) { + String resultString = response.body().string(); + JSONObject result = new JSONObject(resultString); + JSONArray j = result.getJSONArray("results"); + + for (int i = 0; i < j.length(); i++) { + JSONObject podcastJson = j.getJSONObject(i); + Podcast podcast = new Podcast(podcastJson); + podcasts.add(podcast); + } + } + else { + subscriber.onError(new IOException("Unexpected error: " + response)); + } + } catch (IOException | JSONException e) { + Log.e(TAG, Log.getStackTraceString(e)); + } + subscriber.onNext(podcasts); + subscriber.onCompleted(); + }) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(podcasts -> { + updateData(podcasts); + }, error -> { + Log.e(TAG, Log.getStackTraceString(error)); + }); } + } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index 85586962f..64e3a7da7 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -1,6 +1,6 @@ package de.danoeh.antennapod.fragment; -import android.app.Activity; +import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; import android.support.v4.app.ListFragment; @@ -14,7 +14,6 @@ import android.view.View; import android.widget.ListView; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; @@ -50,16 +49,13 @@ public class PlaybackHistoryFragment extends ListFragment { private boolean itemsLoaded = false; private boolean viewsCreated = false; - private AtomicReference<Activity> activity = new AtomicReference<Activity>(); - private List<Downloader> downloaderList; private Subscription subscription; @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - this.activity.set(activity); + public void onAttach(Context context) { + super.onAttach(context); if (viewsCreated && itemsLoaded) { onFragmentLoaded(); } @@ -123,7 +119,6 @@ public class PlaybackHistoryFragment extends ListFragment { if(subscription != null) { subscription.unsubscribe(); } - activity.set(null); } @Override @@ -138,7 +133,7 @@ public class PlaybackHistoryFragment extends ListFragment { DownloaderUpdate update = event.update; downloaderList = update.downloaders; if (adapter != null) { - adapter.notifyDataSetChanged(); + adapter.notifyDataSetChanged(); } } @@ -210,7 +205,8 @@ public class PlaybackHistoryFragment extends ListFragment { // played items shoudln't be transparent for this fragment since, *all* items // in this fragment will, by definition, be played. So it serves no purpose and can make // it harder to read. - adapter = new FeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(activity.get()), true, false); + adapter = new FeedItemlistAdapter(getActivity(), itemAccess, + new DefaultActionButtonCallback(getActivity()), true, false); setListAdapter(adapter); } setListShown(true); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java index 1271887b1..cc6b44f6a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java @@ -10,6 +10,7 @@ import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; +import android.support.v7.widget.SimpleItemAnimator; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.view.LayoutInflater; @@ -365,7 +366,10 @@ public class QueueFragment extends Fragment { View root = inflater.inflate(R.layout.queue_fragment, container, false); infoBar = (TextView) root.findViewById(R.id.info_bar); recyclerView = (RecyclerView) root.findViewById(R.id.recyclerView); - recyclerView.getItemAnimator().setSupportsChangeAnimations(false); + RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); + if (animator instanceof SimpleItemAnimator) { + ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); + } layoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(layoutManager); recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build()); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java index e2450f03d..d39829260 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java @@ -45,7 +45,7 @@ public class TagFragment extends PodcastListFragment { @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - ((MainActivity) getActivity()).getMainActivtyActionBar().setTitle(tag.getTitle()); + ((MainActivity) getActivity()).getSupportActionBar().setTitle(tag.getTitle()); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java index 5bd567a2f..338f02e61 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java @@ -80,7 +80,7 @@ public class TagListFragment extends ListFragment { @Override public void onResume() { super.onResume(); - ((MainActivity) getActivity()).getMainActivtyActionBar().setTitle(R.string.add_feed_label); + ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.add_feed_label); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/SwitchCompatPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/SwitchCompatPreference.java new file mode 100644 index 000000000..10c11b88e --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/preferences/SwitchCompatPreference.java @@ -0,0 +1,37 @@ +package de.danoeh.antennapod.preferences; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.preference.CheckBoxPreference; +import android.util.AttributeSet; + +import de.danoeh.antennapod.R; + +public class SwitchCompatPreference extends CheckBoxPreference { + + public SwitchCompatPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public SwitchCompatPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + public SwitchCompatPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public SwitchCompatPreference(Context context) { + super(context); + init(); + } + + private void init() { + setWidgetLayoutResource(R.layout.preference_switch_layout); + } +}
\ No newline at end of file diff --git a/app/src/main/res/drawable/shadow.xml b/app/src/main/res/drawable/shadow.xml new file mode 100644 index 000000000..fc5110e0b --- /dev/null +++ b/app/src/main/res/drawable/shadow.xml @@ -0,0 +1,7 @@ +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <gradient + android:startColor="@android:color/transparent" + android:endColor="#40000000" + android:angle="90" /> +</shape> diff --git a/app/src/main/res/layout/feeditem_fragment.xml b/app/src/main/res/layout/feeditem_fragment.xml index 5e1b580d2..3dd4e134d 100644 --- a/app/src/main/res/layout/feeditem_fragment.xml +++ b/app/src/main/res/layout/feeditem_fragment.xml @@ -1,13 +1,141 @@ <?xml version="1.0" encoding="utf-8"?> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/content_root" android:layout_width="match_parent" android:layout_height="match_parent"> + <LinearLayout + android:id="@+id/header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:background="?attr/colorPrimary" + android:gravity="center_horizontal" + android:orientation="vertical" + tools:background="@android:color/darker_gray"> + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:orientation="horizontal" + android:layout_marginTop="16dp" + android:layout_marginLeft="16dp" + android:layout_marginRight="16dp"> + + <ImageView + android:id="@+id/imgvCover" + android:layout_width="50dp" + android:layout_height="50dp" + android:layout_gravity="center_vertical" + android:contentDescription="@string/cover_label" + android:gravity="center_vertical" + tools:src="@drawable/ic_stat_antenna_default" + tools:background="@android:color/holo_green_dark" /> + + <TextView + android:id="@+id/txtvPublished" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_alignParentRight="true" + android:layout_marginLeft="8dp" + tools:text="Jan\n23" + tools:background="@android:color/holo_green_dark" + android:layout_below="@+id/txtvTitle"/> + + <TextView + android:id="@+id/txtvTitle" + style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignTop="@id/imgvCover" + android:layout_marginLeft="16dp" + android:layout_toLeftOf="@id/txtvPublished" + android:layout_toRightOf="@id/imgvCover" + android:includeFontPadding="false" + android:maxLines="5" + tools:text="Podcast title" + tools:background="@android:color/holo_green_dark" /> + + <TextView + android:id="@+id/txtvDuration" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toRightOf="@id/imgvCover" + android:layout_below="@id/txtvTitle" + android:layout_marginLeft="16dp" + tools:text="00:42:23" + tools:background="@android:color/holo_green_dark"/> + + </RelativeLayout> + + <ProgressBar + android:id="@+id/progbarDownload" + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginLeft="16dp" + android:layout_marginRight="16dp" + android:visibility="gone" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="16dp" + android:layout_marginRight="16dp" + android:layout_marginBottom="8dp" + android:orientation="horizontal" + tools:background="@android:color/holo_blue_bright"> + + <com.joanzapata.iconify.widget.IconButton + android:id="@+id/butAction1" + android:layout_width="0dp" + android:layout_height="48dp" + android:layout_gravity="center_vertical" + android:layout_marginRight="8dp" + android:layout_weight="1" + android:background="?attr/selectableItemBackground" + android:ellipsize="end" + android:gravity="center" + android:textColor="?android:attr/textColorPrimary" + android:textSize="@dimen/text_size_small" + tools:text="Button 1" + tools:background="@android:color/holo_red_light" /> + + <com.joanzapata.iconify.widget.IconButton + android:id="@+id/butAction2" + android:layout_width="0dp" + android:layout_height="48dp" + android:layout_gravity="center_vertical" + android:layout_marginLeft="8dp" + android:layout_weight="1" + android:background="?attr/selectableItemBackground" + android:ellipsize="end" + android:gravity="center" + android:textColor="?android:attr/textColorPrimary" + android:textSize="@dimen/text_size_small" + tools:text="Button 2" + tools:background="@android:color/holo_orange_dark" /> + + </LinearLayout> + + <View + android:layout_width="match_parent" + android:layout_height="2dp" + android:background="@color/light_gray"/> + + </LinearLayout> <WebView android:id="@+id/webvDescription" android:layout_width="match_parent" + android:layout_below="@id/header" android:layout_height="match_parent" android:foreground="?android:windowContentOverlay" /> @@ -22,4 +150,4 @@ android:layout_gravity="center" android:indeterminate="true" /> </FrameLayout> -</FrameLayout>
\ No newline at end of file +</RelativeLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/feeditem_fragment_header.xml b/app/src/main/res/layout/feeditem_fragment_header.xml deleted file mode 100644 index 2534dddbe..000000000 --- a/app/src/main/res/layout/feeditem_fragment_header.xml +++ /dev/null @@ -1,136 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/header" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:background="?attr/colorPrimary" - android:gravity="center_horizontal" - android:orientation="vertical" - tools:background="@android:color/darker_gray"> - - - <RelativeLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:orientation="horizontal" - android:paddingBottom="0dp"> - - <ImageView - android:id="@+id/imgvCover" - android:layout_width="50dp" - android:layout_height="50dp" - android:layout_gravity="center_vertical" - android:layout_marginBottom="8dp" - android:layout_marginTop="16dp" - android:contentDescription="@string/cover_label" - android:gravity="center_vertical" - tools:src="@drawable/ic_stat_antenna_default" - tools:background="@android:color/holo_green_dark" /> - - - <ImageButton - android:id="@+id/butMoreActions" - android:layout_width="48dp" - android:layout_height="48dp" - android:layout_alignParentRight="true" - android:layout_alignParentTop="true" - android:background="?attr/selectableItemBackground" - android:contentDescription="@string/butAction_label" - android:paddingTop="4dp" - android:src="?attr/ic_action_overflow" - tools:src="@drawable/ic_info_white_24dp" - tools:background="@android:color/holo_green_dark" /> - - <TextView - android:id="@+id/txtvTitle" - style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_centerVertical="true" - android:layout_marginBottom="8dp" - android:layout_marginLeft="16dp" - android:layout_marginRight="8dp" - android:layout_marginTop="16dp" - android:layout_toLeftOf="@id/butMoreActions" - android:layout_toRightOf="@id/imgvCover" - android:maxLines="5" - tools:text="Podcast title" - tools:background="@android:color/holo_green_dark" /> - - <TextView - android:id="@+id/txtvDuration" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/imgvCover" - android:layout_below="@id/txtvTitle" - android:layout_marginLeft="16dp" - tools:text="00:42:23" - tools:background="@android:color/holo_green_dark"/> - - <TextView - android:id="@+id/txtvPublished" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toLeftOf="@id/butMoreActions" - android:layout_marginRight="8dp" - tools:text="Jan 23" - tools:background="@android:color/holo_green_dark" - android:layout_below="@+id/txtvTitle"/> - - </RelativeLayout> - - <ProgressBar - android:id="@+id/progbarDownload" - style="?android:attr/progressBarStyleHorizontal" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="16dp" - android:layout_marginRight="16dp" - android:visibility="invisible" /> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="?attr/actionBarSize" - android:layout_marginRight="8dp" - android:orientation="horizontal" - tools:background="@android:color/holo_blue_bright"> - - <Button - android:id="@+id/butAction1" - android:layout_width="0dp" - android:layout_height="48dp" - android:layout_gravity="center_vertical" - android:layout_marginRight="8dp" - android:layout_weight="1" - android:background="?attr/selectableItemBackground" - android:ellipsize="end" - android:paddingTop="4dp" - android:textColor="?android:attr/textColorPrimary" - android:textSize="@dimen/text_size_small" - tools:text="Button 1" - tools:background="@android:color/holo_red_light" /> - - <Button - android:id="@+id/butAction2" - android:layout_width="0dp" - android:layout_height="48dp" - android:layout_gravity="center_vertical" - android:layout_marginLeft="8dp" - android:layout_weight="1" - android:background="?attr/selectableItemBackground" - android:ellipsize="end" - android:paddingTop="4dp" - android:textColor="?android:attr/textColorPrimary" - android:textSize="@dimen/text_size_small" - tools:text="Button 2" - tools:background="@android:color/holo_orange_dark" /> - - </LinearLayout> - - -</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml index 46be5bc5f..c05132b42 100644 --- a/app/src/main/res/layout/main.xml +++ b/app/src/main/res/layout/main.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" +<android.support.v4.widget.DrawerLayout + xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" @@ -10,7 +11,6 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - <FrameLayout android:id="@+id/playerFragment" android:layout_width="match_parent" @@ -27,6 +27,14 @@ android:background="?attr/colorPrimary" android:minHeight="?attr/actionBarSize" tools:background="@android:color/holo_blue_dark" /> + + <View + android:id="@+id/shadow" + android:layout_width="match_parent" + android:layout_height="4dp" + android:layout_below="@id/toolbar" + android:background="@drawable/shadow" /> + <FrameLayout android:id="@+id/main_view" android:layout_width="match_parent" diff --git a/app/src/main/res/layout/preference_switch_layout.xml b/app/src/main/res/layout/preference_switch_layout.xml new file mode 100644 index 000000000..54fa74061 --- /dev/null +++ b/app/src/main/res/layout/preference_switch_layout.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.v7.widget.SwitchCompat + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/checkbox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@null" + android:clickable="false" + android:focusable="false" />
\ No newline at end of file diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index e9e9d48f7..cdb582898 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1,5 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> +<PreferenceScreen + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> <PreferenceCategory android:title="@string/user_interface_label"> <com.afollestad.materialdialogs.prefs.MaterialListPreference @@ -8,7 +10,8 @@ android:title="@string/pref_set_theme_title" android:key="prefTheme" android:summary="@string/pref_set_theme_sum" - android:defaultValue="0"/> + android:defaultValue="0" + app:useStockLayout="true"/> <PreferenceScreen android:key="prefDrawerSettings" android:summary="@string/pref_nav_drawer_sum" @@ -23,34 +26,36 @@ android:title="@string/pref_nav_drawer_feed_order_title" android:key="prefDrawerFeedOrder" android:summary="@string/pref_nav_drawer_feed_order_sum" - android:defaultValue="0"/> + android:defaultValue="0" + app:useStockLayout="true"/> <com.afollestad.materialdialogs.prefs.MaterialListPreference android:entryValues="@array/nav_drawer_feed_counter_values" android:entries="@array/nav_drawer_feed_counter_options" android:title="@string/pref_nav_drawer_feed_counter_title" android:key="prefDrawerFeedIndicator" android:summary="@string/pref_nav_drawer_feed_counter_sum" - android:defaultValue="0"/> + android:defaultValue="0" + app:useStockLayout="true"/> </PreferenceScreen> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="true" android:key="prefExpandNotify" android:summary="@string/pref_expandNotify_sum" android:title="@string/pref_expandNotify_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="true" android:enabled="true" android:key="prefPersistNotify" android:summary="@string/pref_persistNotify_sum" android:title="@string/pref_persistNotify_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="true" android:enabled="true" android:key="prefLockscreenBackground" android:summary="@string/pref_lockscreen_background_sum" android:title="@string/pref_lockscreen_background_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="true" android:enabled="true" android:key="prefShowDownloadReport" @@ -59,7 +64,7 @@ </PreferenceCategory> <PreferenceCategory android:title="@string/queue_label"> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="true" android:key="prefQueueAddToFront" @@ -69,45 +74,45 @@ </PreferenceCategory> <PreferenceCategory android:title="@string/playback_pref"> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="true" android:enabled="true" android:key="prefPauseOnHeadsetDisconnect" android:summary="@string/pref_pauseOnDisconnect_sum" android:title="@string/pref_pauseOnHeadsetDisconnect_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="true" android:enabled="true" android:dependency="prefPauseOnHeadsetDisconnect" android:key="prefUnpauseOnHeadsetReconnect" android:summary="@string/pref_unpauseOnHeadsetReconnect_sum" android:title="@string/pref_unpauseOnHeadsetReconnect_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="true" android:dependency="prefPauseOnHeadsetDisconnect" android:key="prefUnpauseOnBluetoothReconnect" android:summary="@string/pref_unpauseOnBluetoothReconnect_sum" android:title="@string/pref_unpauseOnBluetoothReconnect_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="true" android:key="prefHardwareForwardButtonSkips" android:summary="@string/pref_hardwareForwardButtonSkips_sum" android:title="@string/pref_hardwareForwardButtonSkips_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="true" android:enabled="true" android:key="prefFollowQueue" android:summary="@string/pref_followQueue_sum" android:title="@string/pref_followQueue_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="true" android:enabled="true" android:key="prefSkipKeepsEpisode" android:summary="@string/pref_skip_keeps_episodes_sum" android:title="@string/pref_skip_keeps_episodes_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="true" android:key="prefAutoDelete" @@ -119,19 +124,20 @@ android:entryValues="@array/smart_mark_as_played_values" android:key="prefSmartMarkAsPlayedSecs" android:summary="@string/pref_smart_mark_as_played_sum" - android:title="@string/pref_smart_mark_as_played_title"/> + android:title="@string/pref_smart_mark_as_played_title" + app:useStockLayout="true"/> <Preference android:key="prefPlaybackSpeedLauncher" android:summary="@string/pref_playback_speed_sum" android:title="@string/pref_playback_speed_title" /> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="true" android:key="prefPauseForFocusLoss" android:summary="@string/pref_pausePlaybackForFocusLoss_sum" android:title="@string/pref_pausePlaybackForFocusLoss_title" /> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="true" android:enabled="true" android:key="prefResumeAfterCall" @@ -144,46 +150,47 @@ android:key="prefAutoUpdateIntervall" android:summary="@string/pref_autoUpdateIntervallOrTime_sum" android:title="@string/pref_autoUpdateIntervallOrTime_title"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="true" android:key="prefMobileUpdate" android:summary="@string/pref_mobileUpdate_sum" android:title="@string/pref_mobileUpdate_title"/> - <com.afollestad.materialdialogs.prefs.MaterialListPreference android:defaultValue="-1" android:entries="@array/episode_cleanup_entries" android:key="prefEpisodeCleanup" android:title="@string/pref_episode_cleanup_title" android:summary="@string/pref_episode_cleanup_summary" - android:entryValues="@array/episode_cleanup_values"/> - + android:entryValues="@array/episode_cleanup_values" + app:useStockLayout="true"/> <com.afollestad.materialdialogs.prefs.MaterialEditTextPreference android:defaultValue="4" android:inputType="number" android:key="prefParallelDownloads" - android:title="@string/pref_parallel_downloads_title"/> + android:title="@string/pref_parallel_downloads_title" + app:useStockLayout="true"/> <com.afollestad.materialdialogs.prefs.MaterialListPreference android:defaultValue="20" android:entries="@array/episode_cache_size_entries" android:key="prefEpisodeCacheSize" android:title="@string/pref_episode_cache_title" - android:entryValues="@array/episode_cache_size_values"/> + android:entryValues="@array/episode_cache_size_values" + app:useStockLayout="true"/> <PreferenceScreen android:summary="@string/pref_automatic_download_sum" android:key="prefAutoDownloadSettings" android:title="@string/pref_automatic_download_title"> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:key="prefEnableAutoDl" android:title="@string/pref_automatic_download_title" android:defaultValue="false"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:key="prefEnableAutoDownloadOnBattery" android:title="@string/pref_automatic_download_on_battery_title" android:summary="@string/pref_automatic_download_on_battery_sum" android:defaultValue="true"/> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:key="prefEnableAutoDownloadWifiFilter" android:title="@string/pref_autodl_wifi_filter_title" android:summary="@string/pref_autodl_wifi_filter_sum"/> @@ -258,7 +265,7 @@ </PreferenceCategory> <PreferenceCategory android:title="@string/experimental_pref"> - <CheckBoxPreference + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="false" android:key="prefSonic" diff --git a/build.gradle b/build.gradle index a82809ca4..96d4076dd 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { classpath "com.android.tools.build:gradle:1.5.0" - classpath "me.tatarka:gradle-retrolambda:3.2.3" + classpath "me.tatarka:gradle-retrolambda:3.2.4" classpath "me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2" // Exclude the version that the android plugin depends on. @@ -36,27 +36,30 @@ subprojects { } project.ext { - compileSdkVersion = 22 - buildToolsVersion = "22.0.1" + compileSdkVersion = 23 + buildToolsVersion = "23.0.2" minSdkVersion = 10 - targetSdkVersion = 22 + targetSdkVersion = 23 - supportVersion = "22.2.1" + supportVersion = "23.1.1" commonsioVersion = "2.4" commonslangVersion = "3.4" eventbusVersion = "2.4.0" flattr4jVersion = "2.12" glideVersion = "3.6.1" jsoupVersion = "1.7.3" - rxAndroidVersion = "1.0.1" - rxJavaVersion = "1.0.16" - rxJavaRulesVersion = "1.0.16.1" - okhttpVersion = "2.5.0" + iconifyFontawesomeVersion = "2.1.1" + materialDialogsVersion = "0.8.5.3@aar" + recyclerviewFlexibledividerVersion = "1.2.6" + rxAndroidVersion = "1.1.0" + rxJavaVersion = "1.1.0" + rxJavaRulesVersion = "1.1.0.0" + okhttpVersion = "2.7.0" okioVersion = "1.6.0" - audioPlayerVersion = "v1.0.7" + audioPlayerVersion = "v1.0.8" } task wrapper(type: Wrapper) { - gradleVersion = "2.4" + gradleVersion = "2.10" } diff --git a/circle.yml b/circle.yml index abea320a5..4a0170173 100644 --- a/circle.yml +++ b/circle.yml @@ -4,6 +4,10 @@ general: machine: java: version: oraclejdk8 +dependencies: + pre: + - echo y | android update sdk --no-ui --all --filter "tools,platform-tools,android-23" + - echo y | android update sdk --no-ui --all --filter "build-tools-23.0.2" test: override: - ./gradlew assembleDebug -PdisablePreDex
\ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle index 93f6f94db..d8e6b6287 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -46,7 +46,7 @@ dependencies { exclude group: "org.json", module: "json" } compile "commons-io:commons-io:$commonsioVersion" - compile "com.jayway.android.robotium:robotium-solo:5.5.2" + compile "com.jayway.android.robotium:robotium-solo:5.5.3" compile "org.jsoup:jsoup:$jsoupVersion" compile "com.github.bumptech.glide:glide:$glideVersion" compile "com.github.bumptech.glide:okhttp-integration:1.3.1" diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java index d2a13f768..a24e3a485 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java @@ -10,8 +10,6 @@ import com.squareup.okhttp.RequestBody; import com.squareup.okhttp.Response; import com.squareup.okhttp.ResponseBody; -import org.apache.http.HttpStatus; -import org.apache.http.client.ClientProtocolException; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -19,6 +17,7 @@ import org.json.JSONObject; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; @@ -602,10 +601,7 @@ public class GpodnetService { checkStatusCode(response); body = response.body(); result = getStringFromResponseBody(body); - } catch (ClientProtocolException e) { - e.printStackTrace(); - throw new GpodnetServiceException(e); - } catch (IOException e) { + } catch (Exception e) { e.printStackTrace(); throw new GpodnetServiceException(e); } finally { @@ -652,12 +648,12 @@ public class GpodnetService { private void checkStatusCode(@NonNull Response response) throws GpodnetServiceException { int responseCode = response.code(); - if (responseCode != HttpStatus.SC_OK) { - if (responseCode == HttpStatus.SC_UNAUTHORIZED) { + if (responseCode != HttpURLConnection.HTTP_OK) { + if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) { throw new GpodnetServiceAuthenticationException("Wrong username or password"); } else { - throw new GpodnetServiceBadStatusCodeException( - "Bad response code: " + responseCode, responseCode); + throw new GpodnetServiceBadStatusCodeException("Bad response code: " + + responseCode, responseCode); } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeActionPostResponse.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeActionPostResponse.java index e06a88d5c..5f096db14 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeActionPostResponse.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeActionPostResponse.java @@ -1,12 +1,13 @@ package de.danoeh.antennapod.core.gpoddernet.model; +import android.support.v4.util.ArrayMap; + import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import java.util.HashMap; import java.util.Map; public class GpodnetEpisodeActionPostResponse { @@ -36,8 +37,8 @@ public class GpodnetEpisodeActionPostResponse { public static GpodnetEpisodeActionPostResponse fromJSONObject(String objectString) throws JSONException { final JSONObject object = new JSONObject(objectString); final long timestamp = object.getLong("timestamp"); - Map<String, String> updatedUrls = new HashMap<String, String>(); JSONArray urls = object.getJSONArray("update_urls"); + Map<String, String> updatedUrls = new ArrayMap<String, String>(urls.length()); for (int i = 0; i < urls.length(); i++) { JSONArray urlPair = urls.getJSONArray(i); updatedUrls.put(urlPair.getString(0), urlPair.getString(1)); diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetUploadChangesResponse.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetUploadChangesResponse.java index 5a37efa5e..9bd1881e4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetUploadChangesResponse.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetUploadChangesResponse.java @@ -1,10 +1,11 @@ package de.danoeh.antennapod.core.gpoddernet.model; +import android.support.v4.util.ArrayMap; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import java.util.HashMap; import java.util.Map; /** @@ -37,7 +38,7 @@ public class GpodnetUploadChangesResponse { public static GpodnetUploadChangesResponse fromJSONObject(String objectString) throws JSONException { final JSONObject object = new JSONObject(objectString); final long timestamp = object.getLong("timestamp"); - Map<String, String> updatedUrls = new HashMap<String, String>(); + Map<String, String> updatedUrls = new ArrayMap<>(); JSONArray urls = object.getJSONArray("update_urls"); for (int i = 0; i < urls.length(); i++) { JSONArray urlPair = urls.getJSONArray(i); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java index d5660f67e..0b90cef6c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java @@ -8,12 +8,12 @@ import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.support.v4.app.NotificationCompat; +import android.support.v4.util.ArrayMap; import android.util.Log; import android.util.Pair; import java.util.Collection; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -226,7 +226,7 @@ public class GpodnetSyncService extends Service { if(remoteActions.size() == 0) { return; } - Map<Pair<String, String>, GpodnetEpisodeAction> localMostRecentPlayAction = new HashMap<Pair<String, String>, GpodnetEpisodeAction>(); + Map<Pair<String, String>, GpodnetEpisodeAction> localMostRecentPlayAction = new ArrayMap<>(); for(GpodnetEpisodeAction action : localActions) { Pair key = new Pair(action.getPodcast(), action.getEpisode()); GpodnetEpisodeAction mostRecent = localMostRecentPlayAction.get(key); @@ -238,7 +238,7 @@ public class GpodnetSyncService extends Service { } // make sure more recent local actions are not overwritten by older remote actions - Map<Pair<String, String>, GpodnetEpisodeAction> mostRecentPlayAction = new HashMap<Pair<String, String>, GpodnetEpisodeAction>(); + Map<Pair<String, String>, GpodnetEpisodeAction> mostRecentPlayAction = new ArrayMap<>(); for (GpodnetEpisodeAction action : remoteActions) { switch (action.getAction()) { case NEW: diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/APRedirectHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/APRedirectHandler.java deleted file mode 100644 index 3efcf4da8..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/APRedirectHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -package de.danoeh.antennapod.core.service.download; - -import android.util.Log; -import de.danoeh.antennapod.core.BuildConfig; -import org.apache.http.Header; -import org.apache.http.HttpResponse; -import org.apache.http.impl.client.DefaultRedirectHandler; -import org.apache.http.protocol.HttpContext; - -import java.net.URI; - -public class APRedirectHandler extends DefaultRedirectHandler { - // Identifier for logger - private static final String TAG = "APRedirectHandler"; - // Header field, which has to be potentially fixed - private static final String LOC = "Location"; - // Regular expressions for character strings, which should not appear in URLs - private static final String CHi[] = { "\\{", "\\}", "\\|", "\\\\", "\\^", "~", "\\[", "\\]", "\\`"}; - private static final String CHo[] = { "%7B", "%7D", "%7C", "%5C", "%5E", "%7E", "%5B", "%5D", "%60"}; - - /** - * Workaround for broken URLs in redirection. - * Proper solution involves LaxRedirectStrategy() which is not available in - * current API yet. - */ - @Override - public URI getLocationURI(HttpResponse response, HttpContext context) - throws org.apache.http.ProtocolException { - - Header h[] = response.getHeaders(LOC); - if (h.length>0) { - String s = h[0].getValue(); - - // Fix broken URL - for(int i=0; i<CHi.length;i++) - s = s.replaceAll(CHi[i], CHo[i]); - - // If anything had to be fixed, then replace the header - if (!s.equals(h[0].getValue())) - { - if (BuildConfig.DEBUG) - Log.d(TAG, "Original URL: " + h[0].getValue()); - - response.setHeader(LOC, s); - - if (BuildConfig.DEBUG) - Log.d(TAG, "Fixed URL: " + s); - } - } - - // call DefaultRedirectHandler with fixed URL - return super.getLocationURI(response, context); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 9768bd5de..29c44207d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -22,7 +22,6 @@ import android.util.Log; import android.webkit.URLUtil; import org.apache.commons.io.FileUtils; -import org.apache.http.HttpStatus; import org.xml.sax.SAXException; import java.io.File; @@ -187,7 +186,7 @@ public class DownloadService extends Service { if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) { postAuthenticationNotification(downloader.getDownloadRequest()); } else if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR - && Integer.valueOf(status.getReasonDetailed()) == HttpStatus.SC_REQUESTED_RANGE_NOT_SATISFIABLE) { + && Integer.valueOf(status.getReasonDetailed()) == 416) { Log.d(TAG, "Requested invalid range, restarting download from the beginning"); FileUtils.deleteQuietly(new File(downloader.getDownloadRequest().getDestination())); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java index 9f54db477..0b9fba6f7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java @@ -11,7 +11,6 @@ import com.squareup.okhttp.ResponseBody; import com.squareup.okhttp.internal.http.HttpDate; import org.apache.commons.io.IOUtils; -import org.apache.http.HttpStatus; import java.io.BufferedInputStream; import java.io.File; @@ -162,7 +161,7 @@ public class HttpDownloader extends Downloader { return; } - if (!StorageUtils.storageAvailable(ClientConfig.applicationCallbacks.getApplicationInstance())) { + if (!StorageUtils.storageAvailable()) { onFail(DownloadError.ERROR_DEVICE_NOT_FOUND, null); return; } @@ -171,7 +170,7 @@ public class HttpDownloader extends Downloader { String contentRangeHeader = (fileExists) ? response.header("Content-Range") : null; - if (fileExists && response.code() == HttpStatus.SC_PARTIAL_CONTENT + if (fileExists && response.code() == HttpURLConnection.HTTP_PARTIAL && !TextUtils.isEmpty(contentRangeHeader)) { String start = contentRangeHeader.substring("bytes ".length(), contentRangeHeader.indexOf("-")); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java index 446061ea6..fcd96826b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java @@ -5,7 +5,6 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; -import android.util.FloatMath; import android.util.Log; public class ShakeListener implements SensorEventListener @@ -50,8 +49,8 @@ public class ShakeListener implements SensorEventListener float gY = event.values[1] / SensorManager.GRAVITY_EARTH; float gZ = event.values[2] / SensorManager.GRAVITY_EARTH; - float gForce = FloatMath.sqrt(gX*gX + gY*gY + gZ*gZ); - if (gForce > 2.25f) { + double gForce = Math.sqrt(gX*gX + gY*gY + gZ*gZ); + if (gForce > 2.25) { Log.d(TAG, "Detected shake " + gForce); mSleepTimer.onShake(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index c34515118..fe5b177ab 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -1,13 +1,13 @@ package de.danoeh.antennapod.core.storage; import android.database.Cursor; +import android.support.v4.util.ArrayMap; import android.util.Log; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -229,7 +229,7 @@ public final class DBReader { for(int i=0, len=itemIds.length; i < len; i++) { ids[i] = String.valueOf(itemIds[i]); } - Map<Long,FeedMedia> result = new HashMap<>(itemIds.length); + Map<Long,FeedMedia> result = new ArrayMap<>(itemIds.length); Cursor cursor = adapter.getFeedMediaCursor(ids); try { if (cursor.moveToFirst()) { @@ -871,7 +871,7 @@ public final class DBReader { ids[i] = String.valueOf(imageIds[i]); } Cursor cursor = adapter.getImageCursor(ids); - Map<Long, FeedImage> result = new HashMap<>(cursor.getCount()); + Map<Long, FeedImage> result = new ArrayMap<>(cursor.getCount()); try { if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { return Collections.emptyMap(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/HandlerState.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/HandlerState.java index 413a11f8e..9280db8a3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/HandlerState.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/HandlerState.java @@ -1,8 +1,8 @@ package de.danoeh.antennapod.core.syndication.handler; +import android.support.v4.util.ArrayMap; + import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import java.util.Stack; @@ -32,7 +32,7 @@ public class HandlerState { /** * Namespaces that have been defined so far. */ - protected HashMap<String, Namespace> namespaces; + protected Map<String, Namespace> namespaces; protected Stack<Namespace> defaultNamespaces; /** * Buffer for saving characters. @@ -42,16 +42,16 @@ public class HandlerState { /** * Temporarily saved objects. */ - protected HashMap<String, Object> tempObjects; + protected Map<String, Object> tempObjects; public HandlerState(Feed feed) { this.feed = feed; - alternateUrls = new LinkedHashMap<String, String>(); + alternateUrls = new ArrayMap<>(); items = new ArrayList<FeedItem>(); tagstack = new Stack<SyndElement>(); - namespaces = new HashMap<String, Namespace>(); + namespaces = new ArrayMap<>(); defaultNamespaces = new Stack<Namespace>(); - tempObjects = new HashMap<String, Object>(); + tempObjects = new ArrayMap<>(); } public Feed getFeed() { @@ -105,7 +105,7 @@ public class HandlerState { alternateUrls.put(url, title); } - public HashMap<String, Object> getTempObjects() { + public Map<String, Object> getTempObjects() { return tempObjects; } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/LangUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/LangUtils.java index 07432d28a..287ec4d0c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/LangUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/LangUtils.java @@ -1,14 +1,15 @@ package de.danoeh.antennapod.core.util; +import android.support.v4.util.ArrayMap; + import java.nio.charset.Charset; -import java.util.HashMap; public class LangUtils { public static final Charset UTF_8 = Charset.forName("UTF-8"); - private static HashMap<String, String> languages; + private static ArrayMap<String, String> languages; static { - languages = new HashMap<String, String>(); + languages = new ArrayMap<>(); languages.put("af", "Afrikaans"); languages.put("sq", "Albanian"); languages.put("sq", "Albanian"); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/StorageUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/StorageUtils.java index d64148715..1ef81bf64 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/StorageUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/StorageUtils.java @@ -1,14 +1,12 @@ package de.danoeh.antennapod.core.util; import android.app.Activity; -import android.content.Context; import android.os.Build; import android.os.StatFs; import android.util.Log; import java.io.File; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.preferences.UserPreferences; @@ -18,13 +16,12 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; public class StorageUtils { private static final String TAG = "StorageUtils"; - public static boolean storageAvailable(Context context) { + public static boolean storageAvailable() { File dir = UserPreferences.getDataFolder(null); if (dir != null) { return dir.exists() && dir.canRead() && dir.canWrite(); } else { - if (BuildConfig.DEBUG) - Log.d(TAG, "Storage not available: data folder is null"); + Log.d(TAG, "Storage not available: data folder is null"); return false; } } @@ -39,7 +36,7 @@ public class StorageUtils { * @return true if external storage is available */ public static boolean checkStorageAvailability(Activity activity) { - boolean storageAvailable = storageAvailable(activity); + boolean storageAvailable = storageAvailable(); if (!storageAvailable) { activity.finish(); activity.startActivity(ClientConfig.applicationCallbacks.getStorageErrorActivity(activity)); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/syndication/FeedDiscoverer.java b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/FeedDiscoverer.java index d148419fd..13cb9f002 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/syndication/FeedDiscoverer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/FeedDiscoverer.java @@ -1,6 +1,7 @@ package de.danoeh.antennapod.core.util.syndication; import android.net.Uri; +import android.support.v4.util.ArrayMap; import android.text.TextUtils; import org.jsoup.Jsoup; @@ -10,7 +11,6 @@ import org.jsoup.select.Elements; import java.io.File; import java.io.IOException; -import java.util.LinkedHashMap; import java.util.Map; /** @@ -46,7 +46,7 @@ public class FeedDiscoverer { } private Map<String, String> findLinks(Document document, String baseUrl) { - Map<String, String> res = new LinkedHashMap<String, String>(); + Map<String, String> res = new ArrayMap<>(); Elements links = document.head().getElementsByTag("link"); for (Element link : links) { String rel = link.attr("rel"); |