Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/news-android.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'News-Android-App/src/main/java/de/luhmer/owncloudnewsreader')
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/PodcastArrayAdapter.java92
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/SubscriptionExpandableListAdapter.java130
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/MenuUtilsSherlockFragmentActivity.java220
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailActivity.java36
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java5
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderDetailFragment.java7
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java49
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java26
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragment.java164
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastSherlockFragmentActivity.java467
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SettingsActivity.java3
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/AsyncTask_DownloadImages.java9
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/IKeyValuePair.java65
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/KeyValuePair.java154
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/MapUtils.java145
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/URLParams.java198
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnection.java18
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/NewPodcastPlaybackListener.java7
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/OpenAudioPodcastEvent.java9
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/OpenPodcastEvent.java17
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/RegisterVideoOutput.java18
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/StartDownloadPodcast.java10
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/UpdatePodcastStatusEvent.java12
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/VideoDoubleClicked.java7
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/AlphaAnimator.java53
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/DatabaseUtils.java2
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FavIconHandler.java6
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FileUtils.java46
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ImageHandler.java33
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/JavaYoutubeDownloader.java381
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/MenuUtilsSherlockFragmentActivity.java226
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/SizeAnimator.java40
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/AudioPodcastItem.java12
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastItem.java32
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/DownloadItemsToCache.java4
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertItemIntoDatabase.java19
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/AudioPodcastService.java170
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java7
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastDownloadService.java240
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java298
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/OnPinchListener.java44
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastNotification.java11
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastSlidingUpPanelLayout.java8
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/ZoomableRelativeLayout.java242
44 files changed, 3088 insertions, 654 deletions
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/PodcastArrayAdapter.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/PodcastArrayAdapter.java
index 0e0c2fea..5c073094 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/PodcastArrayAdapter.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/PodcastArrayAdapter.java
@@ -5,40 +5,46 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
+import android.widget.ProgressBar;
import android.widget.TextView;
+import android.widget.Toast;
import butterknife.ButterKnife;
import butterknife.InjectView;
import de.greenrobot.event.EventBus;
import de.luhmer.owncloudnewsreader.R;
import de.luhmer.owncloudnewsreader.events.podcast.AudioPodcastClicked;
-import de.luhmer.owncloudnewsreader.model.AudioPodcastItem;
+import de.luhmer.owncloudnewsreader.events.podcast.StartDownloadPodcast;
+import de.luhmer.owncloudnewsreader.helper.JavaYoutubeDownloader;
+import de.luhmer.owncloudnewsreader.model.PodcastItem;
/**
* Created by David on 21.06.2014.
*/
-public class PodcastArrayAdapter extends ArrayAdapter<AudioPodcastItem> {
+public class PodcastArrayAdapter extends ArrayAdapter<PodcastItem> {
LayoutInflater inflater;
EventBus eventBus;
- public PodcastArrayAdapter(Context context, AudioPodcastItem[] values) {
- super(context, R.layout.podcast_audio_row, values);
+ public PodcastArrayAdapter(Context context, PodcastItem[] values) {
+ super(context, R.layout.podcast_row, values);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
eventBus = EventBus.getDefault();
+ //eventBus.register(this);
}
@Override
public View getView(final int position, View view, ViewGroup parent) {
- ViewHolder holder;
+ final ViewHolder holder;
if (view != null) {
holder = (ViewHolder) view.getTag();
} else {
- view = inflater.inflate(R.layout.podcast_audio_row, parent, false);
+ view = inflater.inflate(R.layout.podcast_row, parent, false);
holder = new ViewHolder(view);
view.setTag(holder);
}
- AudioPodcastItem podcastItem = getItem(position);
+ final PodcastItem podcastItem = getItem(position);
holder.tvTitle.setText(podcastItem.title);
holder.tvBody.setText(podcastItem.mimeType);
@@ -46,19 +52,85 @@ public class PodcastArrayAdapter extends ArrayAdapter<AudioPodcastItem> {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- AudioPodcastClicked audioPodcastClicked = new AudioPodcastClicked();
- audioPodcastClicked.position = position;
- eventBus.post(audioPodcastClicked);
+ playPodcast(position);
}
});
+
+ holder.flDownloadPodcast.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ holder.flDownloadPodcast.setVisibility(View.GONE);
+
+ Toast.makeText(getContext(), "Starting download.. Please wait", Toast.LENGTH_SHORT).show();
+
+ eventBus.post(new StartDownloadPodcast() {{ podcast = podcastItem; }});
+ }
+ });
+
+ holder.flPlayPodcast.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ playPodcast(position);
+ }
+ });
+
+
+ holder.pbDownloadPodcast.setProgress(podcastItem.downloadProgress);
+ if(podcastItem.downloadProgress >= 0)
+ holder.tvDownloadPodcastProgress.setText(podcastItem.downloadProgress + "%");
+ else
+ holder.tvDownloadPodcastProgress.setText(null);
+
+
+ if(podcastItem.link.contains(JavaYoutubeDownloader.host)) {
+ if(podcastItem.downloadProgress == PodcastItem.DOWNLOAD_NOT_STARTED) {
+ holder.flPlayPodcast.setVisibility(View.GONE);//Youtube Videos can't be streamed
+ holder.flDownloadPodcast.setVisibility(View.VISIBLE);
+ } else {
+ holder.flPlayPodcast.setVisibility(View.VISIBLE);
+ holder.flDownloadPodcast.setVisibility(View.GONE);
+ }
+ } else if(podcastItem.downloadProgress == PodcastItem.DOWNLOAD_NOT_STARTED) {
+ holder.flDownloadPodcast.setVisibility(View.VISIBLE);
+ } else {
+ holder.flDownloadPodcast.setVisibility(View.GONE);
+ }
+
+ /*
+ File podcastFile = new File(PodcastDownloadService.getUrlToPodcastFile(getContext(), podcastItem.link, true));
+ File podcastFileCache = new File(PodcastDownloadService.getUrlToPodcastFile(getContext(), podcastItem.link, true) + ".download");
+ if(podcastFile.exists()) {
+ holder.flDownloadPodcast.setVisibility(View.GONE);
+ }
+ else if(podcastFileCache.exists()) {
+ holder.flDownloadPodcast.setVisibility(View.GONE);
+ }
+ else
+ holder.flDownloadPodcast.setVisibility(View.VISIBLE);
+ */
+
return view;
}
+ private void playPodcast(int position) {
+ AudioPodcastClicked audioPodcastClicked = new AudioPodcastClicked();
+ audioPodcastClicked.position = position;
+ eventBus.post(audioPodcastClicked);
+ }
+
+
+
static class ViewHolder {
@InjectView(R.id.tv_title) TextView tvTitle;
@InjectView(R.id.tv_body) TextView tvBody;
+ @InjectView(R.id.fl_downloadPodcastWrapper) FrameLayout flDownloadPodcast;
+ @InjectView(R.id.fl_PlayPodcastWrapper) FrameLayout flPlayPodcast;
+ @InjectView(R.id.pbDownloadPodcast) ProgressBar pbDownloadPodcast;
+ @InjectView(R.id.tvDownloadPodcastProgress) TextView tvDownloadPodcastProgress;
+
+
public ViewHolder(View view) {
ButterKnife.inject(this, view);
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/SubscriptionExpandableListAdapter.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/SubscriptionExpandableListAdapter.java
index 5b771017..1e1040f3 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/SubscriptionExpandableListAdapter.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/SubscriptionExpandableListAdapter.java
@@ -51,6 +51,7 @@ import de.luhmer.owncloudnewsreader.R;
import de.luhmer.owncloudnewsreader.SettingsActivity;
import de.luhmer.owncloudnewsreader.database.DatabaseConnection;
import de.luhmer.owncloudnewsreader.helper.FavIconHandler;
+import de.luhmer.owncloudnewsreader.helper.FileUtils;
import de.luhmer.owncloudnewsreader.helper.FontHelper;
import de.luhmer.owncloudnewsreader.helper.ImageHandler;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
@@ -105,7 +106,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
LayoutInflater inflater;
private final String favIconPath;
boolean mIsTwoPane;
- private static boolean isTwoPane(Context context) {
+ public static boolean isTwoPane(Context context) {
return context.getResources().getBoolean(R.bool.two_pane);
//return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
@@ -116,7 +117,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
//Picasso.with(mContext).setDebugging(true);
- this.favIconPath = ImageHandler.getPathFavIcons(mContext);
+ this.favIconPath = FileUtils.getPathFavIcons(mContext);
this.inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.mContext = mContext;
this.dbConn = dbConn;
@@ -139,18 +140,18 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
this.listView = listView;
}
- private void AddEverythingInCursorFolderToSubscriptions(Cursor itemsCursor)
+ private void AddEverythingInCursorFolderToSubscriptions(Cursor itemsCursor, ArrayList<AbstractItem> dest)
{
while (itemsCursor.moveToNext()) {
String header = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.FOLDER_LABEL));
//String id_folder = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.FOLDER_LABEL_ID));
long id = itemsCursor.getLong(0);
- mCategoriesArrayList.add(new FolderSubscribtionItem(header, null, id, null));
+ dest.add(new FolderSubscribtionItem(header, null, id, null));
}
itemsCursor.close();
}
- private void AddEverythingInCursorFeedsToSubscriptions(Cursor itemsCursor)
+ private void AddEverythingInCursorFeedsToSubscriptions(Cursor itemsCursor, ArrayList<AbstractItem> dest)
{
while (itemsCursor.moveToNext()) {
String header = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_HEADERTEXT));
@@ -158,7 +159,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
long id = itemsCursor.getLong(0);
String subscriptionId = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_ID));
String favIconUrl = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_FAVICON_URL));
- mCategoriesArrayList.add(new ConcreteFeedItem(header, ITEMS_WITHOUT_FOLDER.getValueString(), subscriptionId, favIconUrl, id));
+ dest.add(new ConcreteFeedItem(header, ITEMS_WITHOUT_FOLDER.getValueString(), subscriptionId, favIconUrl, id));
}
itemsCursor.close();
}
@@ -208,7 +209,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
if(unreadCount != null)
viewHolder.tV_UnreadCount.setText(unreadCount);
else
- viewHolder.tV_UnreadCount.setText("0");
+ viewHolder.tV_UnreadCount.setText("");
/*
else {
viewHolder.tV_UnreadCount.setText("0");
@@ -226,7 +227,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
else
{
viewHolder.tV_HeaderText.setText(mContext.getString(R.string.login_dialog_text_something_went_wrong));
- viewHolder.tV_UnreadCount.setText("0");
+ viewHolder.tV_UnreadCount.setText("");
viewHolder.imgView_FavIcon.setImageDrawable(null);
}
@@ -327,7 +328,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
});
- viewHolder.txt_UnreadCount.setText("0");
+ viewHolder.txt_UnreadCount.setText("");
boolean skipGetUnread = false;
if(group.idFolder != null && group.idFolder.equals(ITEMS_WITHOUT_FOLDER.getValueString())) {
@@ -495,28 +496,31 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
}
+ ArrayList<AbstractItem> mCategoriesArrayListAsync;
+ SparseArray<SparseArray<ConcreteFeedItem>> mItemsArrayListAsync;
public void ReloadAdapter()
{
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
showOnlyUnread = mPrefs.getBoolean(SettingsActivity.CB_SHOWONLYUNREAD_STRING, false);
- mCategoriesArrayList = new ArrayList<AbstractItem>();
- mCategoriesArrayList.add(new FolderSubscribtionItem(mContext.getString(R.string.allUnreadFeeds), null, ALL_UNREAD_ITEMS.getValue(), null));
- mCategoriesArrayList.add(new FolderSubscribtionItem(mContext.getString(R.string.starredFeeds), null, ALL_STARRED_ITEMS.getValue(), null));
+ mCategoriesArrayListAsync = new ArrayList<AbstractItem>();
+ mCategoriesArrayListAsync.add(new FolderSubscribtionItem(mContext.getString(R.string.allUnreadFeeds), null, ALL_UNREAD_ITEMS.getValue(), null));
+ mCategoriesArrayListAsync.add(new FolderSubscribtionItem(mContext.getString(R.string.starredFeeds), null, ALL_STARRED_ITEMS.getValue(), null));
//mCategoriesArrayList.add(new FolderSubscribtionItem(mContext.getString(R.string.starredFeeds), -11, null, null));
- AddEverythingInCursorFolderToSubscriptions(dbConn.getAllTopSubscriptions(showOnlyUnread));
- AddEverythingInCursorFeedsToSubscriptions(dbConn.getAllTopSubscriptionsWithoutFolder(showOnlyUnread));
+ AddEverythingInCursorFolderToSubscriptions(dbConn.getAllTopSubscriptions(showOnlyUnread), mCategoriesArrayListAsync);
+ AddEverythingInCursorFeedsToSubscriptions(dbConn.getAllTopSubscriptionsWithoutFolder(showOnlyUnread), mCategoriesArrayListAsync);
//AddEverythingInCursorToSubscriptions(dbConn.getAllTopSubscriptionsWithUnreadFeeds());
- mItemsArrayList = new SparseArray<SparseArray<ConcreteFeedItem>>();
+ mItemsArrayListAsync = new SparseArray<SparseArray<ConcreteFeedItem>>();
- for(int groupPosition = 0; groupPosition < mCategoriesArrayList.size(); groupPosition++) {
- int parent_id = (int)getGroupId(groupPosition);
+ for(int groupPosition = 0; groupPosition < mCategoriesArrayListAsync.size(); groupPosition++) {
+ //int parent_id = (int)getGroupId(groupPosition);
+ int parent_id = (int) mCategoriesArrayListAsync.get(groupPosition).id_database;
String parentId = String.valueOf(parent_id);
- mItemsArrayList.append(parent_id, new SparseArray<ConcreteFeedItem>());
+ mItemsArrayListAsync.append(parent_id, new SparseArray<ConcreteFeedItem>());
Cursor itemsCursor = dbConn.getAllSubscriptionForFolder(parentId, showOnlyUnread);
itemsCursor.requery();
int childPosTemp = 0;
@@ -527,7 +531,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
String subscription_id = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_ID));
String urlFavicon = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_FAVICON_URL));
ConcreteFeedItem newItem = new ConcreteFeedItem(name, parentId, subscription_id, urlFavicon, id_database);
- mItemsArrayList.get(parent_id).put(childPosTemp, newItem);
+ mItemsArrayListAsync.get(parent_id).put(childPosTemp, newItem);
childPosTemp++;
} while (itemsCursor.moveToNext());
itemsCursor.close();
@@ -552,50 +556,94 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
private class NotifyDataSetChangedAsyncTask extends AsyncTask<Void, Void, Void> {
- // Block children layout for now
- BlockingExpandableListView bView;
SparseArray<String> unreadCountFoldersTemp;
SparseArray<String> unreadCountFeedsTemp;
SparseArray<String> urlsToFavIconsTemp;
+ @Override
+ protected Void doInBackground(Void... voids) {
+ unreadCountFoldersTemp = dbConn.getUnreadItemCountForFolder(mContext);
+ unreadCountFeedsTemp = dbConn.getUnreadItemCountForFeed();
+ urlsToFavIconsTemp = dbConn.getUrlsToFavIcons();
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ notifyCountDataSetChanged(unreadCountFoldersTemp, unreadCountFeedsTemp, urlsToFavIconsTemp);
+ super.onPostExecute(aVoid);
+ }
+ }
+
+ public void ReloadAdapterAsync(View progressBar) {
+ new ReloadAdapterAsyncTask(progressBar).execute((Void) null);
+ }
+
+ private class ReloadAdapterAsyncTask extends AsyncTask<Void, Void, Void> {
+
+ View progressBar;
+
+ public ReloadAdapterAsyncTask(View progressBar) {
+ this.progressBar = progressBar;
+ }
@Override
protected void onPreExecute() {
- bView = (BlockingExpandableListView) listView;
+ progressBar.setVisibility(View.VISIBLE);
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... voids) {
- unreadCountFoldersTemp = dbConn.getUnreadItemCountForFolder(mContext);
- unreadCountFeedsTemp = dbConn.getUnreadItemCountForFeed();
- urlsToFavIconsTemp = dbConn.getUrlsToFavIcons();
+ ReloadAdapter();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
- unreadCountFolders = unreadCountFoldersTemp;
- unreadCountFeeds = unreadCountFeedsTemp;
- urlsToFavIcons = urlsToFavIconsTemp;
+ notifyReloadAdapterDataChanged();
- int firstVisPos = bView.getFirstVisiblePosition();
- View firstVisView = bView.getChildAt(0);
- int top = firstVisView != null ? firstVisView.getTop() : 0;
+ progressBar.setVisibility(View.GONE);
- // Number of items added before the first visible item
- int itemsAddedBeforeFirstVisible = 0;
+ super.onPostExecute(aVoid);
+ }
+ }
- bView.setBlockLayoutChildren(true);
- notifyDataSetChanged();
- bView.setBlockLayoutChildren(false);
- // Call setSelectionFromTop to change the ListView position
- if(bView.getCount() >= firstVisPos + itemsAddedBeforeFirstVisible)
- bView.setSelectionFromTop(firstVisPos + itemsAddedBeforeFirstVisible, top);
+ public void notifyReloadAdapterDataChanged()
+ {
+ mCategoriesArrayList = mCategoriesArrayListAsync;
+ mCategoriesArrayListAsync = null;
- super.onPostExecute(aVoid);
- }
+ mItemsArrayList = mItemsArrayListAsync;
+ mItemsArrayListAsync = null;
+
+ notifyDataSetChanged();
+
+ NotifyDataSetChangedAsync();
+ }
+
+ public void notifyCountDataSetChanged(SparseArray<String> unreadCountFolders, SparseArray<String> unreadCountFeeds, SparseArray<String> urlsToFavIcons) {
+ this.unreadCountFolders = unreadCountFolders;
+ this.unreadCountFeeds = unreadCountFeeds;
+ this.urlsToFavIcons = urlsToFavIcons;
+
+ BlockingExpandableListView bView = (BlockingExpandableListView) listView;
+
+ int firstVisPos = bView.getFirstVisiblePosition();
+ View firstVisView = bView.getChildAt(0);
+ int top = firstVisView != null ? firstVisView.getTop() : 0;
+
+ // Number of items added before the first visible item
+ int itemsAddedBeforeFirstVisible = 0;
+
+ bView.setBlockLayoutChildren(true);
+ notifyDataSetChanged();
+ bView.setBlockLayoutChildren(false);
+
+ // Call setSelectionFromTop to change the ListView position
+ if(bView.getCount() >= firstVisPos + itemsAddedBeforeFirstVisible)
+ bView.setSelectionFromTop(firstVisPos + itemsAddedBeforeFirstVisible, top);
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/MenuUtilsSherlockFragmentActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/MenuUtilsSherlockFragmentActivity.java
new file mode 100644
index 00000000..cafc0807
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/MenuUtilsSherlockFragmentActivity.java
@@ -0,0 +1,220 @@
+/**
+ * Android ownCloud News
+ *
+ * @author David Luhmer
+ * @copyright 2013 David Luhmer david-dev@live.de
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package de.luhmer.owncloudnewsreader;
+
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.preference.PreferenceManager;
+import android.support.v4.app.FragmentActivity;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.actionbarsherlock.app.SherlockDialogFragment;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuInflater;
+import com.actionbarsherlock.view.MenuItem;
+
+import de.luhmer.owncloudnewsreader.database.DatabaseConnection;
+import de.luhmer.owncloudnewsreader.reader.IReader;
+import de.luhmer.owncloudnewsreader.reader.OnAsyncTaskCompletedListener;
+import de.luhmer.owncloudnewsreader.reader.owncloud.API;
+import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloud_Reader;
+
+public class MenuUtilsSherlockFragmentActivity extends PodcastSherlockFragmentActivity {
+
+ protected static final String TAG = "MenuUtils";
+
+ static FragmentActivity activity;
+
+ static MenuItem menuItemSettings;
+ static MenuItem menuItemLogin;
+ static MenuItem menuItemStartImageCaching;
+
+
+ private static MenuItem menuItemUpdater;
+ private static MenuItem menuItemDownloadMoreItems;
+
+ static IReader _Reader;
+
+ /**
+ * @return the menuItemUpdater
+ */
+ public static MenuItem getMenuItemUpdater() {
+ return menuItemUpdater;
+ }
+
+
+ /**
+ * @return the menuItemDownloadMoreItems
+ */
+ public static MenuItem getMenuItemDownloadMoreItems() {
+ return menuItemDownloadMoreItems;
+ }
+
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ @Override
+ protected void onResume() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ invalidateOptionsMenu();
+ }
+ super.onResume();
+ }
+
+
+ public static void onCreateOptionsMenu(Menu menu, MenuInflater inflater, FragmentActivity act) {
+ inflater.inflate(R.menu.news_reader, menu);
+ activity = act;
+
+ menuItemSettings = menu.findItem(R.id.action_settings);
+ menuItemLogin = menu.findItem(R.id.action_login);
+ menuItemStartImageCaching = menu.findItem(R.id.menu_StartImageCaching);
+
+ menuItemUpdater = menu.findItem(R.id.menu_update);
+ //menuItemMarkAllAsRead = menu.findItem(R.id.menu_markAllAsRead);
+ menuItemDownloadMoreItems = menu.findItem(R.id.menu_downloadMoreItems);
+
+
+ //menuItemMarkAllAsRead.setEnabled(false);
+ menuItemDownloadMoreItems.setEnabled(false);
+
+ NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame));
+ if(ndf != null)
+ ndf.UpdateMenuItemsState();
+ }
+
+ public static boolean onOptionsItemSelected(MenuItem item, FragmentActivity activity) {
+ switch (item.getItemId()) {
+ case R.id.menu_About_Changelog:
+ SherlockDialogFragment dialog = new VersionInfoDialogFragment();
+ dialog.show(activity.getSupportFragmentManager(), "VersionChangelogDialogFragment");
+ return true;
+
+ case R.id.menu_markAllAsRead:
+ NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame));
+ if(ndf != null)
+ {
+ /*
+ for(int i = 0; i < ndf.getListView().getChildCount(); i++)
+ {
+ View view = ndf.getListView().getChildAt(i);
+ CheckBox cb = (CheckBox) view.findViewById(R.id.cb_lv_item_read);
+ if(!cb.isChecked())
+ cb.setChecked(true);
+ }
+ */
+
+ DatabaseConnection dbConn = new DatabaseConnection(activity);
+ try {
+ /*
+ //dbConn.markAllItemsAsRead(ndf.getDatabaseIdsOfItems());
+ List<Integer> items = new ArrayList<Integer>();
+
+
+ Cursor cursor = ncla.getLvAdapter().getCursor();
+ cursor.moveToFirst();
+ do {
+ items.add(Integer.parseInt(cursor.getString(0)));
+ } while (cursor.moveToNext());
+ dbConn.markAllItemsAsRead(items);
+ */
+ dbConn.markAllItemsAsReadForCurrentView();
+ } finally {
+ dbConn.closeDatabase();
+ }
+ ndf.UpdateCursor();
+
+ //If tablet view is enabled update the listview as well
+ if(activity instanceof NewsReaderListActivity)
+ ((NewsReaderListActivity) activity).updateAdapter();
+
+ }
+ return true;
+
+ case R.id.menu_downloadMoreItems:
+ DownloadMoreItems();
+ return true;
+ }
+ return false;
+ }
+
+ private static void DownloadMoreItems()
+ {
+ /*
+ DatabaseConnection dbConn = new DatabaseConnection(activity);
+ int count = dbConn.getCountFeedsForFolder(SubscriptionExpandableListAdapter.ALL_ITEMS, false);
+ if(count >= Constants.maxItemsCount)
+ {
+ String text = activity.getString(R.string.max_items_count_reached);
+ text = text.replace("XX", "" + Constants.maxItemsCount);
+ new AlertDialog.Builder(activity)
+ .setTitle(activity.getString(R.string.empty_view_header))
+ .setMessage(text)
+ .setPositiveButton(activity.getString(android.R.string.ok), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,int id) {
+
+ }
+ })
+ .create()
+ .show();
+ //Toast.makeText(activity, text, Toast.LENGTH_LONG).show();
+ }
+ else
+ {*/
+ String username = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()).getString("edt_username", "");
+ String password = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()).getString("edt_password", "");
+
+ if(username != null) {
+ _Reader = new OwnCloud_Reader();
+ ((OwnCloud_Reader)_Reader).Start_AsyncTask_GetVersion(Constants.TaskID_GetVersion, activity, onAsyncTaskGetVersionFinished, username, password);
+
+ Toast.makeText(activity, activity.getString(R.string.toast_GettingMoreItems), Toast.LENGTH_SHORT).show();
+ }
+ //}
+ }
+
+ static OnAsyncTaskCompletedListener onAsyncTaskGetVersionFinished = new OnAsyncTaskCompletedListener() {
+
+ @Override
+ public void onAsyncTaskCompleted(int task_id, Object task_result) {
+ if(_Reader != null) {
+ String appVersion = task_result.toString();
+ API api = API.GetRightApiForVersion(appVersion, activity);
+ ((OwnCloud_Reader) _Reader).setApi(api);
+
+ NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame));
+ _Reader.Start_AsyncTask_GetOldItems(Constants.TaskID_GetItems, activity, onAsyncTaskComplete, ndf.getIdFeed(), ndf.getIdFolder());
+ }
+ }
+ };
+
+ static OnAsyncTaskCompletedListener onAsyncTaskComplete = new OnAsyncTaskCompletedListener() {
+ @Override
+ public void onAsyncTaskCompleted(int task_id, Object task_result) {
+ NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame));
+ if(ndf != null)
+ ndf.UpdateCursor();
+
+ Log.d(TAG, "Finished Download extra items..");
+ }
+ };
+} \ No newline at end of file
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailActivity.java
index 2bda52cd..0c00036f 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailActivity.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailActivity.java
@@ -38,9 +38,7 @@ import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
-import android.view.View;
-import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
@@ -53,10 +51,9 @@ import de.luhmer.owncloudnewsreader.helper.PostDelayHandler;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
import de.luhmer.owncloudnewsreader.reader.IReader;
import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloud_Reader;
-import de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout;
import de.luhmer.owncloudnewsreader.widget.WidgetProvider;
-public class NewsDetailActivity extends SherlockFragmentActivity {
+public class NewsDetailActivity extends PodcastSherlockFragmentActivity {
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
@@ -67,7 +64,6 @@ public class NewsDetailActivity extends SherlockFragmentActivity {
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
- public PodcastSlidingUpPanelLayout sliding_layout;
/**
* The {@link ViewPager} that will host the section contents.
@@ -75,8 +71,6 @@ public class NewsDetailActivity extends SherlockFragmentActivity {
public ViewPager mViewPager;
private int currentPosition;
- PodcastFragment podcastFragment;
-
PostDelayHandler pDelayHandler;
MenuItem menuItem_Starred;
@@ -100,9 +94,6 @@ public class NewsDetailActivity extends SherlockFragmentActivity {
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- sliding_layout = (PodcastSlidingUpPanelLayout) findViewById(R.id.sliding_layout);
- UpdatePodcastView();
-
pDelayHandler = new PostDelayHandler(this);
_Reader = new OwnCloud_Reader();
@@ -184,20 +175,9 @@ public class NewsDetailActivity extends SherlockFragmentActivity {
public void onPageScrollStateChanged(int arg0) {
}
});
- }
-
- public void UpdatePodcastView() {
- SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- if(mPrefs.getBoolean(SettingsActivity.CB_ENABLE_PODCASTS_STRING, false)) {
- podcastFragment = PodcastFragment.newInstance(null, null);
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.podcast_frame, podcastFragment)
- .commit();
- } else {
- sliding_layout.getChildAt(1).setVisibility(View.GONE);
- }
}
+
@Override
protected void onDestroy() {
if(dbConn != null)
@@ -349,10 +329,8 @@ public class NewsDetailActivity extends SherlockFragmentActivity {
@Override
public void onBackPressed() {
- if(podcastFragment != null && sliding_layout.isExpanded()) {
- if (!podcastFragment.onBackPressed())
- sliding_layout.collapsePane();
- } else
+ if(handlePodcastBackPressed());
+ else
super.onBackPressed();
}
@@ -383,10 +361,8 @@ public class NewsDetailActivity extends SherlockFragmentActivity {
switch (item.getItemId()) {
case android.R.id.home:
- if(podcastFragment != null && sliding_layout.isExpanded()) {
- if (!podcastFragment.onBackPressed())
- sliding_layout.collapsePane();
- } else {
+ if(handlePodcastBackPressed());
+ else {
super.onBackPressed();
}
break;
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java
index 89085df6..1fabb950 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java
@@ -46,6 +46,7 @@ import java.util.Date;
import java.util.List;
import de.luhmer.owncloudnewsreader.database.DatabaseConnection;
+import de.luhmer.owncloudnewsreader.helper.FileUtils;
import de.luhmer.owncloudnewsreader.helper.FontHelper;
import de.luhmer.owncloudnewsreader.helper.ImageHandler;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
@@ -264,7 +265,7 @@ public class NewsDetailFragment extends SherlockFragment {
favIconUrl = favIconCursor.getString(favIconCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_FAVICON_URL));
if(favIconUrl != null)
{
- File file = ImageHandler.getFullPathOfCacheFile(favIconUrl, ImageHandler.getPathFavIcons(context));
+ File file = ImageHandler.getFullPathOfCacheFile(favIconUrl, FileUtils.getPathFavIcons(context));
if(file.isFile())
favIconUrl = "file://" + file.getAbsolutePath().toString();
}
@@ -356,7 +357,7 @@ public class NewsDetailFragment extends SherlockFragment {
link = link.trim();
try
{
- File file = ImageHandler.getFullPathOfCacheFile(link, ImageHandler.getPathImageCache(context));
+ File file = ImageHandler.getFullPathOfCacheFile(link, FileUtils.getPathImageCache(context));
if(file.isFile())
text = text.replace(link, "file://" + file.getAbsolutePath().toString());
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderDetailFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderDetailFragment.java
index 8fda9002..361abab7 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderDetailFragment.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderDetailFragment.java
@@ -52,7 +52,6 @@ import de.luhmer.owncloudnewsreader.cursor.NewsListCursorAdapter;
import de.luhmer.owncloudnewsreader.cursor.SimpleCursorLoader;
import de.luhmer.owncloudnewsreader.database.DatabaseConnection;
import de.luhmer.owncloudnewsreader.database.DatabaseConnection.SORT_DIRECTION;
-import de.luhmer.owncloudnewsreader.helper.MenuUtilsSherlockFragmentActivity;
/**
* A fragment representing a single NewsReader detail screen. This fragment is
@@ -140,7 +139,7 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- //setRetainInstance(true);
+ setRetainInstance(true);
//dbConn = new DatabaseConnection(getActivity());
@@ -173,7 +172,7 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO
}
- public void UpdateMenuItemsState()
+ public void UpdateMenuItemsState()
{
if(MenuUtilsSherlockFragmentActivity.getMenuItemDownloadMoreItems() != null)
{
@@ -225,6 +224,8 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO
+
+
private RobotoCheckBox getCheckBoxAtPosition(int pos, AbsListView viewLV)
{
ListView lv = (ListView) viewLV;
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java
index a47edd84..e006a116 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java
@@ -49,11 +49,9 @@ import de.luhmer.owncloudnewsreader.cursor.NewsListCursorAdapter;
import de.luhmer.owncloudnewsreader.database.DatabaseConnection;
import de.luhmer.owncloudnewsreader.helper.DatabaseUtils;
import de.luhmer.owncloudnewsreader.helper.ImageHandler;
-import de.luhmer.owncloudnewsreader.helper.MenuUtilsSherlockFragmentActivity;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
import de.luhmer.owncloudnewsreader.services.DownloadImagesService;
import de.luhmer.owncloudnewsreader.services.IOwnCloudSyncService;
-import de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout;
import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefreshLayout;
/**
@@ -70,8 +68,8 @@ import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefresh
public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity implements
NewsReaderListFragment.Callbacks {
- private SlidingPaneLayout mSlidingLayout;
- public PodcastSlidingUpPanelLayout sliding_layout;
+ SlidingPaneLayout mSlidingLayout;
+
//static final String TAG = "NewsReaderListActivity";
//ActionBarDrawerToggle drawerToggle;
@@ -82,7 +80,6 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im
public static final String ITEM_ID = "ITEM_ID";
public static final String TITEL = "TITEL";
- PodcastFragment podcastFragment;
//boolean isSlideUpPanelExpanded = false;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@@ -131,14 +128,6 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im
-
-
-
- sliding_layout = (PodcastSlidingUpPanelLayout) findViewById(R.id.sliding_layout);
- UpdatePodcastView();
-
-
-
mSlidingLayout = (SlidingPaneLayout) findViewById(R.id.sliding_pane);
mSlidingLayout.setParallaxDistance(280);
@@ -152,6 +141,8 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im
@Override
public void onPanelOpened(View arg0) {
+ togglePodcastVideoViewAnimation();
+
updateAdapter();
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
@@ -162,6 +153,8 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im
@Override
public void onPanelClosed(View arg0) {
+ togglePodcastVideoViewAnimation();
+
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
@@ -222,25 +215,6 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im
private static final String OPTIONAL_FOLDER_ID ="OPTIONAL_FOLDER_ID";
- public void UpdatePodcastView() {
-
- if(podcastFragment != null) {
- getSupportFragmentManager().beginTransaction().remove(podcastFragment).commitAllowingStateLoss();
- }
-
-
- SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- if(mPrefs.getBoolean(SettingsActivity.CB_ENABLE_PODCASTS_STRING, false)) {
- podcastFragment = PodcastFragment.newInstance(null, null);
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.podcast_frame, podcastFragment)
- .commitAllowingStateLoss();
- } else {
- sliding_layout.getChildAt(1).setVisibility(View.GONE);
- podcastFragment = null;
- }
- }
-
/* (non-Javadoc)
* @see com.actionbarsherlock.app.SherlockFragmentActivity#onSaveInstanceState(android.os.Bundle)
*/
@@ -481,10 +455,8 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im
@Override
public void onBackPressed() {
- if(podcastFragment != null && sliding_layout.isExpanded()) {
- if (!podcastFragment.onBackPressed())
- sliding_layout.collapsePane();
- } else if(mSlidingLayout.isOpen())
+ if(handlePodcastBackPressed());
+ else if(mSlidingLayout.isOpen())
super.onBackPressed();
else
mSlidingLayout.openPane();
@@ -502,10 +474,7 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im
switch (item.getItemId()) {
case android.R.id.home:
- if(podcastFragment != null && sliding_layout.isExpanded()) {
- if (!podcastFragment.onBackPressed())
- sliding_layout.collapsePane();
- }
+ if(handlePodcastBackPressed());
else if(!mSlidingLayout.isOpen())
mSlidingLayout.openPane();
return true;
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java
index 95e8ae4f..6d9606ce 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java
@@ -30,7 +30,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -165,33 +164,10 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate
}
public void ReloadAdapter() {
- new ReloadAdapterAsync().execute((Void) null);
+ lvAdapter.ReloadAdapterAsync(progressBar);
}
- private class ReloadAdapterAsync extends AsyncTask<Void, Void, Void> {
- @Override
- protected void onPreExecute() {
- progressBar.setVisibility(View.VISIBLE);
- super.onPreExecute();
- }
-
- @Override
- protected Void doInBackground(Void... voids) {
- lvAdapter.ReloadAdapter();
- return null;
- }
-
- @Override
- protected void onPostExecute(Void aVoid) {
- //lvAdapter.notifyDataSetChanged();
- lvAdapter.NotifyDataSetChangedAsync();
-
- progressBar.setVisibility(View.GONE);
-
- super.onPostExecute(aVoid);
- }
- }
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragment.java
index 1d9b5275..9d5d1c96 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragment.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragment.java
@@ -24,6 +24,8 @@ import android.widget.ViewSwitcher;
import com.actionbarsherlock.app.SherlockFragment;
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
+import java.io.File;
+import java.util.Arrays;
import java.util.List;
import butterknife.ButterKnife;
@@ -34,14 +36,16 @@ import de.luhmer.owncloudnewsreader.ListView.PodcastArrayAdapter;
import de.luhmer.owncloudnewsreader.ListView.PodcastFeedArrayAdapter;
import de.luhmer.owncloudnewsreader.database.DatabaseConnection;
import de.luhmer.owncloudnewsreader.events.podcast.AudioPodcastClicked;
-import de.luhmer.owncloudnewsreader.events.podcast.OpenAudioPodcastEvent;
+import de.luhmer.owncloudnewsreader.events.podcast.OpenPodcastEvent;
import de.luhmer.owncloudnewsreader.events.podcast.PodcastFeedClicked;
+import de.luhmer.owncloudnewsreader.events.podcast.StartDownloadPodcast;
import de.luhmer.owncloudnewsreader.events.podcast.TogglePlayerStateEvent;
import de.luhmer.owncloudnewsreader.events.podcast.UpdatePodcastStatusEvent;
import de.luhmer.owncloudnewsreader.events.podcast.WindPodcast;
-import de.luhmer.owncloudnewsreader.model.AudioPodcastItem;
import de.luhmer.owncloudnewsreader.model.PodcastFeedItem;
-import de.luhmer.owncloudnewsreader.services.AudioPodcastService;
+import de.luhmer.owncloudnewsreader.model.PodcastItem;
+import de.luhmer.owncloudnewsreader.services.PodcastDownloadService;
+import de.luhmer.owncloudnewsreader.services.PodcastPlaybackService;
import de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout;
@@ -106,6 +110,9 @@ public class PodcastFragment extends SherlockFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ setRetainInstance(true);
+
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
@@ -114,7 +121,10 @@ public class PodcastFragment extends SherlockFragment {
eventBus = EventBus.getDefault();
- getActivity().startService(new Intent(getActivity(), AudioPodcastService.class));
+ // when initialize
+ //getActivity().registerReceiver(downloadCompleteReceiver, downloadCompleteIntentFilter);
+
+ getActivity().startService(new Intent(getActivity(), PodcastPlaybackService.class));
}
@@ -133,29 +143,135 @@ public class PodcastFragment extends SherlockFragment {
super.onPause();
}
+ public void onEventMainThread(StartDownloadPodcast podcast) {
+ PodcastDownloadService.startPodcastDownload(getActivity(), podcast.podcast);//, new DownloadReceiver(new Handler(), new WeakReference<ProgressBar>(holder.pbDownloadPodcast)));
+ }
+
+ /*
+ private class DownloadReceiver extends ResultReceiver {
+ WeakReference<ProgressBar> progressBar;
+
+ public DownloadReceiver(Handler handler, WeakReference<ProgressBar> progressBar) {
+ super(handler);
+
+ this.progressBar = progressBar;
+ }
+
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ super.onReceiveResult(resultCode, resultData);
+ if (resultCode == PodcastDownloadService.UPDATE_PROGRESS) {
+
+ if(progressBar.get() != null) {
+ int progress = resultData.getInt("progress");
+ progressBar.get().setIndeterminate(false);
+ progressBar.get().setProgress(progress);
+ if (progress == 100) {
+ progressBar.get().setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+ }
+ */
+
+ public static String[] VIDEO_FORMATS = { "youtube" };
+
public void onEventMainThread(AudioPodcastClicked podcast) {
- final AudioPodcastItem audioPodcast = audioPodcasts.get(podcast.position);
+ final PodcastItem audioPodcast = audioPodcasts.get(podcast.position);
tvTitle.setText(audioPodcast.title);
- eventBus.post(new OpenAudioPodcastEvent() {{ pathToFile = audioPodcast.link; mediaTitle = audioPodcast.title; }});
+ boolean isVideo = Arrays.asList(VIDEO_FORMATS).contains(audioPodcast.mimeType);
+
+ if(audioPodcast.mimeType.equals("youtube") && !audioPodcast.offlineCached)
+ Toast.makeText(getActivity(), "Cannot stream from youtube. Please download the video first.", Toast.LENGTH_SHORT).show();
+ else {
+ File file = new File(PodcastDownloadService.getUrlToPodcastFile(getActivity(), audioPodcast.link, true));
+ if(file.exists())
+ audioPodcast.link = file.getAbsolutePath();
+ else
+ Toast.makeText(getActivity(), "Starting podcast.. please wait", Toast.LENGTH_SHORT).show(); //Only show if we need to stream the file
- Toast.makeText(getActivity(), "Starting podcast.. please wait", Toast.LENGTH_SHORT).show();
+ eventBus.post(new OpenPodcastEvent(audioPodcast.link, audioPodcast.title, isVideo));
+ }
}
public void onEventMainThread(PodcastFeedClicked podcast) {
DatabaseConnection dbConn = new DatabaseConnection(getActivity());
- audioPodcasts = dbConn.getListOfAudioPodcastsForFeed(feedsWithAudioPodcasts.get(podcast.position).itemId);
+ audioPodcasts = dbConn.getListOfAudioPodcastsForFeed(getActivity(), feedsWithAudioPodcasts.get(podcast.position).itemId);
- PodcastArrayAdapter mArrayAdapter = new PodcastArrayAdapter(getActivity(), audioPodcasts.toArray(new AudioPodcastItem[audioPodcasts.size()]));
+
+ for(int i = 0; i < audioPodcasts.size(); i++) {
+ PodcastItem podcastItem = audioPodcasts.get(i);
+
+ File podcastFile = new File(PodcastDownloadService.getUrlToPodcastFile(getActivity(), podcastItem.link, false));
+ File podcastFileCache = new File(PodcastDownloadService.getUrlToPodcastFile(getActivity(), podcastItem.link, false) + ".download");
+ if(podcastFile.exists())
+ podcastItem.downloadProgress = PodcastItem.DOWNLOAD_COMPLETED;
+ else if(podcastFileCache.exists())
+ podcastItem.downloadProgress = 0;
+ else
+ podcastItem.downloadProgress = PodcastItem.DOWNLOAD_NOT_STARTED;
+ }
+
+ PodcastArrayAdapter mArrayAdapter = new PodcastArrayAdapter(getActivity(), audioPodcasts.toArray(new PodcastItem[audioPodcasts.size()]));
if (podcastTitleGrid != null) {
podcastTitleGrid.setAdapter(mArrayAdapter);
}
podcastTitleGrid.setVisibility(View.VISIBLE);
podcastFeedList.setVisibility(View.GONE);
+
+
+ //eventBus.post(new OpenAudioPodcastEvent(FileUtils.getPathPodcasts(getActivity()) + "/Foxes.mp4", "Test Video"));
+ //eventBus.post(new OpenPodcastEvent(FileUtils.getPathPodcasts(getActivity()) + "/Aneta.mp4", "Test Video", true));
+
+ //PodcastDownloadService.startPodcastDownload(getActivity(), new PodcastItem("5", "Blaa", "http://www.youtube.com/v/wtLJPvx7-ys?version=3&f=playlists&app=youtube_gdata", "youtube"));
+ }
+
+
+ public void onEventMainThread(PodcastDownloadService.DownloadProgressUpdate downloadProgress) {
+ PodcastArrayAdapter podcastArrayAdapter = (PodcastArrayAdapter) podcastTitleGrid.getAdapter();
+
+ for(int i = 0; i < podcastTitleGrid.getCount(); i++) {
+ if(podcastArrayAdapter.getItem(i).link.equals(downloadProgress.podcast.link)) {
+
+ if(podcastArrayAdapter.getItem(i).downloadProgress != downloadProgress.podcast.downloadProgress) { //If Progress changed
+ PodcastItem pItem = podcastArrayAdapter.getItem(i);
+
+ if (downloadProgress.podcast.downloadProgress == 100) {
+ pItem.downloadProgress = PodcastItem.DOWNLOAD_COMPLETED;
+ File file = new File(PodcastDownloadService.getUrlToPodcastFile(getActivity(), pItem.link, false));
+ pItem.offlineCached = file.exists();
+ } else
+ pItem.downloadProgress = downloadProgress.podcast.downloadProgress;
+ podcastTitleGrid.invalidateViews();
+ }
+
+ return;
+ /*
+ View v = podcastTitleGrid.getChildAt(i -
+ podcastTitleGrid.getFirstVisiblePosition());
+ ((ProgressBar)v.findViewById(R.id.pbDownloadPodcast)).setProgress(downloadProgress.podcast.downloadProgress);
+
+ //podcastArrayAdapter.notifyDataSetChanged();
+ return;
+ */
+ }
+ }
}
+ /*
+ private String downloadCompleteIntentName = DownloadManager.ACTION_DOWNLOAD_COMPLETE;
+ private IntentFilter downloadCompleteIntentFilter = new IntentFilter(downloadCompleteIntentName);
+ private BroadcastReceiver downloadCompleteReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ ((ArrayAdapter) podcastTitleGrid.getAdapter()).notifyDataSetChanged();
+ }
+ };
+ */
int lastDrawableId;
@@ -207,7 +323,7 @@ public class PodcastFragment extends SherlockFragment {
}
}
- List<AudioPodcastItem> audioPodcasts;
+ List<PodcastItem> audioPodcasts;
List<PodcastFeedItem> feedsWithAudioPodcasts;
@InjectView(R.id.btn_playPausePodcast) ImageButton btnPlayPausePodcast;
@@ -274,15 +390,14 @@ public class PodcastFragment extends SherlockFragment {
ButterKnife.inject(this, view);
- if(getActivity() instanceof NewsReaderListActivity) {
- sliding_layout = ((NewsReaderListActivity) getActivity()).sliding_layout;
- } else if(getActivity() instanceof NewsDetailActivity) {
- sliding_layout = ((NewsDetailActivity) getActivity()).sliding_layout;
+ if(getActivity() instanceof PodcastSherlockFragmentActivity) {
+ sliding_layout = ((PodcastSherlockFragmentActivity) getActivity()).getSlidingLayout();
}
if(sliding_layout != null) {
sliding_layout.setSlideableView(rlPodcast);
sliding_layout.setDragView(rlPodcastHeader);
+ //sliding_layout.setEnableDragViewTouchEvents(true);
sliding_layout.setPanelSlideListener(onPanelSlideListener);
}
@@ -365,6 +480,9 @@ public class PodcastFragment extends SherlockFragment {
if(sliding_layout != null)
sliding_layout.setDragView(rlPodcastHeader);
viewSwitcherProgress.setDisplayedChild(0);
+
+ if(getActivity() instanceof PodcastSherlockFragmentActivity)
+ ((PodcastSherlockFragmentActivity)getActivity()).togglePodcastVideoViewAnimation();
}
@Override
@@ -372,19 +490,27 @@ public class PodcastFragment extends SherlockFragment {
if(sliding_layout != null)
sliding_layout.setDragView(viewSwitcherProgress);
viewSwitcherProgress.setDisplayedChild(1);
+
+ if(getActivity() instanceof PodcastSherlockFragmentActivity)
+ ((PodcastSherlockFragmentActivity)getActivity()).togglePodcastVideoViewAnimation();
}
@Override
public void onPanelAnchored(View view) {
}
+
+ @Override
+ public void onPanelHidden(View view) {
+
+ }
};
boolean blockSeekbarUpdate = false;
private SeekBar.OnSeekBarChangeListener onSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
- Log.d(TAG, "onProgressChanged");
+ //Log.d(TAG, "onProgressChanged");
}
@Override
@@ -395,8 +521,12 @@ public class PodcastFragment extends SherlockFragment {
@Override
public void onStopTrackingTouch(final SeekBar seekBar) {
- eventBus.post(new WindPodcast() {{ toPositionInPercent = seekBar.getProgress(); }});
- blockSeekbarUpdate = false;
+ if(hasTitleInCache) {
+ eventBus.post(new WindPodcast() {{
+ toPositionInPercent = seekBar.getProgress();
+ }});
+ blockSeekbarUpdate = false;
+ }
Log.d(TAG, "onStopTrackingTouch");
}
};
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastSherlockFragmentActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastSherlockFragmentActivity.java
new file mode 100644
index 00000000..4a5c9dcd
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastSherlockFragmentActivity.java
@@ -0,0 +1,467 @@
+package de.luhmer.owncloudnewsreader;
+
+import android.animation.Animator;
+import android.annotation.TargetApi;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.animation.Animation;
+import android.widget.LinearLayout;
+
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import de.greenrobot.event.EventBus;
+import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter;
+import de.luhmer.owncloudnewsreader.events.podcast.RegisterVideoOutput;
+import de.luhmer.owncloudnewsreader.events.podcast.UpdatePodcastStatusEvent;
+import de.luhmer.owncloudnewsreader.events.podcast.VideoDoubleClicked;
+import de.luhmer.owncloudnewsreader.helper.SizeAnimator;
+import de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout;
+import de.luhmer.owncloudnewsreader.view.ZoomableRelativeLayout;
+
+/**
+ * Created by David on 29.06.2014.
+ */
+public class PodcastSherlockFragmentActivity extends SherlockFragmentActivity {
+
+ private static final String TAG = "PodcastSherlockFragmentActivity";
+ private PodcastFragment podcastFragment;
+
+ private EventBus eventBus;
+
+ @InjectView(R.id.videoPodcastSurfaceWrapper) ZoomableRelativeLayout rlVideoPodcastSurfaceWrapper;
+ //@InjectView(R.id.videoPodcastSurface) SurfaceView surfaceView;
+ @InjectView(R.id.sliding_layout) PodcastSlidingUpPanelLayout sliding_layout;
+
+ int appHeight;
+ int appWidth;
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ eventBus = EventBus.getDefault();
+
+ ButterKnife.inject(this);
+
+ //surfaceView.getHolder().setFixedSize(surfaceView.getWidth(), 10);
+ //surfaceView.setVisibility(View.GONE);
+ //rlVideoPodcastSurfaceWrapper.setVisibility(View.GONE);
+
+ rlVideoPodcastSurfaceWrapper.setVisibility(View.INVISIBLE);
+
+ UpdatePodcastView();
+
+ /*
+ new OrientationEventListener(this, SensorManager.SENSOR_DELAY_UI) {
+ @Override
+ public void onOrientationChanged(int i) {
+ sliding_layout.collapsePanel();
+ }
+ };
+ */
+
+ super.onPostCreate(savedInstanceState);
+ }
+
+
+
+
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ if(hasWindowFocus) {
+ int currentOrientation = getResources().getConfiguration().orientation;
+ if (currentOrientation != lastOrientation) {
+ sliding_layout.collapsePanel();
+ lastOrientation = currentOrientation;
+ }
+ }
+
+ //rlVideoPodcastSurfaceWrapper.setVisibility(View.GONE);
+ //isVideoViewVisible = false;
+
+ super.onWindowFocusChanged(hasWindowFocus);
+ }
+
+
+
+ int lastOrientation = -1;
+ @Override
+ protected void onResume() {
+ eventBus.register(this);
+
+ //eventBus.post(new RegisterVideoOutput(surfaceView));
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ Log.d(TAG, "onPause");
+ eventBus.unregister(this);
+ eventBus.post(new RegisterVideoOutput(null, null));
+
+ super.onPause();
+ }
+
+
+ //TODO sliding_layout.collapsePanel();// --> on Orientation change!!!!
+
+ /*
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ sliding_layout.collapsePanel();
+ super.onConfigurationChanged(newConfig);
+ }
+ */
+
+ public PodcastSlidingUpPanelLayout getSlidingLayout() {
+ return sliding_layout;
+ }
+
+ public boolean handlePodcastBackPressed() {
+ if(podcastFragment != null && sliding_layout.isPanelExpanded()) {
+ if (!podcastFragment.onBackPressed())
+ sliding_layout.collapsePanel();
+ return true;
+ }
+ return false;
+ }
+
+ public void UpdatePodcastView() {
+
+ if(podcastFragment != null) {
+ getSupportFragmentManager().beginTransaction().remove(podcastFragment).commitAllowingStateLoss();
+ }
+
+
+ SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ if(mPrefs.getBoolean(SettingsActivity.CB_ENABLE_PODCASTS_STRING, false)) {
+ podcastFragment = PodcastFragment.newInstance(null, null);
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.podcast_frame, podcastFragment)
+ .commitAllowingStateLoss();
+ } else {
+ sliding_layout.getChildAt(1).setVisibility(View.GONE);
+ podcastFragment = null;
+ }
+ }
+
+
+ boolean surfaceInitalized = false;
+ boolean isVideoViewVisible = true;
+ public void onEventMainThread(UpdatePodcastStatusEvent podcast) {
+
+ if (podcast.isVideoFile()) {
+ if((!isVideoViewVisible || !surfaceInitalized) && rlVideoPodcastSurfaceWrapper.isPositionReady()) {
+ surfaceInitalized = true;
+ isVideoViewVisible = true;
+
+ rlVideoPodcastSurfaceWrapper.setVisibility(View.VISIBLE);
+ //AlphaAnimator.AnimateVisibilityChange(rlVideoPodcastSurfaceWrapper, View.VISIBLE);
+
+
+ SurfaceView surfaceView = new SurfaceView(this);
+ surfaceView.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT));
+ rlVideoPodcastSurfaceWrapper.addView(surfaceView);
+
+ eventBus.post(new RegisterVideoOutput(surfaceView, rlVideoPodcastSurfaceWrapper));
+ togglePodcastVideoViewAnimation();
+ }
+ } else if(isVideoViewVisible) {
+ isVideoViewVisible = false;
+
+ eventBus.post(new RegisterVideoOutput(null, null));
+
+ rlVideoPodcastSurfaceWrapper.setVisibility(View.GONE);
+ //AlphaAnimator.AnimateVisibilityChange(rlVideoPodcastSurfaceWrapper, View.GONE);
+
+ rlVideoPodcastSurfaceWrapper.removeAllViews();
+ }
+
+ }
+
+ private static final int animationTime = 300; //Milliseconds
+ float oldScaleFactor = 1;
+ boolean isFullScreen = false;
+ float scaleFactor = 1;
+ boolean useAnimation = false;
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
+ public void onEventMainThread(VideoDoubleClicked doubleClicked) {
+ appHeight = getWindow().getDecorView().findViewById(android.R.id.content).getHeight();
+ appWidth = getWindow().getDecorView().findViewById(android.R.id.content).getWidth();
+
+ if(isFullScreen) {
+ rlVideoPodcastSurfaceWrapper.setDisableScale(false);
+ togglePodcastVideoViewAnimation();
+ } else {
+ rlVideoPodcastSurfaceWrapper.setDisableScale(true);
+ oldScaleFactor = rlVideoPodcastSurfaceWrapper.getScaleFactor();
+
+ final View view = rlVideoPodcastSurfaceWrapper;
+
+ final float oldHeight = view.getLayoutParams().height;
+ final float oldWidth = view.getLayoutParams().width;
+
+
+ //view.setPivotX(oldWidth/2);
+ //view.setPivotY(oldHeight/2);
+
+ /*
+ Display display = getWindowManager().getDefaultDisplay();
+ float width = display.getWidth(); // deprecated
+ float height = display.getHeight(); // deprecated
+ */
+
+
+
+ scaleFactor = appWidth / (float) view.getWidth();
+ float newHeightTemp = oldHeight * scaleFactor;
+ float newWidthTemp = oldWidth * scaleFactor;
+
+ //view.animate().scaleX(scaleFactor).scaleY(scaleFactor).setDuration(100);
+ //scaleView(view, 1f, scaleFactor, 1f, scaleFactor);
+
+
+ if(newHeightTemp > appHeight) { //Could happen on Tablets or in Landscape Mode
+ scaleFactor = appHeight / (float) view.getHeight();
+ newHeightTemp = oldHeight * scaleFactor;
+ newWidthTemp = oldWidth * scaleFactor;
+ }
+
+
+ final float newHeight = newHeightTemp;
+ final float newWidth = newWidthTemp;
+ float newXPosition = rlVideoPodcastSurfaceWrapper.getVideoXPosition() + (int) getResources().getDimension(R.dimen.activity_vertical_margin);// (appWidth / 2) + dipToPx(10);
+ float newYPosition = (appHeight/2) + ((newHeight/2) - oldHeight);
+
+ useAnimation = true;
+
+ view.animate().x(newXPosition).y(newYPosition).setDuration(animationTime).setListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ if(useAnimation) {
+ view.startAnimation(new SizeAnimator(view, newWidth, newHeight, oldWidth, oldHeight, animationTime).sizeAnimator);
+ }
+ useAnimation = false;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animator) {
+
+ }
+ });
+
+
+ //rlVideoPodcastSurfaceWrapper.animate().scaleX(scaleFactor).scaleY(scaleFactor).x(newXPosition).y(newYPosition).setDuration(500).setListener(onResizeListener);
+ //surfaceView.animate().scaleX(scaleFactor).scaleY(scaleFactor).setDuration(500);
+
+ //oldScaleFactor
+ //scaleFactor = dipToPx(oldWidth) / newWidth;
+ //scaleFactor = (1/oldScaleFactor) * dipToPx(oldWidth) / newWidth;
+ //scaleFactor = oldWidth / newWidth;
+
+ scaleFactor = 1/scaleFactor;
+ }
+
+ isFullScreen = !isFullScreen;
+ }
+
+
+
+ Animator.AnimatorListener onResizeListener = new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ View view = rlVideoPodcastSurfaceWrapper;
+
+
+ int height = (int) (view.getHeight() * view.getScaleY());
+ int width = (int) (view.getWidth() * view.getScaleX());
+
+ //view.setPivotX(width/2);
+ //view.setPivotY(height/2);
+
+ view.setScaleX(1);
+ view.setScaleY(1);
+ view.getLayoutParams().height = height;
+ view.getLayoutParams().width = width;
+ view.setLayoutParams(view.getLayoutParams());
+
+ //view.setX(0);
+
+ /*
+ surfaceView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
+ surfaceView.forceLayout();
+ surfaceView.requestLayout();
+ surfaceView.invalidate();
+ surfaceView.requestLayout();
+ surfaceView.forceLayout();
+ */
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animator) {
+
+ }
+ };
+
+
+ /*
+ public void scaleView(View v, float startX, float startY, float endX, float endY) {
+ Animation anim = new ScaleAnimation(
+ startX, endX, // Start and end values for the X axis scaling
+ startY, endY, // Start and end values for the Y axis scaling
+ Animation.RELATIVE_TO_SELF, 0f, // Pivot point of X scaling
+ Animation.RELATIVE_TO_SELF, 0f); // Pivot point of Y scaling
+ anim.setFillAfter(true); // Needed to keep the result of the animation
+ anim.setDuration(500);
+ v.startAnimation(anim);
+ }
+ */
+
+ /*
+ public void onEvent(PodcastPlaybackService.PodcastPlaybackServiceStarted serviceStarted) {
+
+ }
+ */
+
+
+ public void togglePodcastVideoViewAnimation() {
+ boolean isLeftSliderOpen = false;
+
+ if(this instanceof NewsReaderListActivity) {
+ isLeftSliderOpen = ((NewsReaderListActivity) this).mSlidingLayout.isOpen();
+ }
+
+ boolean isTabletView = SubscriptionExpandableListAdapter.isTwoPane(this);
+
+ int podcastMediaControlHeightDp = pxToDp((int) getResources().getDimension(R.dimen.podcast_media_control_height));
+
+ if(isTabletView && sliding_layout.isPanelExpanded()) { //On Tablets
+ animateToPosition(podcastMediaControlHeightDp);
+ } else if(!isTabletView && isLeftSliderOpen)
+ animateToPosition(0);
+ else if(sliding_layout.isPanelExpanded()) {
+ animateToPosition(podcastMediaControlHeightDp);
+ } else {
+ animateToPosition(64);
+ }
+ }
+
+ public static int pxToDp(int px)
+ {
+ return (int) (px / Resources.getSystem().getDisplayMetrics().density);
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
+ public void animateToPosition(final int yPosition) {
+ appHeight = getWindow().getDecorView().findViewById(android.R.id.content).getHeight();
+ appWidth = getWindow().getDecorView().findViewById(android.R.id.content).getWidth();
+
+ final View view = rlVideoPodcastSurfaceWrapper; //surfaceView
+
+ /*
+ viewToMove.getLayoutParams().height *= scaleFactor;
+ viewToMove.getLayoutParams().width *= scaleFactor;
+ viewToMove.setLayoutParams(viewToMove.getLayoutParams());
+ */
+ //float newHeight = viewToMove.getLayoutParams().height * scaleFactor;
+ //float newWidth = viewToMove.getLayoutParams().width * scaleFactor;
+ //viewToMove.animate().scaleX(scaleFactor).scaleY(scaleFactor).setDuration(100);
+ //viewToMove.startAnimation(new SizeAnimator(viewToMove, newWidth, newHeight, 500).sizeAnimator);
+
+ //scaleView(viewToMove, scaleFactor, 1f, scaleFactor, 1f);
+
+
+
+
+
+
+
+
+
+
+ if(scaleFactor != 1) {
+ int oldHeight = view.getLayoutParams().height;
+ int oldWidth = view.getLayoutParams().width;
+ int newHeight = view.getLayoutParams().height *= scaleFactor;
+ int newWidth = view.getLayoutParams().width *= scaleFactor;
+ scaleFactor = 1;
+
+ Animation animator = new SizeAnimator(view, newWidth, newHeight, oldWidth, oldHeight, animationTime).sizeAnimator;
+ animator.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ animateToPosition(yPosition);
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+
+ }
+ });
+ view.startAnimation(animator);
+ } else {
+ int absoluteYPosition = appHeight - view.getHeight() - (int) getResources().getDimension(R.dimen.activity_vertical_margin) - (int) dipToPx(yPosition);
+
+ //int animationpos = 500;
+ float xPosition = rlVideoPodcastSurfaceWrapper.getVideoXPosition();
+ view.animate().x(xPosition).y(absoluteYPosition).setDuration(animationTime);
+ //scaleX(scaleFactor).scaleY(scaleFactor)
+ }
+
+
+
+
+ /*
+ int height = (int)(view.getHeight() * scaleFactor);
+ int width = (int)(view.getWidth() * scaleFactor);
+ view.setScaleX(oldScaleFactor);
+ view.setScaleY(oldScaleFactor);
+ view.getLayoutParams().height = height;
+ view.getLayoutParams().width = width;
+*/
+ oldScaleFactor = 1;
+
+
+ }
+
+
+ float dipToPx(float dip) {
+ Resources r = getResources();
+ float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, r.getDisplayMetrics());
+ return px;
+ }
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SettingsActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SettingsActivity.java
index 13fd686e..d611fe66 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SettingsActivity.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SettingsActivity.java
@@ -51,6 +51,7 @@ import java.text.DecimalFormat;
import java.util.List;
import de.luhmer.owncloudnewsreader.database.DatabaseConnection;
+import de.luhmer.owncloudnewsreader.helper.FileUtils;
import de.luhmer.owncloudnewsreader.helper.ImageHandler;
import de.luhmer.owncloudnewsreader.helper.PostDelayHandler;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
@@ -597,7 +598,7 @@ public class SettingsActivity extends SherlockPreferenceActivity {
protected Void doInBackground(Void... params) {
try
{
- getFolderSize(new File(ImageHandler.getPath(_mActivity)));
+ getFolderSize(new File(FileUtils.getPath(_mActivity)));
mSize = dcmFormat.format(size / 1024d / 1024d) + "MB";
mCount = String.valueOf(count) + " Files";
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/AsyncTask_DownloadImages.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/AsyncTask_DownloadImages.java
index 9b373731..a4457b48 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/AsyncTask_DownloadImages.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/AsyncTask_DownloadImages.java
@@ -26,25 +26,26 @@ import android.os.AsyncTask;
import java.util.List;
+import de.luhmer.owncloudnewsreader.helper.FileUtils;
import de.luhmer.owncloudnewsreader.helper.ImageHandler;
public class AsyncTask_DownloadImages extends AsyncTask<Void, Void, Void>{
String text;
Context context;
-
+
public AsyncTask_DownloadImages(String text, Context context) {
this.text = text;
this.context = context;
}
-
+
@Override
protected Void doInBackground(Void... params) {
if(text != null)
{
List<String> links = ImageHandler.getImageLinksFromText(text);
-
+
for(String link : links)
- new GetImageAsyncTask(link, null, 999, ImageHandler.getPathImageCache(context), context, null).execute();
+ new GetImageAsyncTask(link, null, 999, FileUtils.getPathImageCache(context), context, null).execute();
}
return null;
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/IKeyValuePair.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/IKeyValuePair.java
new file mode 100644
index 00000000..6c930681
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/IKeyValuePair.java
@@ -0,0 +1,65 @@
+package de.luhmer.owncloudnewsreader.collections;
+
+/*
+
+ * Copyright (c) 2008, 2009 by Xuggle Incorporated. All rights reserved.
+
+ *
+
+ * This file is part of Xuggler.
+
+ *
+
+ * You can redistribute Xuggler and/or modify it under the terms of the GNU
+
+ * Affero General Public License as published by the Free Software
+
+ * Foundation, either version 3 of the License, or (at your option) any
+
+ * later version.
+
+ *
+
+ * Xuggler is distributed in the hope that it will be useful, but WITHOUT
+
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+
+ * License for more details.
+
+ *
+
+ * You should have received a copy of the GNU Affero General Public License
+
+ * along with Xuggler. If not, see <http://www.gnu.org/licenses/>.
+
+ */
+
+
+/**
+ * A key-alue pair.
+ *
+ * @author aclarke
+ *
+ */
+public interface IKeyValuePair
+
+{
+
+ /**
+ * Get the key.
+ *
+ * @return the key.
+ */
+ public String getKey();
+
+
+ /**
+ * Get the value.
+ *
+ * @return the value.
+ */
+ public String getValue();
+
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/KeyValuePair.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/KeyValuePair.java
new file mode 100644
index 00000000..33397f26
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/KeyValuePair.java
@@ -0,0 +1,154 @@
+package de.luhmer.owncloudnewsreader.collections;
+
+/*
+
+ * Copyright (c) 2008, 2009 by Xuggle Incorporated. All rights reserved.
+
+ *
+
+ * This file is part of Xuggler.
+
+ *
+
+ * You can redistribute Xuggler and/or modify it under the terms of the GNU
+
+ * Affero General Public License as published by the Free Software
+
+ * Foundation, either version 3 of the License, or (at your option) any
+
+ * later version.
+
+ *
+
+ * Xuggler is distributed in the hope that it will be useful, but WITHOUT
+
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+
+ * License for more details.
+
+ *
+
+ * You should have received a copy of the GNU Affero General Public License
+
+ * along with Xuggler. If not, see <http://www.gnu.org/licenses/>.
+
+ */
+
+
+import java.util.Map.Entry;
+
+
+/**
+
+ * An implementation of {@link IKeyValuePair} with immutable keys
+
+ * but resettable values.
+
+ *
+
+ * @author aclarke
+
+ *
+
+ */
+
+public class KeyValuePair implements IKeyValuePair, Entry<String, String>
+
+{
+
+ private final String mKey;
+
+ private String mValue;
+
+
+
+ /**
+
+ * Creates a new key-value pair.
+
+ *
+
+ * @param key
+
+ * The key; may not be null.
+
+ * @param value
+
+ * The value; may be null.
+
+ * @throws IllegalArgumentException
+
+ * if <code>name==null</code>.
+
+ */
+
+ public KeyValuePair(final String key, final String value)
+
+ {
+
+ if (key == null)
+
+ throw new IllegalArgumentException("must have non null name");
+
+ mKey = key;
+
+ mValue = value;
+
+ }
+
+
+
+ /**
+
+ * {@inheritDoc}
+
+ */
+
+ public String getKey()
+
+ {
+
+ return mKey;
+
+ }
+
+
+
+ /**
+
+ * {@inheritDoc}
+
+ */
+
+ public String getValue()
+
+ {
+
+ return mValue;
+
+ }
+
+
+
+ /**
+
+ * {@inheritDoc}
+
+ */
+
+ public String setValue(String value)
+
+ {
+
+ final String retval = mValue;
+
+ mValue = value;
+
+ return retval;
+
+ }
+
+}
+
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/MapUtils.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/MapUtils.java
new file mode 100644
index 00000000..ef05d858
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/MapUtils.java
@@ -0,0 +1,145 @@
+package de.luhmer.owncloudnewsreader.collections;
+
+/*
+ * Copyright (c) 2008, 2009 by Xuggle Incorporated. All rights reserved.
+ *
+ * This file is part of Xuggler.
+ *
+ * You can redistribute Xuggler and/or modify it under the terms of the GNU
+ * Affero General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Xuggler is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Xuggler. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Some useful utilities for mapping lists to maps and back.
+ * @author aclarke
+ *
+ */
+public class MapUtils
+{
+ /**
+ * How {@link MapUtils#listToMap(List, Map, ListToMapMode)} treats
+ * duplicate values in the input list.
+ * @author aclarke
+ *
+ */
+ public enum ListToMapMode
+ {
+ /**
+ * Last item in list always wins.
+ */
+ LAST_WINS,
+ /**
+ * First item in list always wins.
+ */
+ FIRST_WINS,
+ }
+
+ /**
+ * Converts a list of key-value pairs into a {@link Map}, with either
+ * the first duplicate key always being inserted, or the last duplicate key
+ * always being inserted.
+ *
+ * @param list
+ * The list of name value pairs to convert.
+ * @param mapToFill
+ * The map to fill. This method will empty the list first.
+ * @param mode
+ * How duplicate values in <code>list</code> should be treated.
+ */
+ public static void listToMap(final List<? extends IKeyValuePair> list,
+ final Map<String, String> mapToFill, final ListToMapMode mode)
+ {
+ if (list == null)
+ throw new IllegalArgumentException();
+ if (mapToFill == null)
+ throw new IllegalArgumentException();
+ mapToFill.clear();
+ for (IKeyValuePair pair : list)
+ {
+ if (pair != null)
+ {
+ if (mode == ListToMapMode.FIRST_WINS)
+ {
+ if (mapToFill.containsKey(pair.getKey()))
+ continue;
+ }
+ mapToFill.put(pair.getKey(), pair.getValue());
+ }
+ }
+ }
+
+ /**
+ * Converts a list of key-value pairs into a {@link Map}, with either
+ * the first duplicate key always being inserted, or the last duplicate key
+ * always being inserted.
+ *
+ * @param list
+ * The list of name value pairs to convert.
+ * @param mode
+ * How duplicate values in <code>list</code> should be treated.
+ * @return a new {@link Map} of key-value pairs.
+ */
+ public static Map<String, String> listToMap(
+ final List<? extends IKeyValuePair> list, final ListToMapMode mode)
+ {
+ final Map<String, String> retval = new HashMap<String, String>();
+ listToMap(list, retval, mode);
+ return retval;
+ }
+
+ /**
+ * Converts a map into a {@link List} of {@link IKeyValuePair} objects.
+ * @param map Map to convert.
+ * @param listToFill List to fill. The list has {@link List#clear()} called
+ * before any items are added.
+ */
+ public static void mapToList(final Map<String, String> map, final List<IKeyValuePair> listToFill)
+ {
+ if (map == null || listToFill == null)
+ throw new IllegalArgumentException();
+ final Set<Entry<String, String>> entries = map.entrySet();
+ for(Entry<String, String> entry : entries)
+ {
+ final String name = entry.getKey();
+ final String value = entry.getValue();
+ if (name == null)
+ continue;
+ IKeyValuePair pair = new KeyValuePair(name, value);
+ listToFill.add(pair);
+ }
+ }
+ /**
+ * Converts a map into a {@link List} of {@link IKeyValuePair} objects, and
+ * returns the new list.
+ * @param map Map to convert.
+ * @return A new {@link List} containing all key-value pairs in <code>map</code>
+ * as {@link IKeyValuePair} objects.
+ */
+ public static List<IKeyValuePair> mapToList(final Map<String, String> map)
+ {
+ final List<IKeyValuePair> retval = new ArrayList<IKeyValuePair>();
+ mapToList(map, retval);
+ return retval;
+ }
+
+
+}
+
+
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/URLParams.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/URLParams.java
new file mode 100644
index 00000000..cb681f22
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/collections/URLParams.java
@@ -0,0 +1,198 @@
+package de.luhmer.owncloudnewsreader.collections;
+
+/*
+ * Copyright (c) 2008, 2009 by Xuggle Incorporated. All rights reserved.
+ *
+ * This file is part of Xuggler.
+ *
+ * You can redistribute Xuggler and/or modify it under the terms of the GNU
+ * Affero General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Xuggler is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Xuggler. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Utilities for generating and parsing URL parameter strings
+ *
+ * @author aclarke
+ *
+ */
+public class URLParams
+{
+ /**
+ * Parse the query string, placing the results in <code>paramsToFill</code>,
+ * assuming UTF-8 encoding.
+ *
+ * @param queryString
+ * The query string (without leading "?").
+ * @param paramsToFill
+ * A list to add entries to; the list is not emptied first by this
+ * method. Entries are added in the order they are found.
+ * @see URLParams#parseQueryString(String, List, String)
+ */
+ public static void parseQueryString(final String queryString,
+ final List<KeyValuePair> paramsToFill)
+ {
+ try
+ {
+ parseQueryString(queryString, paramsToFill, "UTF-8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException("What? UTF-8 isn't a valid encoding", e);
+ }
+ }
+
+ /**
+ * Parse the query string, and return as a new list, assuming UTF-8 encoding.
+ *
+ * @param queryString
+ * The query string (without leading "?").
+ * @return A new list with all entries included, in the order they were found.
+ * @see URLParams#parseQueryString(String, List, String)
+ */
+ public static List<KeyValuePair> parseQueryString(final String queryString)
+ {
+ final List<KeyValuePair> retval = new ArrayList<KeyValuePair>();
+ parseQueryString(queryString, retval);
+ return retval;
+ }
+
+ /**
+ * Parse the query string, and return as a new list, assuming UTF-8 encoding.
+ *
+ * @param queryString
+ * The query string (without leading "?").
+ * @param encoding
+ * An encoding (e.g. "UTF-8") to decode parameters as.
+ * @return A new list with all entries included, in the order they were found.
+ * @throws UnsupportedEncodingException
+ * If the <code>encode</code> specified is not supported.
+ * @see URLParams#parseQueryString(String, List, String)
+ */
+ public static List<KeyValuePair> parseQueryString(final String queryString,
+ final String encoding) throws UnsupportedEncodingException
+ {
+ final List<KeyValuePair> retval = new ArrayList<KeyValuePair>();
+ parseQueryString(queryString, retval, encoding);
+ return retval;
+ }
+
+ /**
+ * Parse the query string, placing the results in <code>paramsToFill</code>.
+ *
+ * @param queryString
+ * The query string (without leading "?").
+ * @param parametersToFill
+ * A list to add entries to; the list is not emptied first by this
+ * method. Entries are added in the order they are found.
+ * @param encoding
+ * An encoding (e.g. "UTF-8") to decode parameters as.
+ * @throws UnsupportedEncodingException
+ * If the <code>encode</code> specified is not supported.
+ * @see URLParams#parseQueryString(String, List, String)
+ */
+ public static void parseQueryString(final String queryString,
+ final List<KeyValuePair> parametersToFill, final String encoding)
+ throws UnsupportedEncodingException
+ {
+ final String params[] = queryString.split("&");
+ for (String param : params)
+ {
+ final String[] tuple = param.split("=");
+ final KeyValuePair retval = new KeyValuePair(URLDecoder.decode(
+ tuple[0], encoding), tuple.length > 1 ? URLDecoder.decode(tuple[1],
+ encoding) : null);
+ parametersToFill.add(retval);
+ }
+ }
+
+ /**
+ * Generates a query string suitable for appending to a URI that encodes the
+ * given parameters as UTF-8 encoding strings.
+ *
+ * @param params
+ * A list of name value pairs to encode.
+ * @return A string suitable for appending to URIs.
+ */
+ public static String generateQueryString(
+ final List<? extends IKeyValuePair> params)
+ {
+ try
+ {
+ return generateQueryString(params, "UTF-8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException("What? UTF-8 isn't a valid encoding", e);
+ }
+ }
+
+ /**
+ * Generates a query string suitable for appending to a URI that encodes the
+ * given parameters as specified by the encoding parameter.
+ *
+ * @param params
+ * A list of name value pairs to encode.
+ * @param encoding
+ * The text encoding to use
+ * @return A string suitable for appending to URIs.
+ * @throws UnsupportedEncodingException
+ * If the encoding is not supported.
+ */
+ public static String generateQueryString(
+ final List<? extends IKeyValuePair> params, final String encoding)
+ throws UnsupportedEncodingException
+ {
+ if (params == null)
+ throw new IllegalArgumentException("need params");
+ if (encoding == null)
+ throw new UnsupportedEncodingException();
+
+ final StringBuilder builder = new StringBuilder();
+ final Iterator<? extends IKeyValuePair> iterator = params.iterator();
+ boolean hasNext = iterator.hasNext();
+ while (hasNext)
+ {
+ IKeyValuePair pair = iterator.next();
+ if (pair != null)
+ {
+ final String key = pair.getKey();
+ final String value = pair.getValue();
+ builder.append(URLEncoder.encode(key, encoding));
+ if (value != null)
+ {
+ builder.append("=");
+ builder.append(URLEncoder.encode(value, encoding));
+ }
+ }
+ if (iterator.hasNext())
+ {
+ if (pair != null)
+ builder.append("&");
+ hasNext = true;
+ }
+ else
+ {
+ hasNext = false;
+ }
+ }
+ return builder.toString();
+ }
+}
+
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnection.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnection.java
index 49e8481b..5a0a13df 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnection.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnection.java
@@ -29,15 +29,17 @@ import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.util.SparseArray;
+import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import de.luhmer.owncloudnewsreader.Constants;
import de.luhmer.owncloudnewsreader.ListView.UnreadFolderCount;
-import de.luhmer.owncloudnewsreader.model.AudioPodcastItem;
import de.luhmer.owncloudnewsreader.model.PodcastFeedItem;
+import de.luhmer.owncloudnewsreader.model.PodcastItem;
import de.luhmer.owncloudnewsreader.model.RssFile;
+import de.luhmer.owncloudnewsreader.services.PodcastDownloadService;
import static de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_ITEMS;
import static de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS;
@@ -932,7 +934,7 @@ public class DatabaseConnection {
//Log.d("DatabaseConnection", "Inserted Rows: " + result);
}
- private static final String ALLOWED_PODCASTS_TYPES = "audio/mp3', 'audio/mpeg', 'audio/ogg', 'audio/opus', 'audio/ogg;codecs=opus";
+ private static final String ALLOWED_PODCASTS_TYPES = "audio/mp3', 'audio/mpeg', 'audio/ogg', 'audio/opus', 'audio/ogg;codecs=opus', 'youtube";
public List<PodcastFeedItem> getListOfFeedsWithAudioPodcasts() {
@@ -965,13 +967,13 @@ public class DatabaseConnection {
return result;
}
- public List<AudioPodcastItem> getListOfAudioPodcastsForFeed(String feedId) {
+ public List<PodcastItem> getListOfAudioPodcastsForFeed(Context context, String feedId) {
String buildSQL = "SELECT rowid, " + RSS_ITEM_TITLE + ", " + RSS_ITEM_ENC_LINK + ", " + RSS_ITEM_ENC_MIME + " FROM " + RSS_ITEM_TABLE +
" WHERE " + RSS_ITEM_ENC_MIME + " IN ('" + ALLOWED_PODCASTS_TYPES + "') AND " + RSS_ITEM_SUBSCRIPTION_ID + " = " + feedId;
- List<AudioPodcastItem> result = new ArrayList<AudioPodcastItem>();
+ List<PodcastItem> result = new ArrayList<PodcastItem>();
Cursor cursor = database.rawQuery(buildSQL, null);
try
{
@@ -981,11 +983,17 @@ public class DatabaseConnection {
{
cursor.moveToFirst();
do {
- AudioPodcastItem podcastItem = new AudioPodcastItem();
+ PodcastItem podcastItem = new PodcastItem();
podcastItem.itemId = cursor.getString(0);
podcastItem.title = cursor.getString(1);
podcastItem.link = cursor.getString(2);
podcastItem.mimeType = cursor.getString(3);
+
+ File file = new File(PodcastDownloadService.getUrlToPodcastFile(context, podcastItem.link, false));
+ podcastItem.offlineCached = file.exists();
+
+
+
result.add(podcastItem);
} while(cursor.moveToNext());
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/NewPodcastPlaybackListener.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/NewPodcastPlaybackListener.java
new file mode 100644
index 00000000..f0fa6c19
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/NewPodcastPlaybackListener.java
@@ -0,0 +1,7 @@
+package de.luhmer.owncloudnewsreader.events.podcast;
+
+/**
+ * Created by David on 29.06.2014.
+ */
+public class NewPodcastPlaybackListener {
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/OpenAudioPodcastEvent.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/OpenAudioPodcastEvent.java
deleted file mode 100644
index 22f6e604..00000000
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/OpenAudioPodcastEvent.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package de.luhmer.owncloudnewsreader.events.podcast;
-
-/**
- * Created by David on 21.06.2014.
- */
-public class OpenAudioPodcastEvent {
- public String pathToFile;
- public String mediaTitle;
-}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/OpenPodcastEvent.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/OpenPodcastEvent.java
new file mode 100644
index 00000000..ade8ebfb
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/OpenPodcastEvent.java
@@ -0,0 +1,17 @@
+package de.luhmer.owncloudnewsreader.events.podcast;
+
+/**
+ * Created by David on 21.06.2014.
+ */
+public class OpenPodcastEvent {
+
+ public OpenPodcastEvent(String pathToFile, String mediaTitle, boolean isVideoFile) {
+ this.pathToFile = pathToFile;
+ this.mediaTitle = mediaTitle;
+ this.isVideoFile = isVideoFile;
+ }
+
+ public boolean isVideoFile;
+ public String pathToFile;
+ public String mediaTitle;
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/RegisterVideoOutput.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/RegisterVideoOutput.java
new file mode 100644
index 00000000..f2514a13
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/RegisterVideoOutput.java
@@ -0,0 +1,18 @@
+package de.luhmer.owncloudnewsreader.events.podcast;
+
+import android.view.SurfaceView;
+import android.view.View;
+
+/**
+ * Created by David on 28.06.2014.
+ */
+public class RegisterVideoOutput {
+
+ public RegisterVideoOutput(SurfaceView surfaceView, View parentResizableView) {
+ this.surfaceView = surfaceView;
+ this.parentResizableView = parentResizableView;
+ }
+
+ public SurfaceView surfaceView;
+ public View parentResizableView;
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/StartDownloadPodcast.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/StartDownloadPodcast.java
new file mode 100644
index 00000000..0c109ae0
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/StartDownloadPodcast.java
@@ -0,0 +1,10 @@
+package de.luhmer.owncloudnewsreader.events.podcast;
+
+import de.luhmer.owncloudnewsreader.model.PodcastItem;
+
+/**
+ * Created by David on 28.06.2014.
+ */
+public class StartDownloadPodcast {
+ public PodcastItem podcast;
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/UpdatePodcastStatusEvent.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/UpdatePodcastStatusEvent.java
index f26bbf44..4d41abc5 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/UpdatePodcastStatusEvent.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/UpdatePodcastStatusEvent.java
@@ -10,6 +10,8 @@ public class UpdatePodcastStatusEvent {
private String title;
private boolean playing;
private boolean preparingFile;
+ private boolean fileLoaded;
+ private boolean isVideoFile;
public String getTitle() {
return title;
@@ -31,12 +33,20 @@ public class UpdatePodcastStatusEvent {
return preparingFile;
}
- public UpdatePodcastStatusEvent(long current, long max, boolean playing, String title, boolean preparingFile) {
+ public boolean isFileLoaded() {
+ return fileLoaded;
+ }
+
+ public boolean isVideoFile() { return isVideoFile; }
+
+ public UpdatePodcastStatusEvent(long current, long max, boolean playing, String title, boolean preparingFile, boolean fileLoaded, boolean isVideoFile) {
this.current = current;
this.max = max;
this.playing = playing;
this.title = title;
this.preparingFile = preparingFile;
+ this.fileLoaded = fileLoaded;
+ this.isVideoFile = isVideoFile;
}
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/VideoDoubleClicked.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/VideoDoubleClicked.java
new file mode 100644
index 00000000..4b3f76e0
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/VideoDoubleClicked.java
@@ -0,0 +1,7 @@
+package de.luhmer.owncloudnewsreader.events.podcast;
+
+/**
+ * Created by David on 30.06.2014.
+ */
+public class VideoDoubleClicked {
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/AlphaAnimator.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/AlphaAnimator.java
new file mode 100644
index 00000000..319fa564
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/AlphaAnimator.java
@@ -0,0 +1,53 @@
+package de.luhmer.owncloudnewsreader.helper;
+
+import android.view.View;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+
+/**
+ * Created by David on 02.07.2014.
+ */
+public class AlphaAnimator {
+
+ public static void AnimateVisibilityChange(final View view, final int visibilityTo) {
+
+
+ Animation animation;
+ if(visibilityTo == View.GONE) {
+ animation = new AlphaAnimation(1f, 0f);
+ } else {
+ view.setAlpha(0.1f);
+ view.setVisibility(View.VISIBLE);
+ animation = new AlphaAnimation(0f, 1f);
+ }
+
+
+ animation.setFillAfter(true);
+ animation.setDuration(1000);
+ animation.setStartOffset(1000);
+ //animation.setStartOffset(5000);
+
+ /*
+ animation.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ view.setVisibility(visibilityTo);
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+
+ }
+ });
+ */
+
+ animation.start();
+
+
+ }
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/DatabaseUtils.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/DatabaseUtils.java
index 51370fc5..8ef35a43 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/DatabaseUtils.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/DatabaseUtils.java
@@ -55,6 +55,6 @@ public class DatabaseUtils {
}
public static File GetPath(Context context) {
- return new File(ImageHandler.getPath(context) + "/dbBackup/" + DatabaseHelper.DATABASE_NAME);
+ return new File(FileUtils.getPath(context) + "/dbBackup/" + DatabaseHelper.DATABASE_NAME);
}
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FavIconHandler.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FavIconHandler.java
index 9f2ac621..0dbadfba 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FavIconHandler.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FavIconHandler.java
@@ -46,7 +46,7 @@ public class FavIconHandler {
{
try
{
- File favIconFile = ImageHandler.getFullPathOfCacheFile(URL_TO_PAGE, ImageHandler.getPathFavIcons(context));
+ File favIconFile = ImageHandler.getFullPathOfCacheFile(URL_TO_PAGE, FileUtils.getPathFavIcons(context));
if(favIconFile.isFile() && favIconFile.length() > 0)
{
if(feedID != null) {
@@ -94,7 +94,7 @@ public class FavIconHandler {
int key = Integer.parseInt(feedID);
favIconToFeedId.put(key, favIconCache);
- GetImageAsyncTask giAsync = new GetImageAsyncTask(WEB_URL_TO_FILE, favIconDownloadFinished, key, ImageHandler.getPathFavIcons(context), context, null);
+ GetImageAsyncTask giAsync = new GetImageAsyncTask(WEB_URL_TO_FILE, favIconDownloadFinished, key, FileUtils.getPathFavIcons(context), context, null);
giAsync.scaleImage = true;
giAsync.dstHeight = 2*32;
giAsync.dstWidth = 2*32;
@@ -146,7 +146,7 @@ public class FavIconHandler {
imageView.setImageDrawable(null);
- GetImageAsyncTask giAsync = new GetImageAsyncTask(WEB_URL_TO_FILE, imgDownloadFinished, key, ImageHandler.getPathFavIcons(context), context/*, imageView*/, lruCache);
+ GetImageAsyncTask giAsync = new GetImageAsyncTask(WEB_URL_TO_FILE, imgDownloadFinished, key, FileUtils.getPathFavIcons(context), context/*, imageView*/, lruCache);
giAsync.scaleImage = true;
giAsync.dstHeight = 2*32;
giAsync.dstWidth = 2*32;
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FileUtils.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FileUtils.java
index d329987c..cb230b35 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FileUtils.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FileUtils.java
@@ -21,6 +21,9 @@
package de.luhmer.owncloudnewsreader.helper;
+import android.content.Context;
+import android.os.Environment;
+
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -35,7 +38,7 @@ public class FileUtils {
* <br/>
* <i> Note: <code>fromFile</code> and <code>toFile</code> will be closed by
* this function.</i>
- *
+ *
* @param fromFile
* - FileInputStream for the file to copy from.
* @param toFile
@@ -60,4 +63,45 @@ public class FileUtils {
}
}
}
+
+
+
+
+
+ public static String getPath(Context context) {
+ String url;
+ Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
+ if(isSDPresent)
+ {
+ url = Environment.getExternalStorageDirectory().getAbsolutePath();
+ if (android.os.Build.DEVICE.contains("Samsung") || android.os.Build.MANUFACTURER.contains("Samsung")) {
+ url = url + "/external_sd";
+ }
+ //url = url + "/" + context.getString(R.string.app_name);
+ url = url + "/ownCloud News Reader";
+ }
+ else
+ url = context.getCacheDir().getAbsolutePath();
+
+ return url;
+ }
+
+
+
+
+ public static String getPathPodcasts(Context context)
+ {
+ return getPath(context) + "/podcasts";
+ }
+
+ public static String getPathFavIcons(Context context)
+ {
+ return getPath(context) + "/favIcons";
+ }
+
+ public static String getPathImageCache(Context context)
+ {
+ return getPath(context) + "/imgCache";
+ }
+
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ImageHandler.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ImageHandler.java
index 87a36ac8..90c2029f 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ImageHandler.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ImageHandler.java
@@ -23,7 +23,6 @@ package de.luhmer.owncloudnewsreader.helper;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import android.os.Environment;
import java.io.File;
import java.io.FileOutputStream;
@@ -116,34 +115,6 @@ public class ImageHandler {
- public static String getPathFavIcons(Context context)
- {
- return getPath(context) + "/favIcons";
- }
-
- public static String getPathImageCache(Context context)
- {
- return getPath(context) + "/imgCache";
- }
-
- public static String getPath(Context context) {
- String url;
- Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
- if(isSDPresent)
- {
- url = Environment.getExternalStorageDirectory().getAbsolutePath();
- if (android.os.Build.DEVICE.contains("Samsung") || android.os.Build.MANUFACTURER.contains("Samsung")) {
- url = url + "/external_sd";
- }
- //url = url + "/" + context.getString(R.string.app_name);
- url = url + "/ownCloud News Reader";
- }
- else
- url = context.getCacheDir().getAbsolutePath();
-
- return url;
- }
-
public static List<String> getImageLinksFromText(String text)
{
@@ -168,14 +139,14 @@ public class ImageHandler {
public static boolean clearCache(Context context)
{
- String path = getPath(context);
+ String path = FileUtils.getPath(context);
boolean result = deleteDir(new File(path));
createNoMediaFile(context);
return result;
}
public static void createNoMediaFile(Context context) {
- String path = getPath(context);
+ String path = FileUtils.getPath(context);
createEmptyFile(path + "/.nomedia");
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/JavaYoutubeDownloader.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/JavaYoutubeDownloader.java
new file mode 100644
index 00000000..260fabe7
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/JavaYoutubeDownloader.java
@@ -0,0 +1,381 @@
+package de.luhmer.owncloudnewsreader.helper;
+
+import android.content.Context;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.CookieStore;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.client.utils.URIUtils;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.impl.client.BasicCookieStore;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.math.BigInteger;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.regex.Pattern;
+
+import de.luhmer.owncloudnewsreader.collections.IKeyValuePair;
+import de.luhmer.owncloudnewsreader.collections.KeyValuePair;
+import de.luhmer.owncloudnewsreader.collections.MapUtils;
+import de.luhmer.owncloudnewsreader.collections.URLParams;
+
+public class JavaYoutubeDownloader {
+
+ public static String newline = System.getProperty("line.separator");
+ public static final String scheme = "http";
+ public static final String host = "www.youtube.com";
+ public static final Pattern commaPattern = Pattern.compile(",");
+ public static final char[] ILLEGAL_FILENAME_CHARACTERS = { '/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':' };
+
+
+
+
+
+
+ public String getVideoID( String urlString ){
+ int start = urlString.indexOf("?v=") + 3;
+ int end = urlString.indexOf("&", start);
+ if ( end == -1 ){
+ end = urlString.length();
+ }
+
+ if(start == 2) { //Doesn't work
+ start = urlString.indexOf("/v/") + 3;
+ end = urlString.indexOf("?", start);
+ if (end == -1){
+ end = urlString.length();
+ }
+ }
+
+ return urlString.substring(start, end);
+ }
+
+ public String getExtension(int format) {
+ return "mp4";
+ }
+
+
+ public String getDownloadUrl(String url, Context context) throws Throwable {
+
+ //Map<String, String> videoInfo = getVideoInfo(getVideoID(url));// Html.fromHtml(getStringFromWebsite("http://youtube.com/get_video_info?video_id=" + getVideoID(url))).toString();
+ /*
+
+ byte[] b = videoInfo.getBytes();
+ String videoInfoAscii = new String(b, "ASCII");
+ */
+
+ //getFullPathOfPodcastYoutubeFile(url, context), ".mp4"
+
+ //String urlTemp = videoInfo.get("sig");
+
+ return getDownloadUrl(getVideoID(url), "UTF-8", "ownCloud News Reader");
+ }
+
+ public static File getFullPathOfPodcastYoutubeFile(String WEB_URL_TO_FILE, Context context) throws Exception
+ {
+ String rootPath = FileUtils.getPathPodcasts(context);
+ URL url = new URL(WEB_URL_TO_FILE.trim());
+
+ MessageDigest m = MessageDigest.getInstance("MD5");
+ m.reset();
+ m.update(url.toString().getBytes());
+ byte[] digest = m.digest();
+ BigInteger bigInt = new BigInteger(1,digest);
+ String hashtext = bigInt.toString(16);
+
+ return new File(rootPath + "/" + hashtext + ".mp4");
+ }
+
+
+ public String getDownloadUrl(String videoId, String encoding, String userAgent) throws Throwable {
+ //Utils.log.fine("Retrieving " + videoId);
+ List<NameValuePair> qparams = new ArrayList<NameValuePair>();
+ qparams.add(new BasicNameValuePair("video_id", videoId));
+ URI uri = getUri("get_video_info", qparams);
+
+ CookieStore cookieStore = new BasicCookieStore();
+ HttpContext localContext = new BasicHttpContext();
+ localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
+
+ HttpClient httpclient = new DefaultHttpClient();
+ HttpGet httpget = new HttpGet(uri);
+ httpget.setHeader("User-Agent", userAgent);
+
+ //Utils.log.finer("Executing " + uri);
+ HttpResponse response = httpclient.execute(httpget, localContext);
+ HttpEntity entity = response.getEntity();
+ if (entity != null && response.getStatusLine().getStatusCode() == 200) {
+ InputStream instream = entity.getContent();
+ String videoInfo = getStringFromInputStream(encoding, instream);
+ if (videoInfo != null && videoInfo.length() > 0) {
+ List<NameValuePair> infoMap = new ArrayList<NameValuePair>();
+ URLEncodedUtils.parse(infoMap, new Scanner(videoInfo), encoding);
+ String downloadUrl = null;
+ String filename = videoId;
+ int bestQuality = -1;
+ for (NameValuePair pair : infoMap) {
+ String key = pair.getName();
+ String val = pair.getValue();
+ //Utils.log.finest(key + "=" + val);
+ if (key.equals("title")) {
+ filename = val;
+ } else if (key.equals("url_encoded_fmt_stream_map")) {
+ String[] formats = commaPattern.split(val);
+
+ String fmtString = null;
+ //for (String fmt : formats) {
+ String fmt = formats[0]; {
+ int itagLocation = fmt.indexOf("itag=");
+ if ( itagLocation == -1 ) continue;
+ itagLocation += 5;
+ String subStr = null;
+ try {
+ subStr = fmt.substring(itagLocation, fmt.indexOf("&", itagLocation));
+ }
+ catch( IndexOutOfBoundsException ex){
+ return "Could not find the itag attribute to determine quality";
+ }
+ int tempQuality = Integer.parseInt(fmt.substring(itagLocation, fmt.indexOf("&", itagLocation)));
+ if ( bestQuality < tempQuality ){
+ bestQuality = tempQuality;
+ fmtString = fmt;
+ }
+
+ }
+ //we are going to automatically download the best quality youtube
+ int begin = fmtString.indexOf("url=");
+ int sig = fmtString.indexOf("sig=");
+ if (begin != -1) {
+ int end = fmtString.indexOf("&", begin + 4);
+ int end2 = fmtString.indexOf("&", sig + 4);
+ if (end == -1) {
+ end = fmtString.length();
+ }
+ if (end2 == -1 ){
+ end2 = fmtString.length();
+ }
+ String tempURL = fmtString.substring(begin+ 4, end );
+ String signatureURL = URLEncoder.encode("&signature="+fmtString.substring(sig + 4, end2), "UTF-8");
+ //downloadUrl = new String(URLCodec.decodeUrl((tempURL + signatureURL).getBytes()));
+ downloadUrl = URLDecoder.decode((tempURL + signatureURL), "UTF-8");
+
+ return downloadUrl;
+ //break;
+ }
+ }
+ }
+
+ /*
+ if ( downloadUrl == null ){
+ //Utils.log.fine("Content is protected");
+ }
+ filename = cleanFilename(filename);
+ if (filename.length() == 0) {
+ filename = videoId;
+ } else {
+ filename += "_" + videoId;
+ }
+ filename += "." + extension;
+ File outputfile = new File(outputdir, filename);
+ if (downloadUrl != null) {
+ downloadWithHttpClient(userAgent, downloadUrl, outputfile);
+ }
+ */
+ }
+ }
+ return "successful";
+ }
+
+ public void downloadWithHttpClient(String userAgent, String downloadUrl, File outputfile) throws Throwable {
+
+ HttpGet httpget2 = new HttpGet(downloadUrl);
+ //Utils.log.finer("Executing " + httpget2.getURI());
+ HttpClient httpclient2 = new DefaultHttpClient();
+
+ HttpResponse response2 = httpclient2.execute(httpget2);
+ HttpEntity entity2 = response2.getEntity();
+
+ if (entity2 != null && response2.getStatusLine().getStatusCode() == 200) {
+ long length = entity2.getContentLength();
+ InputStream instream2 = entity2.getContent();
+ //Utils.log.finer("Writing " + length + " bytes to " + outputfile);
+ if (outputfile.exists()) {
+ outputfile.delete();
+ }
+ FileOutputStream outstream = new FileOutputStream(outputfile);
+ try {
+ byte[] buffer = new byte[2048];
+ int count = -1;
+ while ((count = instream2.read(buffer)) != -1) {
+ outstream.write(buffer, 0, count);
+ }
+ outstream.flush();
+ } finally {
+ outstream.close();
+ }
+ }
+ }
+
+ private String cleanFilename(String filename) {
+ for (char c : ILLEGAL_FILENAME_CHARACTERS) {
+ filename = filename.replace(c, '_');
+ }
+ return filename;
+ }
+
+ private static URI getUri(String path, List<NameValuePair> qparams) throws URISyntaxException {
+ URI uri = URIUtils.createURI(scheme, host, -1, "/" + path, URLEncodedUtils.format(qparams, "UTF-8"), null);
+ return uri;
+ }
+
+ private String getStringFromInputStream(String encoding, InputStream instream) throws UnsupportedEncodingException, IOException {
+ Writer writer = new StringWriter();
+
+ char[] buffer = new char[1024];
+ try {
+ Reader reader = new BufferedReader(new InputStreamReader(instream, encoding));
+ int n;
+ while ((n = reader.read(buffer)) != -1) {
+ writer.write(buffer, 0, n);
+ }
+ } finally {
+ instream.close();
+ }
+ String result = writer.toString();
+ return result;
+ }
+
+
+ private String getStringFromWebsite(String url) {
+ String response = "";
+ DefaultHttpClient client = new DefaultHttpClient();
+ HttpGet httpGet = new HttpGet(url);
+ try {
+ HttpResponse execute = client.execute(httpGet);
+ InputStream content = execute.getEntity().getContent();
+
+ BufferedReader buffer = new BufferedReader(
+ new InputStreamReader(content));
+ String s = "";
+ //Charset cs = Charset.forName("ASCII"); // Or whatever encoding you want
+
+
+ while ((s = buffer.readLine()) != null) {
+ response += s;
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return response;
+ }
+
+
+
+
+
+ /**
+ * Gets all parameters we can figure out about this youTubeId by scraping YouTube.
+ * The URL for the underlying video will have the key "location".
+ * @param youTubeId A YouTube ID
+ * @return A map with all parameters as key-value pairs.
+ * @throws IOException if we have networking troubles
+ */
+ public static Map<String, String> getVideoInfo(String youTubeId) throws IOException
+ {
+ final Map<String, String> retval = new HashMap<String, String>();
+ getVideoInfo(youTubeId, retval);
+ return retval;
+ }
+ /**
+ * Gets all parameters we can figure out about this youTubeId by scraping YouTube.
+ * The URL for the underlying video will have the key "location".
+ * @param youTubeId A YouTube ID
+ * @param map A map to fill with data; it is not cleared first.
+ * @throws IOException if we have networking troubles
+ */
+ public static void getVideoInfo(String youTubeId, Map<String, String> map) throws IOException
+ {
+ final String host = "http://www.youtube.com";
+ final List<IKeyValuePair> params = new ArrayList<IKeyValuePair>();
+ params.add(new KeyValuePair("video_id", youTubeId));
+ final String urlString = host + "/get_video_info?&"+ URLParams.generateQueryString(params);
+
+ final URL url;
+ try
+ {
+ url = new URL(urlString);
+ }
+ catch (MalformedURLException e)
+ {
+ throw new RuntimeException("malformed url: " + urlString, e);
+ }
+ HttpURLConnection conn;
+ BufferedInputStream in;
+ byte[] data = new byte[4096]; // bad Art; fixed size
+
+ conn = (HttpURLConnection)url.openConnection();
+ if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ // badness.
+ conn.disconnect();
+ throw new RuntimeException("could not get video info: " + urlString);
+ }
+ in = new BufferedInputStream(conn.getInputStream());
+ int offset=0;
+ do {
+ offset = in.read(data, offset, data.length-offset);
+ } while(offset >= 0 && offset < data.length);
+ conn.disconnect();
+ // convert to string; ugh
+ String response = new String(data, "UTF-8");
+ System.out.println("Response: "+response);
+ // convert into parameter map
+ final Map<String, String> youTubeParams = MapUtils.listToMap(URLParams.parseQueryString(response), MapUtils.ListToMapMode.FIRST_WINS);
+
+
+ final String token = youTubeParams.get("token");
+ //if (token == null)
+ //throw new RuntimeException("Could not find youtube token: "+ urlString +"; response="+response);
+
+
+ params.clear();
+ params.add(new KeyValuePair("video_id", youTubeId));
+ params.add(new KeyValuePair("t", token));
+ final String location = host + "/get_video?"+URLParams.generateQueryString(params);
+ map.put("location", location);
+ map.putAll(youTubeParams);
+
+ }
+}
+
+
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/MenuUtilsSherlockFragmentActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/MenuUtilsSherlockFragmentActivity.java
deleted file mode 100644
index ef395650..00000000
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/MenuUtilsSherlockFragmentActivity.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/**
-* Android ownCloud News
-*
-* @author David Luhmer
-* @copyright 2013 David Luhmer david-dev@live.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-package de.luhmer.owncloudnewsreader.helper;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.preference.PreferenceManager;
-import android.support.v4.app.FragmentActivity;
-import android.util.Log;
-import android.widget.Toast;
-
-import com.actionbarsherlock.app.SherlockDialogFragment;
-import com.actionbarsherlock.app.SherlockFragmentActivity;
-import com.actionbarsherlock.view.Menu;
-import com.actionbarsherlock.view.MenuInflater;
-import com.actionbarsherlock.view.MenuItem;
-
-import de.luhmer.owncloudnewsreader.Constants;
-import de.luhmer.owncloudnewsreader.NewsReaderDetailFragment;
-import de.luhmer.owncloudnewsreader.NewsReaderListActivity;
-import de.luhmer.owncloudnewsreader.R;
-import de.luhmer.owncloudnewsreader.VersionInfoDialogFragment;
-import de.luhmer.owncloudnewsreader.database.DatabaseConnection;
-import de.luhmer.owncloudnewsreader.reader.IReader;
-import de.luhmer.owncloudnewsreader.reader.OnAsyncTaskCompletedListener;
-import de.luhmer.owncloudnewsreader.reader.owncloud.API;
-import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloud_Reader;
-
-public class MenuUtilsSherlockFragmentActivity extends SherlockFragmentActivity {
-
- protected static final String TAG = "MenuUtils";
-
- static FragmentActivity activity;
-
- static MenuItem menuItemSettings;
- static MenuItem menuItemLogin;
- static MenuItem menuItemStartImageCaching;
-
-
- private static MenuItem menuItemUpdater;
- private static MenuItem menuItemDownloadMoreItems;
-
- static IReader _Reader;
-
- /**
- * @return the menuItemUpdater
- */
- public static MenuItem getMenuItemUpdater() {
- return menuItemUpdater;
- }
-
-
- /**
- * @return the menuItemDownloadMoreItems
- */
- public static MenuItem getMenuItemDownloadMoreItems() {
- return menuItemDownloadMoreItems;
- }
-
-
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- @Override
- protected void onResume() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- invalidateOptionsMenu();
- }
- super.onResume();
- }
-
-
- public static void onCreateOptionsMenu(Menu menu, MenuInflater inflater, FragmentActivity act) {
- inflater.inflate(R.menu.news_reader, menu);
- activity = act;
-
- menuItemSettings = menu.findItem(R.id.action_settings);
- menuItemLogin = menu.findItem(R.id.action_login);
- menuItemStartImageCaching = menu.findItem(R.id.menu_StartImageCaching);
-
- menuItemUpdater = menu.findItem(R.id.menu_update);
- //menuItemMarkAllAsRead = menu.findItem(R.id.menu_markAllAsRead);
- menuItemDownloadMoreItems = menu.findItem(R.id.menu_downloadMoreItems);
-
-
- //menuItemMarkAllAsRead.setEnabled(false);
- menuItemDownloadMoreItems.setEnabled(false);
-
- NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame));
- if(ndf != null)
- ndf.UpdateMenuItemsState();
- }
-
- public static boolean onOptionsItemSelected(MenuItem item, FragmentActivity activity) {
- switch (item.getItemId()) {
- case R.id.menu_About_Changelog:
- SherlockDialogFragment dialog = new VersionInfoDialogFragment();
- dialog.show(activity.getSupportFragmentManager(), "VersionChangelogDialogFragment");
- return true;
-
- case R.id.menu_markAllAsRead:
- NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame));
- if(ndf != null)
- {
- /*
- for(int i = 0; i < ndf.getListView().getChildCount(); i++)
- {
- View view = ndf.getListView().getChildAt(i);
- CheckBox cb = (CheckBox) view.findViewById(R.id.cb_lv_item_read);
- if(!cb.isChecked())
- cb.setChecked(true);
- }
- */
-
- DatabaseConnection dbConn = new DatabaseConnection(activity);
- try {
- /*
- //dbConn.markAllItemsAsRead(ndf.getDatabaseIdsOfItems());
- List<Integer> items = new ArrayList<Integer>();
-
-
- Cursor cursor = ncla.getLvAdapter().getCursor();
- cursor.moveToFirst();
- do {
- items.add(Integer.parseInt(cursor.getString(0)));
- } while (cursor.moveToNext());
- dbConn.markAllItemsAsRead(items);
- */
- dbConn.markAllItemsAsReadForCurrentView();
- } finally {
- dbConn.closeDatabase();
- }
- ndf.UpdateCursor();
-
- //If tablet view is enabled update the listview as well
- if(activity instanceof NewsReaderListActivity)
- ((NewsReaderListActivity) activity).updateAdapter();
-
- }
- return true;
-
- case R.id.menu_downloadMoreItems:
- DownloadMoreItems();
- return true;
- }
- return false;
- }
-
- private static void DownloadMoreItems()
- {
- /*
- DatabaseConnection dbConn = new DatabaseConnection(activity);
- int count = dbConn.getCountFeedsForFolder(SubscriptionExpandableListAdapter.ALL_ITEMS, false);
- if(count >= Constants.maxItemsCount)
- {
- String text = activity.getString(R.string.max_items_count_reached);
- text = text.replace("XX", "" + Constants.maxItemsCount);
- new AlertDialog.Builder(activity)
- .setTitle(activity.getString(R.string.empty_view_header))
- .setMessage(text)
- .setPositiveButton(activity.getString(android.R.string.ok), new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog,int id) {
-
- }
- })
- .create()
- .show();
- //Toast.makeText(activity, text, Toast.LENGTH_LONG).show();
- }
- else
- {*/
- String username = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()).getString("edt_username", "");
- String password = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()).getString("edt_password", "");
-
- if(username != null) {
- _Reader = new OwnCloud_Reader();
- ((OwnCloud_Reader)_Reader).Start_AsyncTask_GetVersion(Constants.TaskID_GetVersion, activity, onAsyncTaskGetVersionFinished, username, password);
-
- Toast.makeText(activity, activity.getString(R.string.toast_GettingMoreItems), Toast.LENGTH_SHORT).show();
- }
- //}
- }
-
- static OnAsyncTaskCompletedListener onAsyncTaskGetVersionFinished = new OnAsyncTaskCompletedListener() {
-
- @Override
- public void onAsyncTaskCompleted(int task_id, Object task_result) {
- if(_Reader != null) {
- String appVersion = task_result.toString();
- API api = API.GetRightApiForVersion(appVersion, activity);
- ((OwnCloud_Reader) _Reader).setApi(api);
-
- NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame));
- _Reader.Start_AsyncTask_GetOldItems(Constants.TaskID_GetItems, activity, onAsyncTaskComplete, ndf.getIdFeed(), ndf.getIdFolder());
- }
- }
- };
-
- static OnAsyncTaskCompletedListener onAsyncTaskComplete = new OnAsyncTaskCompletedListener() {
- @Override
- public void onAsyncTaskCompleted(int task_id, Object task_result) {
- NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame));
- if(ndf != null)
- ndf.UpdateCursor();
-
- Log.d(TAG, "Finished Download extra items..");
- }
- };
-} \ No newline at end of file
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/SizeAnimator.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/SizeAnimator.java
new file mode 100644
index 00000000..5db6f4b3
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/SizeAnimator.java
@@ -0,0 +1,40 @@
+package de.luhmer.owncloudnewsreader.helper;
+
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+/**
+ * Created by David on 30.06.2014.
+ */
+public class SizeAnimator {
+
+ public SizeAnimator(View view, float mWidth, float mHeight, float oldWidth, float oldHeight, int duration) {
+ this.viewToSizeAnimate = view;
+ this.mWidth = mWidth;
+ this.mHeight = mHeight;
+ this.mOldHeight = oldHeight;
+ this.mOldWidth = oldWidth;
+
+ sizeAnimator.setDuration(duration);
+ }
+
+ View viewToSizeAnimate;
+ float mWidth;
+ float mHeight;
+ float mOldWidth;
+ float mOldHeight;
+
+
+
+ public Animation sizeAnimator = new Animation() {
+
+ @Override
+ protected void applyTransformation(float interpolatedTime, Transformation t) {
+ viewToSizeAnimate.getLayoutParams().width = (int)(mOldWidth + ((mWidth - mOldWidth) * interpolatedTime));
+ viewToSizeAnimate.getLayoutParams().height = (int) (mOldHeight + ((mHeight - mOldHeight) * interpolatedTime));
+ viewToSizeAnimate.setLayoutParams(viewToSizeAnimate.getLayoutParams());
+ }
+ };
+
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/AudioPodcastItem.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/AudioPodcastItem.java
deleted file mode 100644
index 7b796faa..00000000
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/AudioPodcastItem.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package de.luhmer.owncloudnewsreader.model;
-
-/**
- * Created by David on 21.06.2014.
- */
-public class AudioPodcastItem {
-
- public String itemId;
- public String title;
- public String link;
- public String mimeType;
-}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastItem.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastItem.java
new file mode 100644
index 00000000..544b91c2
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastItem.java
@@ -0,0 +1,32 @@
+package de.luhmer.owncloudnewsreader.model;
+
+import java.io.Serializable;
+
+/**
+ * Created by David on 21.06.2014.
+ */
+public class PodcastItem implements Serializable {
+
+ public PodcastItem() {
+
+ }
+
+ public PodcastItem(String itemId, String title, String link, String mimeType, boolean offlineCached) {
+ this.itemId = itemId;
+ this.title = title;
+ this.link = link;
+ this.mimeType = mimeType;
+ this.offlineCached = offlineCached;
+ }
+
+ public String itemId;
+ public String title;
+ public String link;
+ public String mimeType;
+ public boolean offlineCached;
+
+ public Integer downloadProgress;
+
+ public static Integer DOWNLOAD_COMPLETED = -1;
+ public static Integer DOWNLOAD_NOT_STARTED = -2;
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/DownloadItemsToCache.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/DownloadItemsToCache.java
index 2540a887..eb3c2c32 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/DownloadItemsToCache.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/DownloadItemsToCache.java
@@ -28,8 +28,8 @@ import android.util.SparseArray;
import de.luhmer.owncloudnewsreader.async_tasks.GetImageAsyncTask;
import de.luhmer.owncloudnewsreader.helper.BitmapDrawableLruCache;
+import de.luhmer.owncloudnewsreader.helper.FileUtils;
import de.luhmer.owncloudnewsreader.helper.ImageDownloadFinished;
-import de.luhmer.owncloudnewsreader.helper.ImageHandler;
public class DownloadItemsToCache {
SparseArray<String> URLs;
@@ -47,7 +47,7 @@ public class DownloadItemsToCache {
key = URLs.keyAt(URLs.size() -1) + 1;
URLs.append(key, URL_TO_IMAGE);
- GetImageAsyncTask getImageAsync = new GetImageAsyncTask(URL_TO_IMAGE, imgDownloadFinished, key, ImageHandler.getPathImageCache(context), context, null);
+ GetImageAsyncTask getImageAsync = new GetImageAsyncTask(URL_TO_IMAGE, imgDownloadFinished, key, FileUtils.getPathImageCache(context), context, null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
getImageAsync.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ((Void) null));// Execute in parallel
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertItemIntoDatabase.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertItemIntoDatabase.java
index dbc7132b..2eb03b94 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertItemIntoDatabase.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertItemIntoDatabase.java
@@ -55,18 +55,29 @@ public class InsertItemIntoDatabase implements IHandleJsonObject {
content = content.replaceAll("<img[^>]*auslieferung.commindo-media-ressourcen.de.*>", "");
content = content.replaceAll("<img[^>]*rss.buysellads.com.*>", "");
+ String url = e.optString("url");
+ String guid = e.optString("guid");
+ String enclosureLink = e.optString("enclosureLink");
+ String enclosureMime = e.optString("enclosureMime");
+
+ if(enclosureLink.isEmpty() && guid.startsWith("http://gdata.youtube.com/feeds/api/")) {
+ enclosureLink = url;
+ enclosureMime = "youtube";
+ }
+
+
return new RssFile(0, e.optString("id"),
e.optString("title"),
- e.optString("url"), content,
+ url, content,
!e.optBoolean("unread"), null,
e.optString("feedId"), null,
date, e.optBoolean("starred"),
- e.optString("guid"),
+ guid,
e.optString("guidHash"),
e.optString("lastModified"),
e.optString("author"),
- e.optString("enclosureLink"),
- e.optString("enclosureMime"));
+ enclosureLink,
+ enclosureMime);
}
@Override
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/AudioPodcastService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/AudioPodcastService.java
deleted file mode 100644
index 9fe56b8a..00000000
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/AudioPodcastService.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package de.luhmer.owncloudnewsreader.services;
-
-import android.app.Service;
-import android.content.Intent;
-import android.media.MediaPlayer;
-import android.os.Handler;
-import android.os.IBinder;
-
-import java.io.IOException;
-
-import de.greenrobot.event.EventBus;
-import de.luhmer.owncloudnewsreader.events.podcast.OpenAudioPodcastEvent;
-import de.luhmer.owncloudnewsreader.events.podcast.TogglePlayerStateEvent;
-import de.luhmer.owncloudnewsreader.events.podcast.UpdatePodcastStatusEvent;
-import de.luhmer.owncloudnewsreader.events.podcast.WindPodcast;
-import de.luhmer.owncloudnewsreader.view.PodcastNotification;
-
-public class AudioPodcastService extends Service {
-
- PodcastNotification podcastNotification;
-
- @Override
- public void onCreate() {
- podcastNotification = new PodcastNotification(this);
-
- super.onCreate();
- }
-
- public AudioPodcastService() {
- mediaPlayer = new MediaPlayer();
- mHandler = new Handler();
- eventBus = EventBus.getDefault();
-
- eventBus.register(this);
-
- mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(MediaPlayer mediaPlayer) {
- mHandler.removeCallbacks(mUpdateTimeTask);
- }
- });
-
-
- //openFile("/sdcard/Music/#Musik/Finest Tunes/Netsky - Running Low (Ft. Beth Ditto).mp3");
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- // TODO: Return the communication channel to the service.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
-
- private EventBus eventBus;
- private Handler mHandler;
- private MediaPlayer mediaPlayer;
- private String mediaTitle;
-
- public static final int delay = 500; //In milliseconds
-
- private boolean isPreparing = false;
-
- public void openFile(String pathToFile, String mediaTitle) {
- try {
- this.mediaTitle = mediaTitle;
-
- if(mediaPlayer.isPlaying())
- pause();
-
- isPreparing = true;
- mHandler.postDelayed(mUpdateTimeTask, 0);
-
- mediaPlayer.reset();
- mediaPlayer.setDataSource(pathToFile);
- mediaPlayer.prepareAsync();
-
- mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
- @Override
- public void onPrepared(MediaPlayer mediaPlayer) {
- play();
- isPreparing = false;
- }
- });
-
- mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(MediaPlayer mediaPlayer) {
- pause();//Send the over signal
- }
- });
-
- } catch (IOException e) {
- e.printStackTrace();
- isPreparing = false;
- }
- }
-
- /**
- * Background Runnable thread
- * */
- private Runnable mUpdateTimeTask = new Runnable() {
- public void run() {
- sendMediaStatus();
-
- mHandler.postDelayed(this, delay);
- }
- };
-
- public void onEvent(TogglePlayerStateEvent event) {
- if(mediaPlayer.isPlaying()) {
- pause();
- } else {
- play();
- }
- }
-
- public void onEvent(WindPodcast event) {
- if(mediaPlayer != null) {
- double totalDuration = mediaPlayer.getDuration();
- int position = (int)((totalDuration / 100d) * event.toPositionInPercent);
- mediaPlayer.seekTo(position);
- }
- }
-
- public void onEventBackgroundThread(OpenAudioPodcastEvent event) {
- openFile(event.pathToFile, event.mediaTitle);
- }
-
-
-
-
- public void play() {
- mediaPlayer.start();
-
- mHandler.removeCallbacks(mUpdateTimeTask);
- mHandler.postDelayed(mUpdateTimeTask, 0);
- }
-
- public void pause() {
- mediaPlayer.pause();
- mHandler.removeCallbacks(mUpdateTimeTask);
-
- sendMediaStatus();
- }
-
- public void sendMediaStatus() {
- long totalDuration = 0;
- long currentDuration = 0;
- if(!isPreparing) {
- totalDuration = mediaPlayer.getDuration();
- currentDuration = mediaPlayer.getCurrentPosition();
- }
-
- /*
- // Displaying Total Duration time
- songTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDuration));
- // Displaying time completed playing
- songCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(currentDuration));
-
- // Updating progress bar
- int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration));
- //Log.d("Progress", ""+progress);
- songProgressBar.setProgress(progress);
- */
-
- UpdatePodcastStatusEvent audioPodcastEvent = new UpdatePodcastStatusEvent(currentDuration, totalDuration, mediaPlayer.isPlaying(), mediaTitle, isPreparing);
- eventBus.post(audioPodcastEvent);
- }
-
-}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java
index 492cef8d..79100813 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java
@@ -49,6 +49,7 @@ import de.luhmer.owncloudnewsreader.async_tasks.GetImageAsyncTask;
import de.luhmer.owncloudnewsreader.database.DatabaseConnection;
import de.luhmer.owncloudnewsreader.helper.BitmapDrawableLruCache;
import de.luhmer.owncloudnewsreader.helper.FavIconHandler;
+import de.luhmer.owncloudnewsreader.helper.FileUtils;
import de.luhmer.owncloudnewsreader.helper.ImageDownloadFinished;
import de.luhmer.owncloudnewsreader.helper.ImageHandler;
@@ -144,7 +145,7 @@ public class DownloadImagesService extends IntentService {
notificationManager.notify(NOTIFICATION_ID, notify);
for (String link : links)
- new GetImageAsyncTask(link, imgDownloadFinished, 999, ImageHandler.getPathImageCache(this), this, null).execute();
+ new GetImageAsyncTask(link, imgDownloadFinished, 999, FileUtils.getPathImageCache(this), this, null).execute();
}
}
@@ -169,7 +170,7 @@ public class DownloadImagesService extends IntentService {
private void RemoveOldImages(Context context) {
HashMap<File, Long> files;
- long size = ImageHandler.getFolderSize(new File(ImageHandler.getPath(context)));
+ long size = ImageHandler.getFolderSize(new File(FileUtils.getPath(context)));
size = (long) (size / 1024d / 1024d);
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
@@ -177,7 +178,7 @@ public class DownloadImagesService extends IntentService {
if(size > max_allowed_size)
{
files = new HashMap<File, Long>();
- for(File file : ImageHandler.getFilesFromDir(new File(ImageHandler.getPathImageCache(context))))
+ for(File file : ImageHandler.getFilesFromDir(new File(FileUtils.getPathImageCache(context))))
{
files.put(file, file.lastModified());
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastDownloadService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastDownloadService.java
new file mode 100644
index 00000000..0a88c77c
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastDownloadService.java
@@ -0,0 +1,240 @@
+package de.luhmer.owncloudnewsreader.services;
+
+import android.annotation.TargetApi;
+import android.app.DownloadManager;
+import android.app.IntentService;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.ResultReceiver;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.MessageDigest;
+
+import de.greenrobot.event.EventBus;
+import de.luhmer.owncloudnewsreader.helper.FileUtils;
+import de.luhmer.owncloudnewsreader.helper.JavaYoutubeDownloader;
+import de.luhmer.owncloudnewsreader.model.PodcastItem;
+
+/**
+ * An {@link IntentService} subclass for handling asynchronous task requests in
+ * a service on a separate handler thread.
+ * <p>
+ * TODO: Customize class - update intent actions, extra parameters and static
+ * helper methods.
+ */
+public class PodcastDownloadService extends IntentService {
+ // TODO: Rename actions, choose action names that describe tasks that this
+ // IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
+ private static final String ACTION_DOWNLOAD = "de.luhmer.owncloudnewsreader.services.action.DOWNLOAD";
+
+
+
+ // TODO: Rename parameters
+ private static final String EXTRA_RECEIVER = "de.luhmer.owncloudnewsreader.services.extra.RECEIVER";
+ private static final String EXTRA_URL = "de.luhmer.owncloudnewsreader.services.extra.URL";
+ private static final String EXTRA_PARAM2 = "de.luhmer.owncloudnewsreader.services.extra.PARAM2";
+ private static final String TAG = "PodcastDownloadService";
+
+ private EventBus eventBus;
+
+ /**
+ * Starts this service to perform action Foo with the given parameters. If
+ * the service is already performing a task this action will be queued.
+ *
+ * @see IntentService
+ */
+ // TODO: Customize helper method
+ public static void startPodcastDownload(Context context, PodcastItem podcastItem/*, ResultReceiver receiver*/) {
+ Intent intent = new Intent(context, PodcastDownloadService.class);
+ intent.setAction(ACTION_DOWNLOAD);
+ intent.putExtra(EXTRA_URL, podcastItem);
+ //intent.putExtra(EXTRA_RECEIVER, receiver);
+ //intent.putExtra(EXTRA_PARAM2, param2);
+ context.startService(intent);
+ }
+
+
+ public PodcastDownloadService() {
+ super("PodcastDownloadService");
+
+ eventBus = EventBus.getDefault();
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+
+ if (intent != null) {
+ final String action = intent.getAction();
+ if (ACTION_DOWNLOAD.equals(action)) {
+ ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra(EXTRA_RECEIVER);
+ PodcastItem podcast = (PodcastItem) intent.getSerializableExtra(EXTRA_URL);
+ //final String param2 = intent.getStringExtra(EXTRA_PARAM2);
+ //handleActionDownload(podcast);
+
+ downloadPodcast(podcast, this);
+
+
+ }/* else if (ACTION_BAZ.equals(action)) {
+ final String param1 = intent.getStringExtra(EXTRA_PARAM1);
+ final String param2 = intent.getStringExtra(EXTRA_PARAM2);
+ handleActionBaz(param1, param2);
+ }*/
+ }
+ }
+
+ /**
+ * Handle action Foo in the provided background thread with the provided
+ * parameters.
+ */
+ @TargetApi(Build.VERSION_CODES.GINGERBREAD)
+ private void handleActionDownload(PodcastItem podcast) {
+ Uri uri = Uri.parse(podcast.link);
+ DownloadManager.Request request = new DownloadManager.Request(uri);
+ request.setDescription(podcast.mimeType);
+ request.setTitle(podcast.title);
+
+ // in order for this if to run, you must use the android 3.2 to compile your app
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ request.allowScanningByMediaScanner();
+ request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+ }
+
+ String path = "file://" + getUrlToPodcastFile(this, podcast.link, true);
+ request.setDestinationUri(Uri.parse(path));
+ //request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "bla.txt");
+
+ // get download service and enqueue file
+ DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
+ manager.enqueue(request);
+ }
+
+
+ public static String getUrlToPodcastFile(Context context, String WEB_URL_TO_FILE, boolean createDir) {
+ if(WEB_URL_TO_FILE.contains(JavaYoutubeDownloader.host))
+ return getUrlToYoutubePodcastFile(context, WEB_URL_TO_FILE, createDir);
+
+ File file = new File(WEB_URL_TO_FILE);
+
+ String path = FileUtils.getPathPodcasts(context) + "/" + getHashOfString(WEB_URL_TO_FILE) + "/";
+ if(createDir)
+ new File(path).mkdirs();
+
+ return path + file.getName();
+ }
+
+ private static String getUrlToYoutubePodcastFile(Context context, String WEB_URL_TO_FILE, boolean createDir) {
+ String path = FileUtils.getPathPodcasts(context) + "/" + getHashOfString(WEB_URL_TO_FILE) + "/";
+ if(createDir)
+ new File(path).mkdirs();
+
+ return path + "video.mp4";
+ }
+
+
+ public static String getHashOfString(String WEB_URL_TO_FILE)
+ {
+ try {
+ MessageDigest m = MessageDigest.getInstance("MD5");
+ m.reset();
+ m.update(WEB_URL_TO_FILE.trim().getBytes());
+ byte[] digest = m.digest();
+ BigInteger bigInt = new BigInteger(1,digest);
+ String hashtext = bigInt.toString(16);
+
+ return hashtext;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return WEB_URL_TO_FILE;
+ }
+
+
+ private void downloadPodcast(PodcastItem podcast, Context context) {
+ try {
+ String urlTemp = podcast.link;
+ String path = getUrlToPodcastFile(this, urlTemp, true);
+
+ if(podcast.link.contains(JavaYoutubeDownloader.host)) {
+
+ path = getUrlToPodcastFile(context, urlTemp, true);
+
+ try {
+ urlTemp = new JavaYoutubeDownloader().getDownloadUrl(podcast.link, context);
+ } catch (Throwable throwable) {
+ throwable.printStackTrace();
+ }
+
+ }
+ URL url = new URL(urlTemp);
+ URLConnection connection = url.openConnection();
+ connection.connect();
+ connection.setConnectTimeout(10000);
+ connection.setReadTimeout(120000);//2min
+ // this will be useful so that you can show a typical 0-100% progress bar
+ int fileLength = connection.getContentLength();
+
+ // download the file
+ InputStream input = new BufferedInputStream(url.openStream());
+
+
+ String pathCache = path + ".download";
+ OutputStream output = new FileOutputStream(pathCache);
+
+
+ byte data[] = new byte[1024];
+ long total = 0;
+ int count;
+ while ((count = input.read(data)) != -1) {
+ total += count;
+
+ int progress = (int) (total * 100 / fileLength);
+ podcast.downloadProgress = progress;
+ eventBus.post(new DownloadProgressUpdate(podcast));
+
+ output.write(data, 0, count);
+ }
+
+ output.flush();
+ output.close();
+ input.close();
+
+
+ new File(pathCache).renameTo(new File(path));
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+
+ podcast.downloadProgress = 100;
+ eventBus.post(new DownloadProgressUpdate(podcast));
+
+ /*
+ Bundle resultData = new Bundle();
+ resultData.putInt("progress" ,100);
+ receiver.send(UPDATE_PROGRESS, resultData);
+ */
+ }
+
+ public static final int UPDATE_PROGRESS = 5555;
+
+
+ public class DownloadProgressUpdate {
+
+ public DownloadProgressUpdate(PodcastItem podcast) {
+ this.podcast = podcast;
+ }
+
+ public PodcastItem podcast;
+ }
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java
new file mode 100644
index 00000000..61c935ff
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java
@@ -0,0 +1,298 @@
+package de.luhmer.owncloudnewsreader.services;
+
+import android.app.Service;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.View;
+
+import java.io.IOException;
+
+import de.greenrobot.event.EventBus;
+import de.luhmer.owncloudnewsreader.R;
+import de.luhmer.owncloudnewsreader.events.podcast.NewPodcastPlaybackListener;
+import de.luhmer.owncloudnewsreader.events.podcast.OpenPodcastEvent;
+import de.luhmer.owncloudnewsreader.events.podcast.RegisterVideoOutput;
+import de.luhmer.owncloudnewsreader.events.podcast.TogglePlayerStateEvent;
+import de.luhmer.owncloudnewsreader.events.podcast.UpdatePodcastStatusEvent;
+import de.luhmer.owncloudnewsreader.events.podcast.WindPodcast;
+import de.luhmer.owncloudnewsreader.view.PodcastNotification;
+
+public class PodcastPlaybackService extends Service {
+
+ private static final String TAG = "PodcastPlaybackService";
+ PodcastNotification podcastNotification;
+
+ @Override
+ public void onCreate() {
+ podcastNotification = new PodcastNotification(this);
+
+ mediaTitle = getString(R.string.no_podcast_selected);
+
+ super.onCreate();
+ }
+
+ public PodcastPlaybackService() {
+ mMediaPlayer = new MediaPlayer();
+ mHandler = new Handler();
+ eventBus = EventBus.getDefault();
+
+ eventBus.register(this);
+
+ mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mediaPlayer) {
+ play();
+ isPreparing = false;
+ canCallGetDuration = true;
+ }
+ });
+
+ mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mediaPlayer) {
+ pause();//Send the over signal
+ }
+ });
+
+
+ eventBus.post(new PodcastPlaybackServiceStarted());
+
+ mHandler.postDelayed(mUpdateTimeTask, 0);
+
+ //openFile("/sdcard/Music/#Musik/Finest Tunes/Netsky - Running Low (Ft. Beth Ditto).mp3");
+ }
+
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ return Service.START_STICKY;
+ //return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ //throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+
+ private EventBus eventBus;
+ private Handler mHandler;
+ private MediaPlayer mMediaPlayer;
+ private String mediaTitle;
+ View parentResizableView;
+
+ public static final int delay = 500; //In milliseconds
+
+ private boolean canCallGetDuration = false;//Otherwise the player would call getDuration all the time without loading a media file
+ private boolean isPreparing = false;
+ private boolean isVideoFile = false;
+
+ public void openFile(String pathToFile, String mediaTitle) {
+ try {
+ if(mMediaPlayer.isPlaying())
+ pause();
+
+ this.mediaTitle = mediaTitle;
+
+ isPreparing = true;
+ mHandler.postDelayed(mUpdateTimeTask, 0);
+
+ mMediaPlayer.reset();
+ mMediaPlayer.setDataSource(pathToFile);
+ mMediaPlayer.prepareAsync();
+ } catch (IOException e) {
+ e.printStackTrace();
+ isPreparing = false;
+ }
+ }
+
+ /**
+ * Background Runnable thread
+ * */
+ private Runnable mUpdateTimeTask = new Runnable() {
+ public void run() {
+ sendMediaStatus();
+
+ mHandler.postDelayed(this, delay);
+ }
+ };
+
+ public void onEvent(TogglePlayerStateEvent event) {
+ if(mMediaPlayer.isPlaying()) {
+ pause();
+ } else {
+ play();
+ }
+ }
+
+ public void onEvent(WindPodcast event) {
+ if(mMediaPlayer != null) {
+ double totalDuration = mMediaPlayer.getDuration();
+ int position = (int)((totalDuration / 100d) * event.toPositionInPercent);
+ mMediaPlayer.seekTo(position);
+ }
+ }
+
+ public void onEventBackgroundThread(OpenPodcastEvent event) {
+ this.isVideoFile = event.isVideoFile;
+ openFile(event.pathToFile, event.mediaTitle);
+ }
+
+ public void onEvent(RegisterVideoOutput videoOutput) {
+ if(mMediaPlayer != null) {
+ if(videoOutput.surfaceView == null) {
+ mMediaPlayer.setDisplay(null);
+ Log.d(TAG, "Disable Screen output!");
+
+ mMediaPlayer.setScreenOnWhilePlaying(false);
+ } else {
+ if(videoOutput.surfaceView.getHolder() != mSurfaceHolder) {
+ parentResizableView = videoOutput.parentResizableView;
+
+ videoOutput.surfaceView.getHolder().addCallback(mSHCallback);
+ //videoOutput.surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
+
+ populateVideo();
+
+ Log.d(TAG, "Enable Screen output!");
+ }
+ }
+ }
+ }
+
+ public void onEvent(NewPodcastPlaybackListener newListener) {
+ sendMediaStatus();
+ }
+
+
+
+
+ public void play() {
+ try {
+ int progress = mMediaPlayer.getCurrentPosition() / mMediaPlayer.getDuration();
+ if (progress >= 1) {
+ mMediaPlayer.seekTo(0);
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ mMediaPlayer.start();
+
+ mHandler.removeCallbacks(mUpdateTimeTask);
+ mHandler.postDelayed(mUpdateTimeTask, 0);
+
+ populateVideo();
+ }
+
+ private void populateVideo() {
+ double videoHeightRel = (double) mSurfaceWidth / (double) mMediaPlayer.getVideoWidth();
+ int videoHeight = (int) (mMediaPlayer.getVideoHeight() * videoHeightRel);
+
+ if (mSurfaceWidth != 0 && videoHeight != 0 && mSurfaceHolder != null) {
+ //mSurfaceHolder.setFixedSize(mSurfaceWidth, videoHeight);
+
+ parentResizableView.getLayoutParams().height = videoHeight;
+ parentResizableView.setLayoutParams(parentResizableView.getLayoutParams());
+ }
+ }
+
+ public void pause() {
+ if(mMediaPlayer.isPlaying())
+ mMediaPlayer.pause();
+
+ mHandler.removeCallbacks(mUpdateTimeTask);
+ sendMediaStatus();
+ }
+
+ public void sendMediaStatus() {
+ long totalDuration = 0;
+ long currentDuration = 0;
+ if(!isPreparing && canCallGetDuration) {
+ totalDuration = mMediaPlayer.getDuration();
+ currentDuration = mMediaPlayer.getCurrentPosition();
+ }
+
+ /*
+ // Displaying Total Duration time
+ songTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDuration));
+ // Displaying time completed playing
+ songCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(currentDuration));
+
+ // Updating progress bar
+ int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration));
+ //Log.d("Progress", ""+progress);
+ songProgressBar.setProgress(progress);
+ */
+
+ UpdatePodcastStatusEvent audioPodcastEvent = new UpdatePodcastStatusEvent(currentDuration, totalDuration, mMediaPlayer.isPlaying(), mediaTitle, isPreparing, canCallGetDuration, isVideoFile);
+ eventBus.post(audioPodcastEvent);
+ }
+
+
+ public class PodcastPlaybackServiceStarted {
+
+ }
+
+ /*
+ public class VideoAvailableState {
+ public VideoAvailableState(boolean isVideoAvailable) {
+ this.isVideoAvailable = isVideoAvailable;
+ }
+
+ public boolean isVideoAvailable;
+ }
+ */
+
+
+
+ int mSurfaceWidth;
+ int mSurfaceHeight;
+ SurfaceHolder mSurfaceHolder;
+ SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
+ {
+ public void surfaceChanged(SurfaceHolder holder, int format, int surfaceWidth, int surfaceHeight)
+ {
+ mSurfaceWidth = surfaceWidth;
+ mSurfaceHeight = surfaceHeight;
+
+ //populateVideo();
+
+ //Log.d(TAG, "surfaceChanged");
+
+ /*
+ if (!isPreparing && mVideoWidth == w && mVideoHeight == h) {
+ if (mSeekWhenPrepared != 0) {
+ mMediaPlayer.seekTo(mSeekWhenPrepared);
+ }
+ mMediaPlayer.start();
+ if (mMediaController != null) {
+ mMediaController.show();
+ }
+ }
+ */
+ }
+
+ public void surfaceCreated(SurfaceHolder holder)
+ {
+ mSurfaceHolder = holder;
+ mMediaPlayer.setDisplay(mSurfaceHolder);
+
+ mMediaPlayer.setScreenOnWhilePlaying(true);
+
+ Log.d(TAG, "surfaceCreated");
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder)
+ {
+ Log.d(TAG, "surfaceDestroyed");
+ }
+ };
+
+
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/OnPinchListener.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/OnPinchListener.java
new file mode 100644
index 00000000..03689b95
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/OnPinchListener.java
@@ -0,0 +1,44 @@
+package de.luhmer.owncloudnewsreader.view;
+
+import android.view.ScaleGestureDetector;
+
+/**
+ * Created by David on 30.06.2014.
+ */
+public class OnPinchListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+
+ private float mScaleFactor = 1.f;
+
+ ZoomableRelativeLayout mZoomableRelativeLayout;
+
+ public OnPinchListener(ZoomableRelativeLayout mZoomableRelativeLayout) {
+ this.mZoomableRelativeLayout = mZoomableRelativeLayout;
+ }
+
+ float startingSpan;
+ float endSpan;
+ float startFocusX;
+ float startFocusY;
+
+
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
+ startingSpan = detector.getCurrentSpan();
+ startFocusX = detector.getFocusX();
+ startFocusY = detector.getFocusY();
+ return true;
+ }
+
+
+
+
+ /*
+ public boolean onScale(ScaleGestureDetector detector) {
+ mZoomableRelativeLayout.scale(detector.getCurrentSpan()/startingSpan, startFocusX, startFocusY);
+ return true;
+ }
+ */
+
+ public void onScaleEnd(ScaleGestureDetector detector) {
+ //mZoomableRelativeLayout.restore();
+ }
+} \ No newline at end of file
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastNotification.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastNotification.java
index 116db3d8..a54f3095 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastNotification.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastNotification.java
@@ -54,19 +54,10 @@ public class PodcastNotification {
int lastDrawableId;
- long lastUpdate = 0;
- int seconds = 1;//Time of delay between each update
public void onEvent(UpdatePodcastStatusEvent podcast) {
- /*
- long current = new Date().getTime();
-
- if((lastUpdate + (1000 * seconds)) > current) {
+ if(!podcast.isFileLoaded())
return;
- } else {
- lastUpdate = current;
- }
- */
int drawableId = podcast.isPlaying() ? android.R.drawable.ic_media_pause : android.R.drawable.ic_media_play;
String actionText = podcast.isPlaying() ? "Pause" : "Play";
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastSlidingUpPanelLayout.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastSlidingUpPanelLayout.java
index 06dbb26c..650869c4 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastSlidingUpPanelLayout.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/PodcastSlidingUpPanelLayout.java
@@ -25,9 +25,9 @@ public class PodcastSlidingUpPanelLayout extends SlidingUpPanelLayout{
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- //return super.onInterceptTouchEvent(ev);
+ return super.onInterceptTouchEvent(ev);
- return isDragViewHit((int)ev.getX(), (int)ev.getY());
+ //return isDragViewHit((int)ev.getX(), (int)ev.getY());
}
private View mDragView;
@@ -46,8 +46,10 @@ public class PodcastSlidingUpPanelLayout extends SlidingUpPanelLayout{
private boolean isDragViewHit(int x, int y) {
+
+
//original implementation - only allow dragging on mDragView
- View v = isExpanded() ? mDragView : mSlideableView;
+ View v = isPanelExpanded() ? mDragView : mSlideableView;
if (v == null) return false;
int[] viewLocation = new int[2];
v.getLocationOnScreen(viewLocation);
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/ZoomableRelativeLayout.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/ZoomableRelativeLayout.java
new file mode 100644
index 00000000..fdb7958a
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/view/ZoomableRelativeLayout.java
@@ -0,0 +1,242 @@
+package de.luhmer.owncloudnewsreader.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.widget.RelativeLayout;
+
+import de.greenrobot.event.EventBus;
+import de.luhmer.owncloudnewsreader.events.podcast.VideoDoubleClicked;
+
+/**
+ * Created by David on 30.06.2014.
+ */
+//http://stackoverflow.com/questions/10013906/android-zoom-in-out-relativelayout-with-spread-pinch
+public class ZoomableRelativeLayout extends RelativeLayout {
+ private static final int INVALID_POINTER_ID = -1;
+ private static final int INVALID_SIZE = -1;
+
+
+ public boolean disableScale = false;
+ public void setDisableScale(boolean disableScale) {
+ this.disableScale = disableScale;
+ }
+
+ private static final String TAG = "ZoomableRelativeLayout";
+
+ private GestureDetector mDoubleTapDetector;
+ private ScaleGestureDetector mScaleDetector;
+ float mScaleFactor = 1;
+ public float getScaleFactor() {
+ return mScaleFactor;
+ }
+
+ float mPosX;
+ float mPosY;
+ private float mLastTouchX;
+ private float mLastTouchY;
+ private int mActivePointerId;
+
+ private float mInitHeight = INVALID_SIZE;
+ private float mInitWidth = INVALID_SIZE;
+
+ public ZoomableRelativeLayout(Context context) {
+ super(context);
+ initZoomView(context);
+ }
+
+ public ZoomableRelativeLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initZoomView(context);
+ }
+
+ public ZoomableRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initZoomView(context);
+ }
+
+
+ boolean mPositionReady = false;
+ public boolean isPositionReady() {
+ return mPositionReady;
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ if(hasWindowFocus) {
+ readVideoPosition();
+ mPositionReady = true;
+ }
+ super.onWindowFocusChanged(hasWindowFocus);
+ }
+
+
+
+ public void readVideoPosition() {
+ int position[] = new int[2];
+ getLocationOnScreen(position);
+ mVideoXPosition = position[0];
+ mVideoYPosition = position[1];
+
+ Log.d(TAG, "Grabbing new Video Wrapper Position. X:" + mVideoXPosition + " - Y:" + mVideoYPosition);
+
+ //mVideoXPosition = getX();
+ //mVideoYPosition = getY();
+ }
+
+ private void initZoomView(Context context) {
+ // Create our ScaleGestureDetector
+ mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
+ mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener());
+ }
+
+ /*
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ canvas.scale(mScaleFactor, mScaleFactor, mPosX, mPosY);
+ super.dispatchDraw(canvas);
+ canvas.restore();
+ }*/
+
+ private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener {
+
+ // event when double tap occurs
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ float x = e.getX();
+ float y = e.getY();
+
+ Log.d("Double Tap", "Tapped at: (" + x + "," + y + ")");
+
+ EventBus.getDefault().post(new VideoDoubleClicked());
+
+ return true;
+ }
+ }
+
+
+ private float mVideoXPosition;
+ private float mVideoYPosition;
+ public float getVideoXPosition() {return mVideoXPosition;}
+ public float getVideoYPosition() {return mVideoYPosition;}
+
+ private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+ @Override
+ public void onScaleEnd(ScaleGestureDetector detector) {
+ if(!disableScale) {
+ readVideoPosition();
+ }
+
+ super.onScaleEnd(detector);
+ }
+
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ if(disableScale)
+ return true;
+
+ if(mInitWidth == INVALID_SIZE) {
+ mInitWidth = getWidth();
+ mInitHeight = getHeight();
+ }
+
+ mScaleFactor *= detector.getScaleFactor();
+
+ // Don't let the object get too small or too large.
+ mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
+
+ Log.d(TAG, "Scale:" + mScaleFactor);
+
+
+ getLayoutParams().width = (int)(mInitWidth * mScaleFactor);
+ getLayoutParams().height = (int)(mInitHeight * mScaleFactor);
+ setLayoutParams(getLayoutParams());
+
+ //invalidate();
+ return true;
+ }
+ }
+
+
+ /*
+ public void restore() {
+ mScaleFactor = 1;
+ this.invalidate();
+ }*/
+
+
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ // Let the ScaleGestureDetector inspect all events.
+ mScaleDetector.onTouchEvent(ev);
+ mDoubleTapDetector.onTouchEvent(ev);
+
+ final int action = ev.getAction();
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ final float x = ev.getX();
+ final float y = ev.getY();
+
+ mLastTouchX = x;
+ mLastTouchY = y;
+ mActivePointerId = ev.getPointerId(0);
+ break;
+ }
+
+ case MotionEvent.ACTION_MOVE: {
+ final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+ final float x = ev.getX(pointerIndex);
+ final float y = ev.getY(pointerIndex);
+
+ // Only move if the ScaleGestureDetector isn't processing a gesture.
+ if (!mScaleDetector.isInProgress()) {
+ final float dx = x - mLastTouchX;
+ final float dy = y - mLastTouchY;
+
+ mPosX += dx;
+ mPosY += dy;
+
+ invalidate();
+ }
+
+ mLastTouchX = x;
+ mLastTouchY = y;
+
+ break;
+ }
+
+ case MotionEvent.ACTION_UP: {
+ mActivePointerId = INVALID_POINTER_ID;
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL: {
+ mActivePointerId = INVALID_POINTER_ID;
+ break;
+ }
+
+ case MotionEvent.ACTION_POINTER_UP: {
+ final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
+ >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ final int pointerId = ev.getPointerId(pointerIndex);
+ if (pointerId == mActivePointerId) {
+ // This was our active pointer going up. Choose a new
+ // active pointer and adjust accordingly.
+ final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+ mLastTouchX = ev.getX(newPointerIndex);
+ mLastTouchY = ev.getY(newPointerIndex);
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ }
+ break;
+ }
+ }
+
+ return true;
+ }
+
+} \ No newline at end of file