Remove unused code
This commit is contained in:
parent
66aa5ee3e5
commit
4e1b620225
@ -135,7 +135,6 @@ dependencies {
|
||||
implementation(project(":owncloud"))
|
||||
implementation(project(":permissions"))
|
||||
implementation(project(":preferences"))
|
||||
implementation(project(":rssparser"))
|
||||
implementation(project(":search"))
|
||||
implementation(project(":transition"))
|
||||
implementation(project(":unitconverter"))
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 14,
|
||||
"identityHash": "89c214d548f80f5c25612f5e6ebf9725",
|
||||
"identityHash": "7e492b4e6f9b150fd7a36e3e028650e8",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "forecasts",
|
||||
@ -346,39 +346,6 @@
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "Plugin",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `data` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`packageName`, `data`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "packageName",
|
||||
"columnName": "packageName",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "data",
|
||||
"columnName": "data",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"packageName",
|
||||
"data"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "Widget",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `data` TEXT NOT NULL, `height` INTEGER NOT NULL, `position` INTEGER NOT NULL, `label` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
||||
@ -433,7 +400,7 @@
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '89c214d548f80f5c25612f5e6ebf9725')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7e492b4e6f9b150fd7a36e3e028650e8')"
|
||||
]
|
||||
}
|
||||
}
|
||||
406
database/schemas/de.mm20.launcher2.database.AppDatabase/15.json
Normal file
406
database/schemas/de.mm20.launcher2.database.AppDatabase/15.json
Normal file
@ -0,0 +1,406 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 15,
|
||||
"identityHash": "7e492b4e6f9b150fd7a36e3e028650e8",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "forecasts",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`timestamp` INTEGER NOT NULL, `temperature` REAL NOT NULL, `minTemp` REAL NOT NULL, `maxTemp` REAL NOT NULL, `pressure` REAL NOT NULL, `humidity` REAL NOT NULL, `icon` INTEGER NOT NULL, `condition` TEXT NOT NULL, `clouds` INTEGER NOT NULL, `windSpeed` REAL NOT NULL, `windDirection` REAL NOT NULL, `rain` REAL NOT NULL, `snow` REAL NOT NULL, `night` INTEGER NOT NULL, `location` TEXT NOT NULL, `provider` TEXT NOT NULL, `providerUrl` TEXT NOT NULL, `rainProbability` INTEGER NOT NULL, `snowProbability` INTEGER NOT NULL, `updateTime` INTEGER NOT NULL, PRIMARY KEY(`timestamp`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "timestamp",
|
||||
"columnName": "timestamp",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "temperature",
|
||||
"columnName": "temperature",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "minTemp",
|
||||
"columnName": "minTemp",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "maxTemp",
|
||||
"columnName": "maxTemp",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pressure",
|
||||
"columnName": "pressure",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "humidity",
|
||||
"columnName": "humidity",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "icon",
|
||||
"columnName": "icon",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "condition",
|
||||
"columnName": "condition",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "clouds",
|
||||
"columnName": "clouds",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windSpeed",
|
||||
"columnName": "windSpeed",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "windDirection",
|
||||
"columnName": "windDirection",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipitation",
|
||||
"columnName": "rain",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snow",
|
||||
"columnName": "snow",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "night",
|
||||
"columnName": "night",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "location",
|
||||
"columnName": "location",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "provider",
|
||||
"columnName": "provider",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "providerUrl",
|
||||
"columnName": "providerUrl",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "precipProbability",
|
||||
"columnName": "rainProbability",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snowProbability",
|
||||
"columnName": "snowProbability",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "updateTime",
|
||||
"columnName": "updateTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"timestamp"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "Searchable",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `searchable` TEXT NOT NULL, `launchCount` INTEGER NOT NULL, `pinned` INTEGER NOT NULL, `hidden` INTEGER NOT NULL, PRIMARY KEY(`key`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "key",
|
||||
"columnName": "key",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "serializedSearchable",
|
||||
"columnName": "searchable",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "launchCount",
|
||||
"columnName": "launchCount",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pinPosition",
|
||||
"columnName": "pinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "hidden",
|
||||
"columnName": "hidden",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"key"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "Websearch",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`urlTemplate` TEXT NOT NULL, `label` TEXT NOT NULL, `color` INTEGER NOT NULL, `icon` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "urlTemplate",
|
||||
"columnName": "urlTemplate",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "label",
|
||||
"columnName": "label",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "color",
|
||||
"columnName": "color",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "icon",
|
||||
"columnName": "icon",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "Currency",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`symbol` TEXT NOT NULL, `value` REAL NOT NULL, `lastUpdate` INTEGER NOT NULL, PRIMARY KEY(`symbol`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "symbol",
|
||||
"columnName": "symbol",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "value",
|
||||
"columnName": "value",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdate",
|
||||
"columnName": "lastUpdate",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"symbol"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "Icons",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `componentName` TEXT, `drawable` TEXT, `iconPack` TEXT NOT NULL, `scale` REAL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "componentName",
|
||||
"columnName": "componentName",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "drawable",
|
||||
"columnName": "drawable",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "iconPack",
|
||||
"columnName": "iconPack",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "scale",
|
||||
"columnName": "scale",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "IconPack",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `packageName` TEXT NOT NULL, `version` TEXT NOT NULL, `scale` REAL NOT NULL, PRIMARY KEY(`packageName`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "packageName",
|
||||
"columnName": "packageName",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "version",
|
||||
"columnName": "version",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "scale",
|
||||
"columnName": "scale",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"packageName"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "Widget",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `data` TEXT NOT NULL, `height` INTEGER NOT NULL, `position` INTEGER NOT NULL, `label` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "data",
|
||||
"columnName": "data",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "height",
|
||||
"columnName": "height",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "label",
|
||||
"columnName": "label",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7e492b4e6f9b150fd7a36e3e028650e8')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -15,8 +15,7 @@ import de.mm20.launcher2.database.entities.*
|
||||
CurrencyEntity::class,
|
||||
IconEntity::class,
|
||||
IconPackEntity::class,
|
||||
PluginEntity::class,
|
||||
WidgetEntity::class], version = 14, exportSchema = true)
|
||||
WidgetEntity::class], version = 15, exportSchema = true)
|
||||
@TypeConverters(ComponentNameConverter::class, StringListConverter::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
@ -54,7 +53,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration_10_11(),
|
||||
Migration_11_12(),
|
||||
Migration_12_13(),
|
||||
Migration_13_14()
|
||||
Migration_13_14(),
|
||||
Migration_14_15()
|
||||
).build()
|
||||
if (_instance == null) _instance = instance
|
||||
return instance
|
||||
@ -143,5 +143,8 @@ class Migration_13_14 : Migration(13, 14) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS `Plugins`;")
|
||||
}
|
||||
|
||||
}
|
||||
class Migration_14_15 : Migration(14, 15) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
|
||||
@Entity(tableName = "Plugin", primaryKeys = ["packageName", "data"])
|
||||
data class PluginEntity(
|
||||
val packageName: String,
|
||||
val data: String,
|
||||
val type: String
|
||||
)
|
||||
1
rssparser/.gitignore
vendored
1
rssparser/.gitignore
vendored
@ -1 +0,0 @@
|
||||
/build
|
||||
@ -1,40 +0,0 @@
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
id("kotlin-android")
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk = sdk.versions.compileSdk.get().toInt()
|
||||
|
||||
defaultConfig {
|
||||
minSdk = sdk.versions.minSdk.get().toInt()
|
||||
targetSdk = sdk.versions.targetSdk.get().toInt()
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles("consumer-rules.pro")
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.kotlin.stdlib)
|
||||
implementation(libs.okhttp)
|
||||
}
|
||||
21
rssparser/proguard-rules.pro
vendored
21
rssparser/proguard-rules.pro
vendored
@ -1,21 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.kts.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@ -1,2 +0,0 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.mm20.rssparser"/>
|
||||
@ -1,52 +0,0 @@
|
||||
package de.mm20.rssparser
|
||||
|
||||
/**
|
||||
* Represents an <item> of the RSS feed.
|
||||
* A channel may contain any number of <item>s. An item may represent a "story" -- much like a story
|
||||
* in a newspaper or magazine; if so its description is a synopsis of the story, and the link points
|
||||
* to the full story. An item may also be complete in itself, if so, the description contains the
|
||||
* text (entity-encoded HTML is allowed), and the link and title may be omitted. All elements of an
|
||||
* item are optional, however at least one of title or description must be present.
|
||||
*/
|
||||
data class Article(
|
||||
/**
|
||||
* The title of the item.
|
||||
*/
|
||||
val title: String,
|
||||
/**
|
||||
* The URL of the item.
|
||||
*/
|
||||
val link: String,
|
||||
/**
|
||||
* The item synopsis.
|
||||
*/
|
||||
val description: String,
|
||||
/**
|
||||
* Email address of the author of the item.
|
||||
*/
|
||||
val author: String?,
|
||||
/**
|
||||
* Includes the item in one or more categories.
|
||||
*/
|
||||
val categories: List<String>,
|
||||
/**
|
||||
* URL of a page for comments relating to the item.
|
||||
*/
|
||||
val comments: String?,
|
||||
/**
|
||||
* Describes a media object that is attached to the item.
|
||||
*/
|
||||
val enclosure: String?,
|
||||
/**
|
||||
* A string that uniquely identifies the item.
|
||||
*/
|
||||
val guid: String?,
|
||||
/**
|
||||
* Indicates when the item was published.
|
||||
*/
|
||||
val pubDate: Long?,
|
||||
/**
|
||||
* The RSS channel that the item came from.
|
||||
*/
|
||||
val source: String?
|
||||
)
|
||||
@ -1,5 +0,0 @@
|
||||
package de.mm20.rssparser
|
||||
|
||||
enum class DayOfWeek {
|
||||
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
package de.mm20.rssparser
|
||||
|
||||
class InvalidFeedException(message: String? = null) : Exception(message)
|
||||
@ -1,84 +0,0 @@
|
||||
package de.mm20.rssparser
|
||||
|
||||
data class FeedInfo(
|
||||
/**
|
||||
* The name of the channel. It's how people refer to your service. If you have an HTML
|
||||
* website that contains the same information as your RSS file, the title of your channel
|
||||
* should be the same as the title of your website.
|
||||
*/
|
||||
val title: String,
|
||||
/**
|
||||
* The URL to the HTML website corresponding to the channel.
|
||||
*/
|
||||
val link: String,
|
||||
/**
|
||||
* Phrase or sentence describing the channel.
|
||||
*/
|
||||
val description: String,
|
||||
/**
|
||||
* The language the channel is written in. This allows aggregators to group all Italian
|
||||
* language sites, for example, on a single page. A list of allowable values for this
|
||||
* element, as provided by Netscape, is
|
||||
* [here](http://backend.userland.com/stories/storyReader$16). You may also use
|
||||
* [values defined](http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes) by the
|
||||
* W3C.
|
||||
*/
|
||||
val language: String?,
|
||||
/**
|
||||
* Copyright notice for content in the channel.
|
||||
*/
|
||||
val copyright: String?,
|
||||
/**
|
||||
* Email address for person responsible for editorial content.
|
||||
*/
|
||||
val managingEditor: String?,
|
||||
/**
|
||||
* Email address for person responsible for technical issues relating to channel.
|
||||
*/
|
||||
val webMaster: String?,
|
||||
/**
|
||||
* The publication date for the content in the channel. For example, the New York Times
|
||||
* publishes on a daily basis, the publication date flips once every 24 hours. That's when
|
||||
* the pubDate of the channel changes.
|
||||
*/
|
||||
val pubDate: Long?,
|
||||
/**
|
||||
* The last time the content of the channel changed.
|
||||
*/
|
||||
val lastBuildDate: Long?,
|
||||
/**
|
||||
* Specify one or more categories that the channel belongs to.
|
||||
*/
|
||||
val category: List<String>,
|
||||
/**
|
||||
* A string indicating the program used to generate the channel.
|
||||
*/
|
||||
val generator: String?,
|
||||
/**
|
||||
* A URL that points to the documentation for the format used in the RSS file. It's probably
|
||||
* a pointer to [this page](https://validator.w3.org/feed/docs/rss2.html). It's for people
|
||||
* who might stumble across an RSS file on a Web server 25 years from now and wonder what it
|
||||
* is.
|
||||
*/
|
||||
val docs: String?,
|
||||
/**
|
||||
* ttl stands for time to live. It's a number of minutes that indicates how long a channel
|
||||
* can be cached before refreshing from the source. More info
|
||||
* [here](https://validator.w3.org/feed/docs/rss2.html#ltttlgtSubelementOfLtchannelgt).
|
||||
*/
|
||||
val ttl: Int?,
|
||||
/**
|
||||
* Specifies a GIF, JPEG or PNG image that can be displayed with the channel.
|
||||
*/
|
||||
val image: String?,
|
||||
/**
|
||||
* A hint for aggregators telling them which hours they can skip. More info
|
||||
* [here](http://backend.userland.com/skipHoursDays#skiphours).
|
||||
*/
|
||||
val skipHours: List<Int>,
|
||||
/**
|
||||
* A hint for aggregators telling them which days they can skip. More info
|
||||
* [here](http://backend.userland.com/skipHoursDays#skipdays).
|
||||
*/
|
||||
val skipDays: List<DayOfWeek>
|
||||
)
|
||||
@ -1,133 +0,0 @@
|
||||
package de.mm20.rssparser
|
||||
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.w3c.dom.Element
|
||||
import org.xml.sax.SAXException
|
||||
import java.io.IOException
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
|
||||
class RssParser(
|
||||
var url: String
|
||||
) {
|
||||
|
||||
lateinit var articles: List<Article>
|
||||
private set
|
||||
|
||||
lateinit var feedInfo: FeedInfo
|
||||
private set
|
||||
|
||||
/**
|
||||
* Fetches the feed from server and parses it.
|
||||
* Do not call this in main thread.
|
||||
* After this you can access [feedInfo] and [articles]
|
||||
* @return the list of articles in that RSS feed
|
||||
* @throws InvalidFeedException if the url does not point to a valid RSS2.0 feed
|
||||
* @throws java.io.IOException if the feed url does not exist or there was an error downloading it
|
||||
*/
|
||||
@Throws(InvalidFeedException::class, IOException::class)
|
||||
fun loadFeed() {
|
||||
val articles = mutableListOf<Article>()
|
||||
try {
|
||||
val request = Request.Builder().url(url).build()
|
||||
val client = OkHttpClient()
|
||||
val feedStream = client.newCall(request).execute().body?.byteStream()
|
||||
?: throw IOException()
|
||||
val document = DocumentBuilderFactory
|
||||
.newInstance()
|
||||
.newDocumentBuilder()
|
||||
.parse(feedStream)
|
||||
|
||||
val rootElement = document.documentElement
|
||||
|
||||
if (rootElement.tagName != "rss" || rootElement.getAttribute("version") != "2.0") {
|
||||
throw InvalidFeedException("Document is not an RSS 2.0 feed")
|
||||
}
|
||||
val dateFormat = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ROOT)
|
||||
feedInfo = FeedInfo(
|
||||
title = document.getElementsByTagName("title").item(0)?.textContent ?: url,
|
||||
link = document.getElementsByTagName("link").item(0)?.textContent ?: url,
|
||||
description = document.getElementsByTagName("description").item(0)?.textContent
|
||||
?: "",
|
||||
language = document.getElementsByTagName("language").item(0)?.textContent,
|
||||
copyright = document.getElementsByTagName("copyright").item(0)?.textContent,
|
||||
managingEditor = document.getElementsByTagName("managingEditor").item(0)?.textContent,
|
||||
webMaster = document.getElementsByTagName("webMaster").item(0)?.textContent,
|
||||
pubDate = parseDate(document.getElementsByTagName("pubDate")
|
||||
.item(0)?.textContent ?: "", dateFormat),
|
||||
lastBuildDate = parseDate(document.getElementsByTagName("lastBuildDate")
|
||||
.item(0)?.textContent ?: "", dateFormat),
|
||||
category = document.getElementsByTagName("category").run {
|
||||
(0 until length).mapNotNull { item(it).textContent }
|
||||
},
|
||||
generator = document.getElementsByTagName("generator").item(0)?.textContent,
|
||||
docs = document.getElementsByTagName("docs").item(0)?.textContent,
|
||||
ttl = document.getElementsByTagName("generator").item(0)?.textContent?.toIntOrNull(),
|
||||
image = (document.getElementsByTagName("image")
|
||||
.item(0)as? Element)
|
||||
?.getElementsByTagName("url")
|
||||
?.item(0)?.textContent,
|
||||
skipHours = (document.getElementsByTagName("skipHours") as? Element)
|
||||
?.getElementsByTagName("hour")?.run {
|
||||
(0 until length).mapNotNull { item(it)?.textContent?.toIntOrNull() }
|
||||
} ?: emptyList(),
|
||||
skipDays = (document.getElementsByTagName("skipDays") as? Element)
|
||||
?.getElementsByTagName("day")?.run {
|
||||
(0 until length).mapNotNull { getWeekday(item(it)?.textContent) }
|
||||
} ?: emptyList()
|
||||
)
|
||||
val items = document.getElementsByTagName("item")
|
||||
|
||||
for (i in 0 until items.length) {
|
||||
val item = items.item(i) as? Element ?: continue
|
||||
val article = Article(
|
||||
title = item.getElementsByTagName("title").item(0)?.textContent ?: continue,
|
||||
link = item.getElementsByTagName("link").item(0)?.textContent ?: "",
|
||||
description = item.getElementsByTagName("description").item(0)?.textContent
|
||||
?: "",
|
||||
author = item.getElementsByTagName("author").item(0)?.textContent,
|
||||
categories = document.getElementsByTagName("category").run {
|
||||
(0 until length).mapNotNull { item(it).textContent }
|
||||
},
|
||||
comments = item.getElementsByTagName("comments").item(0)?.textContent,
|
||||
enclosure = item.getElementsByTagName("enclosure").item(0)?.textContent,
|
||||
guid = item.getElementsByTagName("guid").item(0)?.textContent,
|
||||
pubDate = parseDate(item.getElementsByTagName("pubDate").item(0)?.textContent
|
||||
?: "", dateFormat),
|
||||
source = item.getElementsByTagName("source").item(0)?.textContent
|
||||
)
|
||||
articles.add(article)
|
||||
}
|
||||
|
||||
} catch (e: SAXException) {
|
||||
throw InvalidFeedException()
|
||||
} catch (e: IOException) {
|
||||
throw IOException(e)
|
||||
}
|
||||
this.articles = articles
|
||||
}
|
||||
|
||||
private fun parseDate(date: String, dateFormat: SimpleDateFormat): Long? {
|
||||
return try {
|
||||
dateFormat.parse(date)?.time
|
||||
} catch (e: ParseException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getWeekday(day: String?): DayOfWeek? {
|
||||
return when (day) {
|
||||
"Sunday" -> DayOfWeek.SUNDAY
|
||||
"Monday" -> DayOfWeek.MONDAY
|
||||
"Tuesday" -> DayOfWeek.TUESDAY
|
||||
"Wednesday" -> DayOfWeek.WEDNESDAY
|
||||
"Thursday" -> DayOfWeek.SATURDAY
|
||||
"Friday" -> DayOfWeek.FRIDAY
|
||||
"Saturday" -> DayOfWeek.SATURDAY
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
<string name="app_name">RSSParser</string>
|
||||
</resources>
|
||||
@ -30,7 +30,6 @@ include(":i18n")
|
||||
include(":database")
|
||||
include(":ktx")
|
||||
include(":app")
|
||||
include(":rssparser")
|
||||
include(":permissions")
|
||||
include(":ui")
|
||||
include(":compat")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user