Initial Commit
This commit is contained in:
commit
c9283f09dc
|
@ -0,0 +1,19 @@
|
||||||
|
# built application files
|
||||||
|
*.apk
|
||||||
|
*.ap_
|
||||||
|
|
||||||
|
# files for the dex VM
|
||||||
|
*.dex
|
||||||
|
|
||||||
|
# Java class files
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# generated files
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
*~
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="de.podfetcher"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0" >
|
||||||
|
|
||||||
|
<!-- <uses-permission android:name="android.permission.ACCESS_ALL_DOWNLOADS" /> -->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
|
<uses-sdk android:minSdkVersion="10" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/app_name" >
|
||||||
|
<activity
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:name=".PodfetcherActivity" >
|
||||||
|
<intent-filter >
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project name="Podfetcher" default="help">
|
||||||
|
|
||||||
|
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||||
|
It contains the path to the SDK. It should *NOT* be checked into
|
||||||
|
Version Control Systems. -->
|
||||||
|
<property file="local.properties" />
|
||||||
|
|
||||||
|
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||||
|
'android' tool to add properties to it.
|
||||||
|
This is the place to change some Ant specific build properties.
|
||||||
|
Here are some properties you may want to change/update:
|
||||||
|
|
||||||
|
source.dir
|
||||||
|
The name of the source directory. Default is 'src'.
|
||||||
|
out.dir
|
||||||
|
The name of the output directory. Default is 'bin'.
|
||||||
|
|
||||||
|
For other overridable properties, look at the beginning of the rules
|
||||||
|
files in the SDK, at tools/ant/build.xml
|
||||||
|
|
||||||
|
Properties related to the SDK location or the project target should
|
||||||
|
be updated using the 'android' tool with the 'update' action.
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<property file="ant.properties" />
|
||||||
|
|
||||||
|
<!-- The project.properties file is created and updated by the 'android'
|
||||||
|
tool, as well as ADT.
|
||||||
|
|
||||||
|
This contains project specific properties such as project target, and library
|
||||||
|
dependencies. Lower level build properties are stored in ant.properties
|
||||||
|
(or in .classpath for Eclipse projects).
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems. -->
|
||||||
|
<loadproperties srcFile="project.properties" />
|
||||||
|
|
||||||
|
<!-- quick check on sdk.dir -->
|
||||||
|
<fail
|
||||||
|
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||||
|
unless="sdk.dir"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||||
|
in between standard targets -->
|
||||||
|
<!--
|
||||||
|
<target name="-pre-build">
|
||||||
|
</target>
|
||||||
|
<target name="-pre-compile">
|
||||||
|
</target>
|
||||||
|
|
||||||
|
/* This is typically used for code obfuscation.
|
||||||
|
Compiled code location: ${out.classes.absolute.dir}
|
||||||
|
If this is not done in place, override ${out.dex.input.absolute.dir} */
|
||||||
|
<target name="-post-compile">
|
||||||
|
</target>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Import the actual build file.
|
||||||
|
|
||||||
|
To customize existing targets, there are two options:
|
||||||
|
- Customize only one target:
|
||||||
|
- copy/paste the target into this file, *before* the
|
||||||
|
<import> task.
|
||||||
|
- customize it to your needs.
|
||||||
|
- Customize the whole content of build.xml
|
||||||
|
- copy/paste the content of the rules files (minus the top node)
|
||||||
|
into this file, replacing the <import> task.
|
||||||
|
- customize to your needs.
|
||||||
|
|
||||||
|
***********************
|
||||||
|
****** IMPORTANT ******
|
||||||
|
***********************
|
||||||
|
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||||
|
in order to avoid having your file be overridden by tools such as "android update project"
|
||||||
|
-->
|
||||||
|
<!-- version-tag: 1 -->
|
||||||
|
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,40 @@
|
||||||
|
-optimizationpasses 5
|
||||||
|
-dontusemixedcaseclassnames
|
||||||
|
-dontskipnonpubliclibraryclasses
|
||||||
|
-dontpreverify
|
||||||
|
-verbose
|
||||||
|
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||||
|
|
||||||
|
-keep public class * extends android.app.Activity
|
||||||
|
-keep public class * extends android.app.Application
|
||||||
|
-keep public class * extends android.app.Service
|
||||||
|
-keep public class * extends android.content.BroadcastReceiver
|
||||||
|
-keep public class * extends android.content.ContentProvider
|
||||||
|
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||||
|
-keep public class * extends android.preference.Preference
|
||||||
|
-keep public class com.android.vending.licensing.ILicensingService
|
||||||
|
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers class * extends android.app.Activity {
|
||||||
|
public void *(android.view.View);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers enum * {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class * implements android.os.Parcelable {
|
||||||
|
public static final android.os.Parcelable$Creator *;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system use,
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-10
|
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" >
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imgvFeedimage"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_width="50dip"
|
||||||
|
android:padding="10dip"
|
||||||
|
android:cropToPadding="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
/>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_alignParentRight="true">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtvFeedname"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtvNewEpisodes"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/textedit"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<Button
|
||||||
|
android:id="@+id/testbutton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Test2" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="hello">Hello World, PodfetcherActivity!</string>
|
||||||
|
<string name="app_name">Podfetcher</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,25 @@
|
||||||
|
package de.podfetcher;
|
||||||
|
|
||||||
|
import de.podfetcher.feed.FeedManager;
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
public class PodcastApp extends Application {
|
||||||
|
|
||||||
|
private static PodcastApp singleton;
|
||||||
|
|
||||||
|
public static PodcastApp getInstance() {
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
singleton = this;
|
||||||
|
|
||||||
|
FeedManager manager = FeedManager.getInstance();
|
||||||
|
manager.loadDBData(getApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package de.podfetcher;
|
||||||
|
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import de.podfetcher.feed.*;
|
||||||
|
import de.podfetcher.storage.DownloadRequester;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class PodfetcherActivity extends Activity {
|
||||||
|
/** Called when the activity is first created. */
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.main);
|
||||||
|
|
||||||
|
final DownloadRequester requester = DownloadRequester.getInstance();
|
||||||
|
final FeedHandler handler = new FeedHandler();
|
||||||
|
final FeedManager manager = FeedManager.getInstance();
|
||||||
|
|
||||||
|
final Button button = (Button)findViewById(R.id.testbutton);
|
||||||
|
final EditText edittext = (EditText)findViewById(R.id.textedit);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
button.setOnClickListener(new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
final String s = edittext.getText().toString();
|
||||||
|
manager.addFeed(v.getContext(), s);
|
||||||
|
edittext.setText("Receiving...");
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data Object for a whole feed
|
||||||
|
* @author daniel
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Feed extends FeedFile{
|
||||||
|
public String title;
|
||||||
|
public String link;
|
||||||
|
public String description;
|
||||||
|
public FeedImage image;
|
||||||
|
public FeedCategory category;
|
||||||
|
public ArrayList<FeedItem> items;
|
||||||
|
|
||||||
|
|
||||||
|
public Feed() {
|
||||||
|
items = new ArrayList<FeedItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Feed(String url) {
|
||||||
|
this.download_url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Feed(String title, String link, String description, String download_url,
|
||||||
|
FeedCategory category) {
|
||||||
|
super();
|
||||||
|
this.title = title;
|
||||||
|
this.link = link;
|
||||||
|
this.description = description;
|
||||||
|
this.download_url = download_url;
|
||||||
|
this.category = category;
|
||||||
|
items = new ArrayList<FeedItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
public class FeedCategory extends FeedComponent{
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
public FeedCategory(String name) {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents every possible component of a feed
|
||||||
|
* @author daniel
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FeedComponent {
|
||||||
|
|
||||||
|
public long id;
|
||||||
|
|
||||||
|
public FeedComponent() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
public abstract class FeedFile extends FeedComponent {
|
||||||
|
public String file_url;
|
||||||
|
public String download_url;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.parsers.SAXParser;
|
||||||
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
|
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
public class FeedHandler {
|
||||||
|
public final static String CHANNEL = "channel";
|
||||||
|
public final static String ITEM = "item";
|
||||||
|
public final static String TITLE = "title";
|
||||||
|
public final static String LINK = "link";
|
||||||
|
public final static String DESCR = "description";
|
||||||
|
public final static String PUBDATE = "pubDate";
|
||||||
|
public final static String ENCLOSURE = "enclosure";
|
||||||
|
public final static String IMAGE = "image";
|
||||||
|
public final static String URL = "url";
|
||||||
|
|
||||||
|
public final static String ENC_URL = "url";
|
||||||
|
public final static String ENC_LEN = "length";
|
||||||
|
public final static String ENC_TYPE = "type";
|
||||||
|
|
||||||
|
public Feed parseFeed(String file) throws ParserConfigurationException, SAXException {
|
||||||
|
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||||
|
SAXParser saxParser = factory.newSAXParser();
|
||||||
|
RSSHandler handler = new RSSHandler();
|
||||||
|
try {
|
||||||
|
saxParser.parse(new File(file), handler);
|
||||||
|
} catch (SAXException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler.feed;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
public class FeedImage extends FeedFile {
|
||||||
|
public String title;
|
||||||
|
|
||||||
|
public FeedImage(String download_url, String title) {
|
||||||
|
super();
|
||||||
|
this.download_url = download_url;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedImage(long id, String title, String file_url, String download_url) {
|
||||||
|
this.id = id;
|
||||||
|
this.title = title;
|
||||||
|
this.file_url = file_url;
|
||||||
|
this.download_url = download_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedImage() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data Object for a XML message
|
||||||
|
* @author daniel
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FeedItem extends FeedComponent{
|
||||||
|
public String title;
|
||||||
|
public String description;
|
||||||
|
public String link;
|
||||||
|
public String pubDate;
|
||||||
|
public FeedMedia media;
|
||||||
|
public Feed feed;
|
||||||
|
public boolean read;
|
||||||
|
|
||||||
|
public FeedItem() {
|
||||||
|
this.read = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedItem(String title, String description, String link,
|
||||||
|
String pubDate, FeedMedia media, Feed feed) {
|
||||||
|
super();
|
||||||
|
this.title = title;
|
||||||
|
this.description = description;
|
||||||
|
this.link = link;
|
||||||
|
this.pubDate = pubDate;
|
||||||
|
this.media = media;
|
||||||
|
this.feed = feed;
|
||||||
|
this.read = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
import de.podfetcher.storage.*;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton class
|
||||||
|
* Manages all feeds, categories and feeditems
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
public class FeedManager {
|
||||||
|
|
||||||
|
private static FeedManager singleton;
|
||||||
|
|
||||||
|
public ArrayList<Feed> feeds;
|
||||||
|
public ArrayList<FeedCategory> categories;
|
||||||
|
|
||||||
|
Cursor feedlistCursor;
|
||||||
|
|
||||||
|
|
||||||
|
private FeedManager() {
|
||||||
|
feeds = new ArrayList<Feed>();
|
||||||
|
categories = new ArrayList<FeedCategory>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FeedManager getInstance(){
|
||||||
|
if(singleton == null) {
|
||||||
|
singleton = new FeedManager();
|
||||||
|
}
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add and Download a new Feed */
|
||||||
|
public void addFeed(Context context, String url) {
|
||||||
|
// TODO Check if URL is correct
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
Feed feed = new Feed(url);
|
||||||
|
feed.id = adapter.setFeed(feed);
|
||||||
|
|
||||||
|
DownloadRequester req = DownloadRequester.getInstance();
|
||||||
|
req.downloadFeed(context, feed);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Reads the database */
|
||||||
|
public void loadDBData(Context context) {
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
feedlistCursor = adapter.getAllFeedsCursor();
|
||||||
|
updateArrays(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void updateArrays(Context context) {
|
||||||
|
feedlistCursor.requery();
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
feeds.clear();
|
||||||
|
categories.clear();
|
||||||
|
extractFeedlistFromCursor(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extractFeedlistFromCursor(Context context) {
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
if(feedlistCursor.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
Feed feed = new Feed();
|
||||||
|
|
||||||
|
feed.id = feedlistCursor.getLong(feedlistCursor.getColumnIndex(PodDBAdapter.KEY_ID));
|
||||||
|
feed.title = feedlistCursor.getString(feedlistCursor.getColumnIndex(PodDBAdapter.KEY_TITLE));
|
||||||
|
feed.link = feedlistCursor.getString(feedlistCursor.getColumnIndex(PodDBAdapter.KEY_LINK));
|
||||||
|
feed.description = feedlistCursor.getString(feedlistCursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION));
|
||||||
|
feed.image = adapter.getFeedImage(feed);
|
||||||
|
feed.file_url = feedlistCursor.getString(feedlistCursor.getColumnIndex(PodDBAdapter.KEY_FILE_URL));
|
||||||
|
feed.download_url = feedlistCursor.getString(feedlistCursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL));
|
||||||
|
|
||||||
|
// Get FeedItem-Object
|
||||||
|
Cursor itemlistCursor = adapter.getAllItemsOfFeedCursor(feed);
|
||||||
|
feed.items = extractFeedItemsFromCursor(context, itemlistCursor);
|
||||||
|
|
||||||
|
feeds.add(feed);
|
||||||
|
}while(feedlistCursor.moveToNext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<FeedItem> extractFeedItemsFromCursor(Context context, Cursor itemlistCursor) {
|
||||||
|
ArrayList<FeedItem> items = new ArrayList<FeedItem>();
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
|
||||||
|
if(itemlistCursor.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
FeedItem item = new FeedItem();
|
||||||
|
|
||||||
|
item.id = itemlistCursor.getLong(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_ID));
|
||||||
|
item.title = itemlistCursor.getString(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_TITLE));
|
||||||
|
item.link = itemlistCursor.getString(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_LINK));
|
||||||
|
item.description = itemlistCursor.getString(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION));
|
||||||
|
item.pubDate = itemlistCursor.getString(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_PUBDATE));
|
||||||
|
item.media = adapter.getFeedMedia(itemlistCursor.getLong(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_MEDIA)));
|
||||||
|
item.read = (itemlistCursor.getInt(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_READ)) > 0) ? true : false;
|
||||||
|
|
||||||
|
items.add(item);
|
||||||
|
} while(itemlistCursor.moveToNext());
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
public class FeedMedia extends FeedFile{
|
||||||
|
public long length;
|
||||||
|
public long position;
|
||||||
|
public long size; // File size in Byte
|
||||||
|
public String mime_type;
|
||||||
|
|
||||||
|
public FeedItem item; // TODO remove
|
||||||
|
|
||||||
|
public FeedMedia(FeedItem i, String download_url, long size, String mime_type) {
|
||||||
|
this.item = i;
|
||||||
|
this.download_url = download_url;
|
||||||
|
this.size = size;
|
||||||
|
this.mime_type = mime_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedMedia(long id, long length, long position, long size, String mime_type,
|
||||||
|
String file_url, String download_url) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
this.length = length;
|
||||||
|
this.position = position;
|
||||||
|
this.size = size;
|
||||||
|
this.mime_type = mime_type;
|
||||||
|
this.file_url = file_url;
|
||||||
|
this.download_url = download_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
package de.podfetcher.feed;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import de.podfetcher.feed.FeedHandler;
|
||||||
|
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SAX-Parser for reading RSS-Feeds
|
||||||
|
*
|
||||||
|
* @author daniel
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class RSSHandler extends DefaultHandler {
|
||||||
|
public ArrayList<FeedItem> items;
|
||||||
|
public FeedItem currentItem;
|
||||||
|
public StringBuilder strBuilder;
|
||||||
|
public Feed feed;
|
||||||
|
public String active_root_element; // channel or item or image
|
||||||
|
public String active_sub_element; // Not channel or item
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void characters(char[] ch, int start, int length)
|
||||||
|
throws SAXException {
|
||||||
|
if (active_sub_element != null) {
|
||||||
|
strBuilder.append(ch, start, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endDocument() throws SAXException {
|
||||||
|
feed.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endElement(String uri, String localName, String qName)
|
||||||
|
throws SAXException {
|
||||||
|
if (qName.equalsIgnoreCase(FeedHandler.ITEM)) {
|
||||||
|
currentItem.feed = feed;
|
||||||
|
items.add(currentItem);
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.TITLE)) {
|
||||||
|
if (active_root_element.equalsIgnoreCase(FeedHandler.CHANNEL)) {
|
||||||
|
feed.title = strBuilder.toString();
|
||||||
|
} else if(active_root_element.equalsIgnoreCase(FeedHandler.TITLE)) {
|
||||||
|
currentItem.title = strBuilder.toString();
|
||||||
|
} else if(active_root_element.equalsIgnoreCase(FeedHandler.IMAGE)) {
|
||||||
|
feed.image.title = strBuilder.toString();
|
||||||
|
}
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.DESCR)) {
|
||||||
|
if (active_root_element.equalsIgnoreCase(FeedHandler.CHANNEL)) {
|
||||||
|
feed.description = strBuilder.toString();
|
||||||
|
} else {
|
||||||
|
currentItem.description = strBuilder.toString();
|
||||||
|
}
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.LINK)) {
|
||||||
|
if (active_root_element.equalsIgnoreCase(FeedHandler.CHANNEL)) {
|
||||||
|
feed.link = strBuilder.toString();
|
||||||
|
} else if(active_root_element.equalsIgnoreCase(FeedHandler.TITLE)){
|
||||||
|
currentItem.link = strBuilder.toString();
|
||||||
|
}
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.PUBDATE)) {
|
||||||
|
if (active_root_element.equalsIgnoreCase(FeedHandler.ITEM)) {
|
||||||
|
currentItem.pubDate = strBuilder.toString();
|
||||||
|
}
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.URL)) {
|
||||||
|
if(active_root_element.equalsIgnoreCase(FeedHandler.IMAGE)) {
|
||||||
|
feed.image.download_url = strBuilder.toString();
|
||||||
|
}
|
||||||
|
} else if(qName.equalsIgnoreCase(FeedHandler.IMAGE)) {
|
||||||
|
active_root_element = FeedHandler.CHANNEL;
|
||||||
|
}
|
||||||
|
active_sub_element = null;
|
||||||
|
strBuilder = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startDocument() throws SAXException {
|
||||||
|
items = new ArrayList<FeedItem>();
|
||||||
|
strBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startElement(String uri, String localName, String qName,
|
||||||
|
Attributes attributes) throws SAXException {
|
||||||
|
if (qName.equalsIgnoreCase(FeedHandler.CHANNEL)) {
|
||||||
|
feed = new Feed();
|
||||||
|
active_root_element = qName;
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.ITEM)) {
|
||||||
|
currentItem = new FeedItem();
|
||||||
|
active_root_element = qName;
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.TITLE)) {
|
||||||
|
active_sub_element = qName;
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.DESCR)) {
|
||||||
|
active_sub_element = qName;
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.LINK)) {
|
||||||
|
active_sub_element = qName;
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.PUBDATE)) {
|
||||||
|
active_sub_element = qName;
|
||||||
|
} else if (qName.equalsIgnoreCase(FeedHandler.ENCLOSURE)) {
|
||||||
|
currentItem.media = new FeedMedia(currentItem,
|
||||||
|
attributes.getValue(FeedHandler.ENC_URL),
|
||||||
|
Long.parseLong(attributes.getValue(FeedHandler.ENC_LEN)),
|
||||||
|
attributes.getValue(FeedHandler.ENC_TYPE));
|
||||||
|
} else if(qName.equalsIgnoreCase(FeedHandler.IMAGE)) {
|
||||||
|
feed.image = new FeedImage();
|
||||||
|
active_root_element = qName;
|
||||||
|
} else if(qName.equalsIgnoreCase(FeedHandler.URL)) {
|
||||||
|
active_sub_element = qName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package de.podfetcher.gui;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class AddFeedActivity extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package de.podfetcher.gui;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.podfetcher.R;
|
||||||
|
import de.podfetcher.feed.Feed;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
|
||||||
|
public class FeedlistAdapter extends ArrayAdapter<Feed> {
|
||||||
|
|
||||||
|
int resource;
|
||||||
|
|
||||||
|
public FeedlistAdapter(Context context, int resource,
|
||||||
|
int textViewResourceId, List<Feed> objects) {
|
||||||
|
super(context, resource, textViewResourceId, objects);
|
||||||
|
this.resource = resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
LinearLayout feedlistView;
|
||||||
|
|
||||||
|
|
||||||
|
Feed feed = getItem(position);
|
||||||
|
// Inflate Layout
|
||||||
|
if (convertView == null) {
|
||||||
|
feedlistView = new LinearLayout(getContext());
|
||||||
|
String inflater = Context.LAYOUT_INFLATER_SERVICE;
|
||||||
|
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(inflater);
|
||||||
|
vi.inflate(resource, feedlistView, true);
|
||||||
|
} else {
|
||||||
|
feedlistView = (LinearLayout) convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageView imageView = (ImageView)feedlistView.findViewById(R.id.imgvFeedimage);
|
||||||
|
TextView txtvFeedname = (TextView)feedlistView.findViewById(R.id.txtvFeedname);
|
||||||
|
TextView txtvNewEpisodes = (TextView)feedlistView.findViewById(R.id.txtvNewEpisodes);
|
||||||
|
|
||||||
|
imageView.setImageURI(Uri.fromFile(new File(feed.file_url))); // TODO select default picture when no image downloaded
|
||||||
|
txtvFeedname.setText(feed.title);
|
||||||
|
// TODO find new Episodes txtvNewEpisodes.setText(feed)
|
||||||
|
return feedlistView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package de.podfetcher.storage;
|
||||||
|
|
||||||
|
import de.podfetcher.PodcastApp;
|
||||||
|
import android.app.DownloadManager;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
public class DownloadReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
|
||||||
|
DownloadRequester requester = DownloadRequester.getInstance();
|
||||||
|
Intent item_intent = requester.getItemIntent(id);
|
||||||
|
String action = item_intent.getAction();
|
||||||
|
if(action.equals(DownloadRequester.ACTION_FEED_DOWNLOAD_COMPLETED)) {
|
||||||
|
requester.removeFeedByID(item_intent.getLongExtra(DownloadRequester.EXTRA_ITEM_ID, -1));
|
||||||
|
} else if(action.equals(DownloadRequester.ACTION_MEDIA_DOWNLOAD_COMPLETED)) {
|
||||||
|
requester.removeMediaByID(item_intent.getLongExtra(DownloadRequester.EXTRA_ITEM_ID, -1));
|
||||||
|
} else if(action.equals(DownloadRequester.ACTION_IMAGE_DOWNLOAD_COMPLETED)) {
|
||||||
|
requester.removeImageByID(item_intent.getLongExtra(DownloadRequester.EXTRA_ITEM_ID, -1));
|
||||||
|
}
|
||||||
|
PodcastApp.getInstance().getApplicationContext().sendBroadcast(item_intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
package de.podfetcher.storage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import de.podfetcher.feed.Feed;
|
||||||
|
import de.podfetcher.feed.FeedImage;
|
||||||
|
import de.podfetcher.feed.FeedMedia;
|
||||||
|
|
||||||
|
import android.app.DownloadManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
|
||||||
|
public class DownloadRequester {
|
||||||
|
public static String EXTRA_DOWNLOAD_ID = "extra.de.podfetcher.storage.download_id";
|
||||||
|
public static String EXTRA_ITEM_ID = "extra.de.podfetcher.storage.item_id";
|
||||||
|
|
||||||
|
public static String ACTION_FEED_DOWNLOAD_COMPLETED = "action.de.podfetcher.storage.feed_download_completed";
|
||||||
|
public static String ACTION_MEDIA_DOWNLOAD_COMPLETED = "action.de.podfetcher.storage.media_download_completed";
|
||||||
|
public static String ACTION_IMAGE_DOWNLOAD_COMPLETED = "action.de.podfetcher.storage.image_download_completed";
|
||||||
|
|
||||||
|
private static boolean STORE_ON_SD = true;
|
||||||
|
public static String IMAGE_DOWNLOADPATH = "images";
|
||||||
|
public static String FEED_DOWNLOADPATH = "cache";
|
||||||
|
public static String MEDIA_DOWNLOADPATH = "media";
|
||||||
|
|
||||||
|
|
||||||
|
private static DownloadRequester downloader;
|
||||||
|
|
||||||
|
public ArrayList<Intent> feeds;
|
||||||
|
public ArrayList<Intent> images;
|
||||||
|
public ArrayList<Intent> media;
|
||||||
|
|
||||||
|
private DownloadRequester(){
|
||||||
|
feeds = new ArrayList<Intent>();
|
||||||
|
images = new ArrayList<Intent>();
|
||||||
|
media = new ArrayList<Intent>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DownloadRequester getInstance() {
|
||||||
|
if(downloader == null) {
|
||||||
|
downloader = new DownloadRequester();
|
||||||
|
}
|
||||||
|
return downloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void download(Context context, ArrayList<Intent> type, String str_uri, File dest, boolean visibleInUI, String action, long id) {
|
||||||
|
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(str_uri));
|
||||||
|
//request.allowScanningByMediaScanner();
|
||||||
|
|
||||||
|
request.setDestinationUri(Uri.fromFile(dest));
|
||||||
|
request.setVisibleInDownloadsUi(visibleInUI);
|
||||||
|
// TODO Set Allowed Network Types
|
||||||
|
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
|
Intent i = new Intent(action);
|
||||||
|
i.putExtra(EXTRA_DOWNLOAD_ID, manager.enqueue(request));
|
||||||
|
i.putExtra(EXTRA_ITEM_ID, id);
|
||||||
|
type.add(i);
|
||||||
|
|
||||||
|
}
|
||||||
|
public void downloadFeed(Context context, Feed feed) {
|
||||||
|
download(context, feeds, feed.download_url,
|
||||||
|
new File(context.getExternalFilesDir(FEED_DOWNLOADPATH), "feed-" + feed.id),
|
||||||
|
true, ACTION_FEED_DOWNLOAD_COMPLETED, feed.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void downloadImage(Context context, FeedImage image) {
|
||||||
|
download(context, images, image.download_url,
|
||||||
|
new File(context.getExternalFilesDir(IMAGE_DOWNLOADPATH), "image-" + image.id),
|
||||||
|
true, ACTION_IMAGE_DOWNLOAD_COMPLETED, image.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void downloadMedia(Context context, FeedMedia feedmedia) {
|
||||||
|
download(context, media, feedmedia.download_url,
|
||||||
|
new File(context.getExternalFilesDir(MEDIA_DOWNLOADPATH), "media-" + feedmedia.id),
|
||||||
|
true, ACTION_MEDIA_DOWNLOAD_COMPLETED, feedmedia.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFeedByID(long id) {
|
||||||
|
int len = feeds.size();
|
||||||
|
for(int x = 0; x < len; x++) {
|
||||||
|
if(feeds.get(x).getLongExtra(EXTRA_ITEM_ID, -1) == id) {
|
||||||
|
feeds.remove(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeMediaByID(long id) {
|
||||||
|
int len = media.size();
|
||||||
|
for(int x = 0; x < len; x++) {
|
||||||
|
if(media.get(x).getLongExtra(EXTRA_ITEM_ID, -1) == id) {
|
||||||
|
media.remove(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeImageByID(long id) {
|
||||||
|
int len = images.size();
|
||||||
|
for(int x = 0; x < len; x++) {
|
||||||
|
if(images.get(x).getLongExtra(EXTRA_ITEM_ID, -1) == id) {
|
||||||
|
images.remove(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the stored intent by looking for the right download id */
|
||||||
|
public Intent getItemIntent(long id) {
|
||||||
|
for(Intent i : feeds) {
|
||||||
|
if(i.getLongExtra(EXTRA_DOWNLOAD_ID, -1) == id) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(Intent i : media) {
|
||||||
|
if(i.getLongExtra(EXTRA_DOWNLOAD_ID, -1) == id) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(Intent i : images) {
|
||||||
|
if(i.getLongExtra(EXTRA_DOWNLOAD_ID, -1) == id) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,295 @@
|
||||||
|
package de.podfetcher.storage;
|
||||||
|
|
||||||
|
import de.podfetcher.feed.Feed;
|
||||||
|
import de.podfetcher.feed.FeedCategory;
|
||||||
|
import de.podfetcher.feed.FeedImage;
|
||||||
|
import de.podfetcher.feed.FeedItem;
|
||||||
|
import de.podfetcher.feed.FeedMedia;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.SQLException;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements methods for accessing the database
|
||||||
|
* */
|
||||||
|
public class PodDBAdapter {
|
||||||
|
|
||||||
|
private static final int DATABASE_VERSION = 1;
|
||||||
|
private static final String DATABASE_NAME = "Podfetcher.db";
|
||||||
|
|
||||||
|
// Key-constants
|
||||||
|
public static final String KEY_ID = "id";
|
||||||
|
public static final String KEY_TITLE = "title";
|
||||||
|
public static final String KEY_NAME = "name";
|
||||||
|
public static final String KEY_LINK = "link";
|
||||||
|
public static final String KEY_DESCRIPTION = "description";
|
||||||
|
public static final String KEY_FILE_URL = "file_url";
|
||||||
|
public static final String KEY_DOWNLOAD_URL = "download_url";
|
||||||
|
public static final String KEY_PUBDATE = "pubDate";
|
||||||
|
public static final String KEY_READ = "read";
|
||||||
|
public static final String KEY_LENGTH = "length";
|
||||||
|
public static final String KEY_POSITION = "position";
|
||||||
|
public static final String KEY_SIZE = "filesize";
|
||||||
|
public static final String KEY_MIME_TYPE = "mime_type";
|
||||||
|
public static final String KEY_IMAGE = "image";
|
||||||
|
public static final String KEY_CATEGORY = "category";
|
||||||
|
public static final String KEY_FEED = "feed";
|
||||||
|
public static final String KEY_MEDIA = "media";
|
||||||
|
|
||||||
|
// Table names
|
||||||
|
public static final String TABLE_NAME_FEEDS = "Feeds";
|
||||||
|
public static final String TABLE_NAME_FEED_ITEMS = "FeedItems";
|
||||||
|
public static final String TABLE_NAME_FEED_CATEGORIES = "FeedCategories";
|
||||||
|
public static final String TABLE_NAME_FEED_IMAGES = "FeedImages";
|
||||||
|
public static final String TABLE_NAME_FEED_MEDIA = "FeedMedia";
|
||||||
|
|
||||||
|
// SQL Statements for creating new tables
|
||||||
|
private static final String TABLE_PRIMARY_KEY = KEY_ID
|
||||||
|
+ " INTEGER PRIMARY KEY AUTOINCREMENT ,";
|
||||||
|
private static final String CREATE_TABLE_FEEDS = "CREATE TABLE "
|
||||||
|
+ TABLE_NAME_FEEDS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
|
||||||
|
+ " TEXT," + KEY_LINK + " TEXT," + KEY_DESCRIPTION
|
||||||
|
+ " TEXT," + KEY_IMAGE + " INTEGER," + KEY_CATEGORY
|
||||||
|
+ " INTEGER," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL
|
||||||
|
+ " TEXT)";
|
||||||
|
|
||||||
|
private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
|
||||||
|
+ TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
|
||||||
|
+ " TEXT," + KEY_LINK + " TEXT," + KEY_DESCRIPTION
|
||||||
|
+ " TEXT," + KEY_PUBDATE + " TEXT," + KEY_MEDIA
|
||||||
|
+ " INTEGER," + KEY_FEED + " INTEGER," + KEY_READ
|
||||||
|
+ " INTEGER)";
|
||||||
|
|
||||||
|
private static final String CREATE_TABLE_FEED_CATEGORIES = "CREATE TABLE "
|
||||||
|
+ TABLE_NAME_FEED_CATEGORIES + " (" + TABLE_PRIMARY_KEY + KEY_NAME
|
||||||
|
+ " TEXT)";
|
||||||
|
|
||||||
|
private static final String CREATE_TABLE_FEED_IMAGES = "CREATE TABLE "
|
||||||
|
+ TABLE_NAME_FEED_IMAGES + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
|
||||||
|
+ " TEXT," + KEY_FILE_URL + " TEXT,"
|
||||||
|
+ KEY_DOWNLOAD_URL + " TEXT)";
|
||||||
|
|
||||||
|
private static final String CREATE_TABLE_FEED_MEDIA = "CREATE TABLE "
|
||||||
|
+ TABLE_NAME_FEED_MEDIA + " (" + TABLE_PRIMARY_KEY + KEY_LENGTH
|
||||||
|
+ " INTEGER," + KEY_POSITION + " INTEGER,"
|
||||||
|
+ KEY_SIZE + " INTEGER," + KEY_MIME_TYPE + " TEXT,"
|
||||||
|
+ KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT)";
|
||||||
|
|
||||||
|
private SQLiteDatabase db;
|
||||||
|
private final Context context;
|
||||||
|
private PodDBHelper helper;
|
||||||
|
|
||||||
|
public PodDBAdapter(Context c) {
|
||||||
|
this.context = c;
|
||||||
|
helper = new PodDBHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PodDBAdapter open() {
|
||||||
|
try {
|
||||||
|
db = helper.getWritableDatabase();
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
db = helper.getReadableDatabase();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Inserts or updates a feed entry
|
||||||
|
* @return the id of the entry
|
||||||
|
* */
|
||||||
|
public long setFeed(Feed feed) {
|
||||||
|
open();
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(KEY_TITLE, feed.title);
|
||||||
|
values.put(KEY_LINK, feed.link);
|
||||||
|
values.put(KEY_DESCRIPTION, feed.description);
|
||||||
|
if (feed.image != null) {
|
||||||
|
if (feed.image.id == 0) {
|
||||||
|
setImage(feed.image);
|
||||||
|
}
|
||||||
|
values.put(KEY_IMAGE, feed.image.id);
|
||||||
|
}
|
||||||
|
if(feed.category != null) {
|
||||||
|
if(feed.category.id == 0) {
|
||||||
|
setCategory(feed.category);
|
||||||
|
}
|
||||||
|
values.put(KEY_CATEGORY, feed.category.id);
|
||||||
|
}
|
||||||
|
if(feed.file_url != null) {
|
||||||
|
values.put(KEY_FILE_URL, feed.file_url);
|
||||||
|
}
|
||||||
|
values.put(KEY_DOWNLOAD_URL, feed.download_url);
|
||||||
|
|
||||||
|
if(feed.id == 0) {
|
||||||
|
// Create new entry
|
||||||
|
feed.id = db.insert(TABLE_NAME_FEEDS, null, values);
|
||||||
|
} else {
|
||||||
|
db.update(TABLE_NAME_FEEDS, values, KEY_ID+"=?", new String[]{String.valueOf(feed.id)});
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
return feed.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Inserts or updates a category entry
|
||||||
|
* @return the id of the entry
|
||||||
|
* */
|
||||||
|
public long setCategory(FeedCategory category) {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(KEY_NAME, category.name);
|
||||||
|
if(category.id == 0) {
|
||||||
|
category.id = db.insert(TABLE_NAME_FEED_CATEGORIES, null, values);
|
||||||
|
} else {
|
||||||
|
db.update(TABLE_NAME_FEED_CATEGORIES, values, KEY_ID+"=?", new String[]{String.valueOf(category.id)});
|
||||||
|
|
||||||
|
}
|
||||||
|
return category.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts or updates an image entry
|
||||||
|
* @return the id of the entry
|
||||||
|
* */
|
||||||
|
public long setImage(FeedImage image) {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(KEY_TITLE, image.title);
|
||||||
|
values.put(KEY_DOWNLOAD_URL, image.download_url);
|
||||||
|
if(image.file_url != null) {
|
||||||
|
values.put(KEY_FILE_URL, image.file_url);
|
||||||
|
}
|
||||||
|
if(image.id == 0) {
|
||||||
|
image.id = db.insert(TABLE_NAME_FEED_IMAGES, null, values);
|
||||||
|
} else {
|
||||||
|
db.update(TABLE_NAME_FEED_IMAGES, values, KEY_ID+"=?", new String[]{String.valueOf(image.id)});
|
||||||
|
}
|
||||||
|
return image.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts or updates an image entry
|
||||||
|
* @return the id of the entry
|
||||||
|
*/
|
||||||
|
public long setMedia(FeedMedia media) {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(KEY_LENGTH, media.length);
|
||||||
|
values.put(KEY_POSITION, media.position);
|
||||||
|
values.put(KEY_SIZE, media.size);
|
||||||
|
values.put(KEY_MIME_TYPE, media.mime_type);
|
||||||
|
values.put(KEY_DOWNLOAD_URL, media.download_url);
|
||||||
|
if(media.file_url != null) {
|
||||||
|
values.put(KEY_FILE_URL, media.file_url);
|
||||||
|
}
|
||||||
|
if(media.id == 0) {
|
||||||
|
media.id = db.insert(TABLE_NAME_FEED_MEDIA, null, values);
|
||||||
|
} else {
|
||||||
|
db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID+"=?", new String[]{String.valueOf(media.id)});
|
||||||
|
}
|
||||||
|
return media.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts or updates a feeditem entry
|
||||||
|
* @return the id of the entry
|
||||||
|
*/
|
||||||
|
public long setFeedItem(FeedItem item) {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(KEY_TITLE, item.title);
|
||||||
|
values.put(KEY_LINK, item.link);
|
||||||
|
values.put(KEY_DESCRIPTION, item.description);
|
||||||
|
values.put(KEY_PUBDATE, item.pubDate);
|
||||||
|
if(item.media != null) {
|
||||||
|
if(item.media.id == 0) {
|
||||||
|
setMedia(item.media);
|
||||||
|
}
|
||||||
|
values.put(KEY_MEDIA, item.media.id);
|
||||||
|
}
|
||||||
|
if(item.feed.id == 0) {
|
||||||
|
setFeed(item.feed);
|
||||||
|
}
|
||||||
|
values.put(KEY_FEED, item.feed.id);
|
||||||
|
values.put(KEY_READ, (item.read) ? 1 : 0);
|
||||||
|
return item.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor getAllCategoriesCursor() {
|
||||||
|
return db.query(TABLE_NAME_FEED_CATEGORIES, null, null, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor getAllFeedsCursor() {
|
||||||
|
return db.query(TABLE_NAME_FEEDS, null, null, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor getAllItemsOfFeedCursor(Feed feed) {
|
||||||
|
return db.query(TABLE_NAME_FEED_ITEMS, null, KEY_FEED+"=?", new String[]{String.valueOf(feed.id)}, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor getFeedMediaOfItemCursor(FeedItem item) {
|
||||||
|
return db.query(TABLE_NAME_FEED_MEDIA, null, KEY_ID+"=?", new String[]{String.valueOf(item.media.id)}, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor getImageOfFeedCursor(Feed feed) {
|
||||||
|
return db.query(TABLE_NAME_FEED_IMAGES, null, KEY_ID+"=?", new String[]{String.valueOf(feed.image.id)}, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedMedia getFeedMedia(long row_index) throws SQLException{
|
||||||
|
Cursor cursor = db.query(TABLE_NAME_FEED_MEDIA, null, KEY_ID+"=?", new String[]{String.valueOf(row_index)}, null, null, null);
|
||||||
|
|
||||||
|
if((cursor.getCount() == 0) || !cursor.moveToFirst()) {
|
||||||
|
throw new SQLException("No FeedMedia found at index: "+ row_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FeedMedia(row_index,
|
||||||
|
cursor.getLong(cursor.getColumnIndex(KEY_LENGTH)),
|
||||||
|
cursor.getLong(cursor.getColumnIndex(KEY_POSITION)),
|
||||||
|
cursor.getLong(cursor.getColumnIndex(KEY_SIZE)),
|
||||||
|
cursor.getString(cursor.getColumnIndex(KEY_MIME_TYPE)),
|
||||||
|
cursor.getString(cursor.getColumnIndex(KEY_FILE_URL)),
|
||||||
|
cursor.getString(cursor.getColumnIndex(KEY_DOWNLOAD_URL)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedImage getFeedImage(Feed feed) throws SQLException {
|
||||||
|
Cursor cursor = this.getImageOfFeedCursor(feed);
|
||||||
|
if((cursor.getCount() == 0) || !cursor.moveToFirst()) {
|
||||||
|
throw new SQLException("No FeedImage found at index: "+ feed.image.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FeedImage(feed.image.id, cursor.getString(cursor.getColumnIndex(KEY_TITLE)),
|
||||||
|
cursor.getString(cursor.getColumnIndex(KEY_FILE_URL)),
|
||||||
|
cursor.getString(cursor.getColumnIndex(KEY_DOWNLOAD_URL)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PodDBHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
public PodDBHelper(Context context, String name, CursorFactory factory,
|
||||||
|
int version) {
|
||||||
|
super(context, name, factory, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
db.execSQL(CREATE_TABLE_FEEDS);
|
||||||
|
db.execSQL(CREATE_TABLE_FEED_ITEMS);
|
||||||
|
db.execSQL(CREATE_TABLE_FEED_CATEGORIES);
|
||||||
|
db.execSQL(CREATE_TABLE_FEED_IMAGES);
|
||||||
|
db.execSQL(CREATE_TABLE_FEED_MEDIA);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
|
||||||
|
+ newVersion + ".");
|
||||||
|
// TODO delete Database
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue