mirror of https://github.com/Xe/xesite_android
oh hey it works!
Signed-off-by: Christine Dodrill <me@christine.website>
This commit is contained in:
parent
74929d4fe1
commit
d8d36edb45
|
@ -207,5 +207,6 @@ dependencies {
|
||||||
|
|
||||||
implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.2.0'
|
implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.2.0'
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
implementation "com.android.support:support-compat:28.0.0"
|
implementation 'com.android.volley:volley:1.2.0'
|
||||||
|
implementation 'com.google.code.gson:gson:2.8.7'
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package website.christine.xesite
|
||||||
|
|
||||||
|
import com.android.volley.NetworkResponse
|
||||||
|
import com.android.volley.ParseError
|
||||||
|
import com.android.volley.Request
|
||||||
|
import com.android.volley.Response
|
||||||
|
import com.android.volley.toolbox.HttpHeaderParser
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import java.io.UnsupportedEncodingException
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a GET request and return a parsed object from JSON.
|
||||||
|
*
|
||||||
|
* @param url URL of the request to make
|
||||||
|
* @param clazz Relevant class object, for Gson's reflection
|
||||||
|
* @param headers Map of request headers
|
||||||
|
*
|
||||||
|
* From here: https://developer.android.com/training/volley/request-custom
|
||||||
|
*/
|
||||||
|
class GsonGetRequest<T>(
|
||||||
|
url: String,
|
||||||
|
private val clazz: Class<T>,
|
||||||
|
private val headers: MutableMap<String, String>?,
|
||||||
|
private val listener: Response.Listener<T>,
|
||||||
|
errorListener: Response.ErrorListener
|
||||||
|
) : Request<T>(Method.GET, url, errorListener) {
|
||||||
|
private val gson = Gson()
|
||||||
|
|
||||||
|
override fun getHeaders(): MutableMap<String, String> = headers ?: super.getHeaders()
|
||||||
|
|
||||||
|
override fun deliverResponse(response: T) = listener.onResponse(response)
|
||||||
|
|
||||||
|
override fun parseNetworkResponse(response: NetworkResponse?): Response<T> {
|
||||||
|
return try {
|
||||||
|
val json = String(
|
||||||
|
response?.data ?: ByteArray(0),
|
||||||
|
Charset.forName(HttpHeaderParser.parseCharset(response?.headers)))
|
||||||
|
Response.success(
|
||||||
|
gson.fromJson(json, clazz),
|
||||||
|
HttpHeaderParser.parseCacheHeaders(response))
|
||||||
|
} catch (e: UnsupportedEncodingException) {
|
||||||
|
Response.error(ParseError(e))
|
||||||
|
} catch (e: JsonSyntaxException) {
|
||||||
|
Response.error(ParseError(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package website.christine.xesite
|
||||||
|
|
||||||
|
class NewPost (
|
||||||
|
val title: String,
|
||||||
|
val summary: String,
|
||||||
|
val link: String,
|
||||||
|
)
|
|
@ -3,44 +3,94 @@ package website.christine.xesite
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.appwidget.AppWidgetProvider
|
import android.appwidget.AppWidgetProvider
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.widget.LinearLayout
|
import android.util.Log
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
|
import com.android.volley.RequestQueue
|
||||||
|
import com.android.volley.Response
|
||||||
|
import com.android.volley.toolbox.BasicNetwork
|
||||||
|
import com.android.volley.toolbox.DiskBasedCache
|
||||||
|
import com.android.volley.toolbox.HurlStack
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of App Widget functionality.
|
* Implementation of App Widget functionality.
|
||||||
*/
|
*/
|
||||||
class NewPostWidget : AppWidgetProvider() {
|
class NewPostWidget : AppWidgetProvider() {
|
||||||
|
private lateinit var requestQueue: RequestQueue
|
||||||
|
|
||||||
override fun onUpdate(
|
override fun onUpdate(
|
||||||
context: Context,
|
ctx: Context,
|
||||||
appWidgetManager: AppWidgetManager,
|
appWidgetManager: AppWidgetManager,
|
||||||
appWidgetIds: IntArray
|
appWidgetIds: IntArray
|
||||||
) {
|
) {
|
||||||
// There may be multiple widgets active, so update all of them
|
val url = "https://christine.website/.within/website.within.xesite/new_post"
|
||||||
for (appWidgetId in appWidgetIds) {
|
|
||||||
updateAppWidget(context, appWidgetManager, appWidgetId)
|
val jor: GsonGetRequest<NewPost> = GsonGetRequest(
|
||||||
|
url,
|
||||||
|
NewPost::class.java,
|
||||||
|
null,
|
||||||
|
Response.Listener<NewPost> { response ->
|
||||||
|
Log.println(Log.INFO, "new_post", response.toString())
|
||||||
|
// There may be multiple widgets active, so update all of them
|
||||||
|
for (appWidgetId in appWidgetIds) {
|
||||||
|
this.updateAppWidget(ctx, appWidgetManager, appWidgetId, response)
|
||||||
|
}
|
||||||
|
}, Response.ErrorListener { error ->
|
||||||
|
// There may be multiple widgets active, so update all of them
|
||||||
|
for (appWidgetId in appWidgetIds) {
|
||||||
|
this.updateAppWidget(
|
||||||
|
ctx,
|
||||||
|
appWidgetManager,
|
||||||
|
appWidgetId,
|
||||||
|
NewPost("Error", error.toString(), "")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!this::requestQueue.isInitialized) {
|
||||||
|
this.makeQueue(ctx)
|
||||||
|
}
|
||||||
|
this.requestQueue.add(jor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun makeQueue(ctx: Context) {
|
||||||
|
// Instantiate the cache
|
||||||
|
val cache = DiskBasedCache(ctx.cacheDir, 1024 * 1024) // 1MB cap
|
||||||
|
|
||||||
|
// Set up the network to use HttpURLConnection as the HTTP client.
|
||||||
|
val network = BasicNetwork(HurlStack())
|
||||||
|
|
||||||
|
this.requestQueue = RequestQueue(cache, network).apply {
|
||||||
|
start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEnabled(context: Context) {
|
override fun onEnabled(ctx: Context) {
|
||||||
// Enter relevant functionality for when the first widget is created
|
this.makeQueue(ctx)
|
||||||
val views = RemoteViews(context.packageName, R.layout.new_post_widget)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDisabled(context: Context) {
|
override fun onDisabled(context: Context) {
|
||||||
// Enter relevant functionality for when the last widget is disabled
|
// Enter relevant functionality for when the last widget is disabled
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal fun updateAppWidget(
|
private fun updateAppWidget(
|
||||||
context: Context,
|
context: Context,
|
||||||
appWidgetManager: AppWidgetManager,
|
appWidgetManager: AppWidgetManager,
|
||||||
appWidgetId: Int
|
appWidgetId: Int,
|
||||||
) {
|
body: NewPost
|
||||||
// Construct the RemoteViews object
|
) {
|
||||||
val views = RemoteViews(context.packageName, R.layout.new_post_widget)
|
// Construct the RemoteViews object
|
||||||
views.setTextViewText(R.id.article_title, "My Thoughts About Using Android Again as an iPhone User")
|
val views = RemoteViews(context.packageName, R.layout.new_post_widget)
|
||||||
views.setTextViewText(R.id.appwidget_text2, "I used to be a hardcore Android user. It was my second major kind of smartphone (the first was Windows Mobile 6.1 on a T-Mobile Dash) and it left me hooked to the concept of smartphones and connected tech in general.")
|
|
||||||
|
|
||||||
// Instruct the widget manager to update the widget
|
views.setTextViewText(
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
R.id.article_title,
|
||||||
|
body.title
|
||||||
|
)
|
||||||
|
views.setTextViewText(
|
||||||
|
R.id.article_preview,
|
||||||
|
body.summary
|
||||||
|
)
|
||||||
|
|
||||||
|
// Instruct the widget manager to update the widget
|
||||||
|
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -10,12 +10,12 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="horizontal">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="92dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="109dp"
|
||||||
android:orientation="vertical">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageView"
|
android:id="@+id/imageView"
|
||||||
|
@ -23,22 +23,6 @@
|
||||||
android:layout_height="75dp"
|
android:layout_height="75dp"
|
||||||
android:src="@drawable/splash" />
|
android:src="@drawable/splash" />
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="67dp"
|
|
||||||
android:text="Button" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/parent_article"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="auto"
|
|
||||||
android:onClick="clickButton"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/article_title"
|
android:id="@+id/article_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -54,23 +38,22 @@
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold|italic" />
|
android:textStyle="bold|italic" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/appwidget_text2"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginTop="0dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="@color/backgroundColor"
|
|
||||||
android:contentDescription="@string/appwidget_body_preview"
|
|
||||||
android:text="@string/appwidget_body_preview"
|
|
||||||
android:textColor="#282828"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="italic" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/article_preview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="117dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="0dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:background="@color/backgroundColor"
|
||||||
|
android:contentDescription="@string/appwidget_body_preview"
|
||||||
|
android:text="@string/appwidget_body_preview"
|
||||||
|
android:textColor="#282828"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
|
@ -6,5 +6,5 @@
|
||||||
android:minHeight="80dp"
|
android:minHeight="80dp"
|
||||||
android:previewImage="@drawable/example_appwidget_preview"
|
android:previewImage="@drawable/example_appwidget_preview"
|
||||||
android:resizeMode="horizontal|vertical"
|
android:resizeMode="horizontal|vertical"
|
||||||
android:updatePeriodMillis="1800000"
|
android:updatePeriodMillis="28800000"
|
||||||
android:widgetCategory="home_screen"></appwidget-provider>
|
android:widgetCategory="home_screen"></appwidget-provider>
|
Loading…
Reference in New Issue