-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from instana/INSTA-12431_adding_widget
[INSTA-12431]Added widget to app
- Loading branch information
Showing
8 changed files
with
231 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
155 changes: 155 additions & 0 deletions
155
...id-compose-robotshop/app/src/main/java/com/ibm/instashop/widget/RoboShopWidgetProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package com.ibm.instashop.widget | ||
|
||
import android.app.PendingIntent | ||
import android.appwidget.AppWidgetManager | ||
import android.appwidget.AppWidgetProvider | ||
import android.content.ComponentName | ||
import android.content.Context | ||
import android.content.Intent | ||
import android.content.SharedPreferences | ||
import android.graphics.Bitmap | ||
import android.widget.RemoteViews | ||
import androidx.work.Constraints | ||
import androidx.work.ExistingWorkPolicy | ||
import androidx.work.OneTimeWorkRequest | ||
import androidx.work.WorkManager | ||
import com.bumptech.glide.Glide | ||
import com.google.gson.Gson | ||
import com.ibm.instashop.R | ||
import com.ibm.instashop.business_unit.models.ProductItem | ||
import com.instana.android.core.event.worker.EventWorker | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.GlobalScope | ||
import kotlinx.coroutines.launch | ||
import kotlinx.coroutines.withContext | ||
import java.net.HttpURLConnection | ||
import java.net.URL | ||
import java.util.concurrent.TimeUnit | ||
import kotlin.random.Random | ||
|
||
|
||
class SharedPreferencesHelper(context: Context) { | ||
|
||
private val sharedPreferences: SharedPreferences = | ||
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) | ||
|
||
companion object { | ||
private const val PREFS_NAME = "robotshop_prefs" | ||
private const val KEY_TITLE_STRING = "example_string_title" | ||
const val KEY_URL_STRING = "example_string_title" | ||
private const val KEY_EXAMPLE_BOOLEAN = "example_boolean" | ||
} | ||
fun saveString(value: String,key: String=KEY_TITLE_STRING) = sharedPreferences.edit().putString(key, value).apply() | ||
fun getString(key: String = KEY_TITLE_STRING)= sharedPreferences.getString(KEY_TITLE_STRING, null) | ||
fun saveBoolean(value: Boolean) = sharedPreferences.edit().putBoolean(KEY_EXAMPLE_BOOLEAN, value).apply() | ||
// if you need to see flickering then you can uninstall the app and install again with below default value as true | ||
fun getBoolean() = sharedPreferences.getBoolean(KEY_EXAMPLE_BOOLEAN, false) | ||
} | ||
class RoboShopWidgetProvider: AppWidgetProvider() { | ||
private var bitMap:Bitmap? = null | ||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { | ||
super.onUpdate(context, appWidgetManager, appWidgetIds) | ||
val prefs = SharedPreferencesHelper(context) | ||
if (!prefs.getBoolean()) { | ||
enqueueDelayedWorker(context) | ||
prefs.saveBoolean(true) | ||
} | ||
val sharedPreferencesHelper = SharedPreferencesHelper(context) | ||
val dataFromApi = sharedPreferencesHelper.getString() ?: "No data" | ||
val urlFromData = sharedPreferencesHelper.getString(SharedPreferencesHelper.KEY_URL_STRING) ?: "http://www.google.com" | ||
for (appWidgetId in appWidgetIds) { | ||
val intent = Intent(context, javaClass).apply { | ||
action = ACTION_FETCH_DATA | ||
} | ||
GlobalScope.launch { | ||
bitMap = getBitMap(context,urlFromData) | ||
} | ||
val pendingIntent = PendingIntent.getBroadcast( | ||
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE | ||
) | ||
val views = RemoteViews(context.packageName, R.layout.widget_layout).apply { | ||
setOnClickPendingIntent(R.id.fetchDataBtn, pendingIntent) | ||
setTextViewText(R.id.widget_text,dataFromApi) | ||
setImageViewBitmap(R.id.image,bitMap) | ||
} | ||
appWidgetManager.updateAppWidget(appWidgetId, views) | ||
} | ||
} | ||
|
||
|
||
override fun onReceive(context: Context, intent: Intent) { | ||
super.onReceive(context, intent) | ||
val sharedPreferencesHelper = SharedPreferencesHelper(context) | ||
if (ACTION_FETCH_DATA == intent.action) { | ||
CoroutineScope(Dispatchers.IO).launch { | ||
val result = fetchApiData() | ||
sharedPreferencesHelper.saveString(result.title.take(17)+"...") | ||
sharedPreferencesHelper.saveString(result.image,SharedPreferencesHelper.KEY_URL_STRING) | ||
withContext(Dispatchers.Main) { | ||
updateWidget(context, result) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private suspend fun fetchApiData(): ProductItem { | ||
val url = URL("https://fakestoreapi.com/products/${Random.nextInt(1, 19)}") // Replace with your API endpoint | ||
val connection = url.openConnection() as HttpURLConnection | ||
return try { | ||
val jsonResponse = connection.inputStream.bufferedReader().readText() | ||
Gson().fromJson(jsonResponse, ProductItem::class.java) | ||
} finally { | ||
connection.disconnect() | ||
} | ||
} | ||
|
||
private suspend fun updateWidget(context: Context, result: ProductItem) { | ||
val appWidgetManager = AppWidgetManager.getInstance(context) | ||
val componentName = ComponentName(context, RoboShopWidgetProvider::class.java) | ||
val bitmap: Bitmap = withContext(Dispatchers.IO) { | ||
Glide.with(context) | ||
.asBitmap() | ||
.load(result.image) | ||
.submit(150, 100) | ||
.get() | ||
} | ||
val views = RemoteViews(context.packageName, R.layout.widget_layout).apply { | ||
setTextViewText(R.id.widget_text, result.title.take(17)+"..") | ||
setImageViewBitmap(R.id.image,bitmap) | ||
} | ||
|
||
appWidgetManager.updateAppWidget(componentName, views) | ||
} | ||
|
||
companion object { | ||
const val ACTION_FETCH_DATA = "com.ibm.instashop.widget.ACTION_FETCH_DATA" | ||
} | ||
//This is a workaround to overcome the issue with, WorkManager sending `android.appwidget.action.APPWIDGET_UPDATE` | ||
//after the work is completed each time causing the Widget to update couple of times | ||
//Issue Reference : https://issuetracker.google.com/issues/241076154 | ||
private fun enqueueDelayedWorker(context: Context) { | ||
val workRequest = OneTimeWorkRequest.Builder(EventWorker::class.java) | ||
.setInitialDelay(5 * 365, TimeUnit.DAYS) | ||
.setConstraints(Constraints.Builder().setRequiresCharging(true).build()) | ||
.build() | ||
|
||
WorkManager.getInstance(context).enqueueUniqueWork( | ||
"appWidgetWorkerKeepEnabled", | ||
ExistingWorkPolicy.KEEP, | ||
workRequest | ||
) | ||
} | ||
|
||
|
||
private suspend fun getBitMap(context: Context, url:String):Bitmap{ | ||
return withContext(Dispatchers.IO) { | ||
Glide.with(context) | ||
.asBitmap() | ||
.load(url) | ||
.submit(150, 100) | ||
.get() | ||
} | ||
} | ||
|
||
} |
5 changes: 5 additions & 0 deletions
5
android-compose-robotshop/app/src/main/res/drawable/widget_image.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<vector android:height="80dp" android:tint="#C125A77E" | ||
android:viewportHeight="24" android:viewportWidth="24" | ||
android:width="80dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<path android:fillColor="@android:color/white" android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/> | ||
</vector> |
34 changes: 34 additions & 0 deletions
34
android-compose-robotshop/app/src/main/res/layout/widget_layout.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | ||
android:orientation="vertical" | ||
android:padding="16dp" | ||
android:background="#FFFFFF"> | ||
|
||
<ImageView | ||
android:id="@+id/image" | ||
android:layout_width="150dp" | ||
android:layout_height="99dp" | ||
android:background="@color/white" | ||
android:src="@drawable/widget_image" | ||
android:scaleType="fitCenter"/> | ||
|
||
<TextView | ||
android:id="@+id/widget_text" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:text="" | ||
android:maxLines="1" | ||
android:gravity="center" | ||
android:textColor="#FF0000" | ||
android:textSize="14sp" | ||
android:textStyle="bold"/> | ||
|
||
<Button | ||
android:id="@+id/fetchDataBtn" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:textColor="@color/white" | ||
android:background="@color/teal_700" | ||
android:text="Load Offers"/> | ||
</LinearLayout> |
5 changes: 5 additions & 0 deletions
5
android-compose-robotshop/app/src/main/res/xml/widget_info.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:initialLayout="@layout/widget_layout" | ||
android:minWidth="250dp" | ||
android:minHeight="100dp"/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters