diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index 0c4927bcc..0a64ad4a7 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
+
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 7376d7788..751587def 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -19,6 +19,9 @@
+
+
+
+
+
+
+
+
+
+
() {
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ Log.d(TAG, "Starting to fetch Bitcoin price...");
+ }
+
+ @Override
+ protected String doInBackground(Void... voids) {
+ try {
+ Log.d(TAG, "Creating URI...");
+ URI uri = new URI("https://api.kraken.com/0/public/Ticker?pair=XBTUSD");
+ URL url = uri.toURL();
+ Log.d(TAG, "Opening connection to URL: " + url);
+ HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+ urlConnection.setRequestMethod("GET");
+ urlConnection.connect();
+
+ int responseCode = urlConnection.getResponseCode();
+ Log.d(TAG, "Response code: " + responseCode);
+ if (responseCode != 200) {
+ Log.e(TAG, "Failed to fetch Bitcoin price. Response code: " + responseCode);
+ return null;
+ }
+
+ InputStreamReader reader = new InputStreamReader(urlConnection.getInputStream());
+ StringBuilder json = new StringBuilder();
+ int read;
+ char[] buffer = new char[1024];
+ while ((read = reader.read(buffer)) != -1) {
+ json.append(buffer, 0, read);
+ }
+
+ Log.d(TAG, "JSON response: " + json.toString());
+ JSONObject jsonObject = new JSONObject(json.toString());
+ JSONObject resultObject = jsonObject.getJSONObject("result");
+ JSONObject xbtusdObject = resultObject.getJSONObject("XXBTZUSD");
+ JSONArray priceArray = xbtusdObject.getJSONArray("c");
+ String price = priceArray.getString(0);
+ return price;
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while fetching Bitcoin price", e);
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(String price) {
+ RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
+ SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
+ String prevPrice = prefs.getString(PREF_PREFIX_KEY + appWidgetId, null);
+ SharedPreferences.Editor editor = prefs.edit();
+
+ if (price != null) {
+ Log.d(TAG, "Fetch completed with price: " + price);
+ NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(Locale.US);
+ views.setTextViewText(R.id.price_value, currencyFormat.format(Double.parseDouble(price)));
+
+ if (prevPrice != null) {
+ double previousPrice = Double.parseDouble(prevPrice);
+ double currentPrice = Double.parseDouble(price);
+ if (currentPrice > previousPrice) {
+ views.setImageViewResource(R.id.price_arrow, android.R.drawable.arrow_up_float);
+ } else if (currentPrice < previousPrice) {
+ views.setImageViewResource(R.id.price_arrow, android.R.drawable.arrow_down_float);
+ } else {
+ views.setImageViewResource(R.id.price_arrow, 0);
+ }
+ views.setTextViewText(R.id.previous_price, "from " + currencyFormat.format(previousPrice));
+ } else {
+ views.setImageViewResource(R.id.price_arrow, 0);
+ views.setTextViewText(R.id.previous_price, "");
+ }
+
+ editor.putString(PREF_PREFIX_KEY + appWidgetId, price);
+ editor.apply();
+
+ String currentTime = new SimpleDateFormat("hh:mm a", Locale.getDefault()).format(new Date());
+ views.setTextViewText(R.id.last_updated, "Last Updated");
+ views.setTextViewText(R.id.last_updated_time, currentTime);
+
+ if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) {
+ views.setTextColor(R.id.last_updated, context.getResources().getColor(android.R.color.white));
+ views.setTextColor(R.id.last_updated_time, context.getResources().getColor(android.R.color.white));
+ views.setTextColor(R.id.price_value, context.getResources().getColor(android.R.color.white));
+ views.setTextColor(R.id.previous_price, context.getResources().getColor(android.R.color.white));
+ views.setInt(R.id.widget_layout, "setBackgroundColor", context.getResources().getColor(android.R.color.black));
+ } else {
+ views.setTextColor(R.id.last_updated, context.getResources().getColor(android.R.color.black));
+ views.setTextColor(R.id.last_updated_time, context.getResources().getColor(android.R.color.black));
+ views.setTextColor(R.id.price_value, context.getResources().getColor(android.R.color.black));
+ views.setTextColor(R.id.previous_price, context.getResources().getColor(android.R.color.black));
+ views.setInt(R.id.widget_layout, "setBackgroundColor", context.getResources().getColor(android.R.color.white));
+ }
+ } else {
+ String errorMessage = "Network Error";
+ Log.e(TAG, errorMessage);
+ views.setTextViewText(R.id.price_value, errorMessage);
+ views.setTextViewText(R.id.last_updated, "");
+ views.setTextViewText(R.id.last_updated_time, "");
+ views.setImageViewResource(R.id.price_arrow, 0);
+ views.setTextViewText(R.id.previous_price, "");
+ Toast.makeText(context, "Failed to fetch Bitcoin price", Toast.LENGTH_SHORT).show();
+ }
+ appWidgetManager.updateAppWidget(appWidgetId, views);
+ }
+ }.execute();
+ }
+}
diff --git a/android/app/src/main/res/drawable/widget_preview.png b/android/app/src/main/res/drawable/widget_preview.png
new file mode 100644
index 000000000..fdf7b30b4
Binary files /dev/null and b/android/app/src/main/res/drawable/widget_preview.png differ
diff --git a/android/app/src/main/res/layout/widget_layout.xml b/android/app/src/main/res/layout/widget_layout.xml
new file mode 100644
index 000000000..adbfcf041
--- /dev/null
+++ b/android/app/src/main/res/layout/widget_layout.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/xml/bitcoin_price_widget_info.xml b/android/app/src/main/res/xml/bitcoin_price_widget_info.xml
new file mode 100644
index 000000000..2fe13a508
--- /dev/null
+++ b/android/app/src/main/res/xml/bitcoin_price_widget_info.xml
@@ -0,0 +1,11 @@
+
+