mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2024-11-19 01:40:12 +01:00
Merge branch 'master' into modal
This commit is contained in:
commit
dcb940b0c7
@ -84,6 +84,12 @@ android {
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
assets.srcDirs = ['src/main/assets', 'src/main/res/assets']
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// Caution! In production, you need to generate your own keystore file.
|
||||
@ -95,6 +101,13 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
task copyFiatUnits(type: Copy) {
|
||||
from '../../models/fiatUnits.json'
|
||||
into 'src/main/assets'
|
||||
}
|
||||
|
||||
preBuild.dependsOn(copyFiatUnits)
|
||||
|
||||
dependencies {
|
||||
// The version of react-native is set by the React Native Gradle Plugin
|
||||
implementation("com.facebook.react:react-android")
|
||||
@ -110,6 +123,7 @@ dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation "androidx.work:work-runtime:2.7.1"
|
||||
}
|
||||
apply plugin: 'com.google.gms.google-services' // Google Services plugin
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning">
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
|
@ -19,10 +19,10 @@
|
||||
<uses-permission android:name="android.permission.ACTION_OPEN_DOCUMENT" />
|
||||
<uses-permission android:name="android.permission.ACTION_GET_CONTENT" />
|
||||
<uses-permission android:name="android.permission.ACTION_CREATE_DOCUMENT" />
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.ACTION_SCREEN_OFF"/>
|
||||
<uses-permission android:name="android.permission.ACTION_SCREEN_ON"/>
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
android:label="@string/app_name"
|
||||
@ -61,19 +61,18 @@
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".BitcoinPriceWidget"
|
||||
android:exported="true"
|
||||
android:label="Bitcoin Price Widget">
|
||||
|
||||
<receiver android:name=".BitcoinPriceWidget" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
<action android:name="android.intent.action.SCREEN_ON"/>
|
||||
<action android:name="android.intent.action.SCREEN_OFF"/>
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/bitcoin_price_widget_info" />
|
||||
android:resource="@xml/bitcoin_price_widget_info"/>
|
||||
</receiver>
|
||||
|
||||
|
||||
<service
|
||||
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
|
||||
android:exported="false">
|
||||
|
408
android/app/src/main/assets/fiatUnits.json
Normal file
408
android/app/src/main/assets/fiatUnits.json
Normal file
@ -0,0 +1,408 @@
|
||||
{
|
||||
"USD": {
|
||||
"endPointKey": "USD",
|
||||
"locale": "en-US",
|
||||
"source": "Kraken",
|
||||
"symbol": "$",
|
||||
"country": "United States (US Dollar)"
|
||||
},
|
||||
"AED": {
|
||||
"endPointKey": "AED",
|
||||
"locale": "ar-AE",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "د.إ.",
|
||||
"country": "United Arab Emirates (UAE Dirham)"
|
||||
},
|
||||
"ANG": {
|
||||
"endPointKey": "ANG",
|
||||
"locale": "en-SX",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "ƒ",
|
||||
"country": "Sint Maarten (Netherlands Antillean Guilder)"
|
||||
},
|
||||
"ARS": {
|
||||
"endPointKey": "ARS",
|
||||
"locale": "es-AR",
|
||||
"source": "Yadio",
|
||||
"symbol": "$",
|
||||
"country": "Argentina (Argentine Peso)"
|
||||
},
|
||||
"AUD": {
|
||||
"endPointKey": "AUD",
|
||||
"locale": "en-AU",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "$",
|
||||
"country": "Australia (Australian Dollar)"
|
||||
},
|
||||
"AWG": {
|
||||
"endPointKey": "AWG",
|
||||
"locale": "nl-AW",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "ƒ",
|
||||
"country": "Aruba (Aruban Florin)"
|
||||
},
|
||||
"BHD": {
|
||||
"endPointKey": "BHD",
|
||||
"locale": "ar-BH",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "د.ب.",
|
||||
"country": "Bahrain (Bahraini Dinar)"
|
||||
},
|
||||
"BRL": {
|
||||
"endPointKey": "BRL",
|
||||
"locale": "pt-BR",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "R$",
|
||||
"country": "Brazil (Brazilian Real)"
|
||||
},
|
||||
"CAD": {
|
||||
"endPointKey": "CAD",
|
||||
"locale": "en-CA",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "$",
|
||||
"country": "Canada (Canadian Dollar)"
|
||||
},
|
||||
"CHF": {
|
||||
"endPointKey": "CHF",
|
||||
"locale": "de-CH",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "CHF",
|
||||
"country": "Switzerland (Swiss Franc)"
|
||||
},
|
||||
"CLP": {
|
||||
"endPointKey": "CLP",
|
||||
"locale": "es-CL",
|
||||
"source": "Yadio",
|
||||
"symbol": "$",
|
||||
"country": "Chile (Chilean Peso)"
|
||||
},
|
||||
"CNY": {
|
||||
"endPointKey": "CNY",
|
||||
"locale": "zh-CN",
|
||||
"source": "Coinbase",
|
||||
"symbol": "¥",
|
||||
"country": "China (Chinese Yuan)"
|
||||
},
|
||||
"COP": {
|
||||
"endPointKey": "COP",
|
||||
"locale": "es-CO",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "$",
|
||||
"country": "Colombia (Colombian Peso)"
|
||||
},
|
||||
"CZK": {
|
||||
"endPointKey": "CZK",
|
||||
"locale": "cs-CZ",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "Kč",
|
||||
"country": "Czech Republic (Czech Koruna)"
|
||||
},
|
||||
"DKK": {
|
||||
"endPointKey": "DKK",
|
||||
"locale": "da-DK",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "kr",
|
||||
"country": "Denmark (Danish Krone)"
|
||||
},
|
||||
"EUR": {
|
||||
"endPointKey": "EUR",
|
||||
"locale": "en-IE",
|
||||
"source": "Kraken",
|
||||
"symbol": "€",
|
||||
"country": "European Union (Euro)"
|
||||
},
|
||||
"GBP": {
|
||||
"endPointKey": "GBP",
|
||||
"locale": "en-GB",
|
||||
"source": "Kraken",
|
||||
"symbol": "£",
|
||||
"country": "United Kingdom (British Pound)"
|
||||
},
|
||||
"HRK": {
|
||||
"endPointKey": "HRK",
|
||||
"locale": "hr-HR",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "HRK",
|
||||
"country": "Croatia (Croatian Kuna)"
|
||||
},
|
||||
"HUF": {
|
||||
"endPointKey": "HUF",
|
||||
"locale": "hu-HU",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "Ft",
|
||||
"country": "Hungary (Hungarian Forint)"
|
||||
},
|
||||
"IDR": {
|
||||
"endPointKey": "IDR",
|
||||
"locale": "id-ID",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "Rp",
|
||||
"country": "Indonesia (Indonesian Rupiah)"
|
||||
},
|
||||
"ILS": {
|
||||
"endPointKey": "ILS",
|
||||
"locale": "he-IL",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "₪",
|
||||
"country": "Israel (Israeli New Shekel)"
|
||||
},
|
||||
"INR": {
|
||||
"endPointKey": "INR",
|
||||
"locale": "hi-IN",
|
||||
"source": "wazirx",
|
||||
"symbol": "₹",
|
||||
"country": "India (Indian Rupee)"
|
||||
},
|
||||
"IRR": {
|
||||
"endPointKey": "IRR",
|
||||
"locale": "fa-IR",
|
||||
"source": "Exir",
|
||||
"symbol": "﷼",
|
||||
"country": "Iran (Iranian Rial)"
|
||||
},
|
||||
"IRT": {
|
||||
"endPointKey": "IRT",
|
||||
"locale": "fa-IR",
|
||||
"source": "Exir",
|
||||
"symbol": "تومان",
|
||||
"country": "Iran (Iranian Toman)"
|
||||
},
|
||||
"ISK": {
|
||||
"endPointKey": "ISK",
|
||||
"locale": "is-IS",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "kr",
|
||||
"country": "Iceland (Icelandic Króna)"
|
||||
},
|
||||
"JPY": {
|
||||
"endPointKey": "JPY",
|
||||
"locale": "ja-JP",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "¥",
|
||||
"country": "Japan (Japanese Yen)"
|
||||
},
|
||||
"KES": {
|
||||
"endPointKey": "KES",
|
||||
"locale": "en-KE",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "Ksh",
|
||||
"country": "Kenya (Kenyan Shilling)"
|
||||
},
|
||||
"KRW": {
|
||||
"endPointKey": "KRW",
|
||||
"locale": "ko-KR",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "₩",
|
||||
"country": "South Korea (South Korean Won)"
|
||||
},
|
||||
"KWD": {
|
||||
"endPointKey": "KWD",
|
||||
"locale": "ar-KW",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "د.ك.",
|
||||
"country": "Kuwait (Kuwaiti Dinar)"
|
||||
},
|
||||
"LBP": {
|
||||
"endPointKey": "LBP",
|
||||
"locale": "ar-LB",
|
||||
"source": "YadioConvert",
|
||||
"symbol": "ل.ل.",
|
||||
"country": "Lebanon (Lebanese Pound)"
|
||||
},
|
||||
"LKR": {
|
||||
"endPointKey": "LKR",
|
||||
"locale": "si-LK",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "රු.",
|
||||
"country": "Sri Lanka (Sri Lankan Rupee)"
|
||||
},
|
||||
"MXN": {
|
||||
"endPointKey": "MXN",
|
||||
"locale": "es-MX",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "$",
|
||||
"country": "Mexico (Mexican Peso)"
|
||||
},
|
||||
"MYR": {
|
||||
"endPointKey": "MYR",
|
||||
"locale": "ms-MY",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "RM",
|
||||
"country": "Malaysia (Malaysian Ringgit)"
|
||||
},
|
||||
"MZN": {
|
||||
"endPointKey": "MZN",
|
||||
"locale": "seh-MZ",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "MTn",
|
||||
"country": "Mozambique (Mozambican Metical)"
|
||||
},
|
||||
"NGN": {
|
||||
"endPointKey": "NGN",
|
||||
"locale": "en-NG",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "₦",
|
||||
"country": "Nigeria (Nigerian Naira)"
|
||||
},
|
||||
"NOK": {
|
||||
"endPointKey": "NOK",
|
||||
"locale": "nb-NO",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "kr",
|
||||
"country": "Norway (Norwegian Krone)"
|
||||
},
|
||||
"NZD": {
|
||||
"endPointKey": "NZD",
|
||||
"locale": "en-NZ",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "$",
|
||||
"country": "New Zealand (New Zealand Dollar)"
|
||||
},
|
||||
"OMR": {
|
||||
"endPointKey": "OMR",
|
||||
"locale": "ar-OM",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "ر.ع.",
|
||||
"country": "Oman (Omani Rial)"
|
||||
},
|
||||
"PHP": {
|
||||
"endPointKey": "PHP",
|
||||
"locale": "en-PH",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "₱",
|
||||
"country": "Philippines (Philippine Peso)"
|
||||
},
|
||||
"PLN": {
|
||||
"endPointKey": "PLN",
|
||||
"locale": "pl-PL",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "zł",
|
||||
"country": "Poland (Polish Zloty)"
|
||||
},
|
||||
"QAR": {
|
||||
"endPointKey": "QAR",
|
||||
"locale": "ar-QA",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "ر.ق.",
|
||||
"country": "Qatar (Qatari Riyal)"
|
||||
},
|
||||
"RON": {
|
||||
"endPointKey": "RON",
|
||||
"locale": "ro-RO",
|
||||
"source": "BNR",
|
||||
"symbol": "lei",
|
||||
"country": "Romania (Romanian Leu)"
|
||||
},
|
||||
"RUB": {
|
||||
"endPointKey": "RUB",
|
||||
"locale": "ru-RU",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "₽",
|
||||
"country": "Russia (Russian Ruble)"
|
||||
},
|
||||
"SAR": {
|
||||
"endPointKey": "SAR",
|
||||
"locale": "ar-SA",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "ر.س.",
|
||||
"country": "Saudi Arabia (Saudi Riyal)"
|
||||
},
|
||||
"SEK": {
|
||||
"endPointKey": "SEK",
|
||||
"locale": "sv-SE",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "kr",
|
||||
"country": "Sweden (Swedish Krona)"
|
||||
},
|
||||
"SGD": {
|
||||
"endPointKey": "SGD",
|
||||
"locale": "zh-SG",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "S$",
|
||||
"country": "Singapore (Singapore Dollar)"
|
||||
},
|
||||
"THB": {
|
||||
"endPointKey": "THB",
|
||||
"locale": "th-TH",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "฿",
|
||||
"country": "Thailand (Thai Baht)"
|
||||
},
|
||||
"TRY": {
|
||||
"endPointKey": "TRY",
|
||||
"locale": "tr-TR",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "₺",
|
||||
"country": "Turkey (Turkish Lira)"
|
||||
},
|
||||
"TWD": {
|
||||
"endPointKey": "TWD",
|
||||
"locale": "zh-Hant-TW",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "NT$",
|
||||
"country": "Taiwan (New Taiwan Dollar)"
|
||||
},
|
||||
"TZS": {
|
||||
"endPointKey": "TZS",
|
||||
"locale": "en-TZ",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "TSh",
|
||||
"country": "Tanzania (Tanzanian Shilling)"
|
||||
},
|
||||
"UAH": {
|
||||
"endPointKey": "UAH",
|
||||
"locale": "uk-UA",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "₴",
|
||||
"country": "Ukraine (Ukrainian Hryvnia)"
|
||||
},
|
||||
"UGX": {
|
||||
"endPointKey": "UGX",
|
||||
"locale": "en-UG",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "USh",
|
||||
"country": "Uganda (Ugandan Shilling)"
|
||||
},
|
||||
"UYU": {
|
||||
"endPointKey": "UYU",
|
||||
"locale": "es-UY",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "$",
|
||||
"country": "Uruguay (Uruguayan Peso)"
|
||||
},
|
||||
"VEF": {
|
||||
"endPointKey": "VEF",
|
||||
"locale": "es-VE",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "Bs.",
|
||||
"country": "Venezuela (Venezuelan Bolívar Fuerte)"
|
||||
},
|
||||
"VES": {
|
||||
"endPointKey": "VES",
|
||||
"locale": "es-VE",
|
||||
"source": "Yadio",
|
||||
"symbol": "Bs.",
|
||||
"country": "Venezuela (Venezuelan Bolívar Soberano)"
|
||||
},
|
||||
"XAF": {
|
||||
"endPointKey": "XAF",
|
||||
"locale": "fr-CF",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "Fr",
|
||||
"country": "Central African Republic (Central African Franc)"
|
||||
},
|
||||
"ZAR": {
|
||||
"endPointKey": "ZAR",
|
||||
"locale": "en-ZA",
|
||||
"source": "CoinGecko",
|
||||
"symbol": "R",
|
||||
"country": "South Africa (South African Rand)"
|
||||
},
|
||||
"GHS": {
|
||||
"endPointKey": "GHS",
|
||||
"locale": "en-GH",
|
||||
"source": "CoinDesk",
|
||||
"symbol": "₵",
|
||||
"country": "Ghana (Ghanaian Cedi)"
|
||||
}
|
||||
}
|
@ -1,189 +1,125 @@
|
||||
package io.bluewallet.bluewallet;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Application;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import androidx.work.ExistingPeriodicWorkPolicy;
|
||||
import androidx.work.PeriodicWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BitcoinPriceWidget extends AppWidgetProvider {
|
||||
|
||||
private static final String TAG = "BitcoinPriceWidget";
|
||||
private static final String ACTION_UPDATE = "io.bluewallet.bluewallet.UPDATE";
|
||||
private static final String PREFS_NAME = "BitcoinPriceWidgetPrefs";
|
||||
private static final String PREF_PREFIX_KEY = "appwidget_";
|
||||
private static final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
private static final String ACTION_UPDATE = "io.bluewallet.bluewallet.UPDATE_WIDGET";
|
||||
private static final long UPDATE_INTERVAL_MINUTES = 15; // Update interval in minutes
|
||||
private static final int MAX_RETRIES = 3;
|
||||
|
||||
private static PowerManager.WakeLock wakeLock;
|
||||
private static int retryCount = 0;
|
||||
private static boolean isScreenOn = true;
|
||||
|
||||
@Override
|
||||
public void onEnabled(Context context) {
|
||||
super.onEnabled(context);
|
||||
scheduleNextUpdate(context);
|
||||
registerScreenReceiver(context);
|
||||
schedulePeriodicUpdates(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisabled(Context context) {
|
||||
super.onDisabled(context);
|
||||
cancelUpdate(context);
|
||||
executorService.shutdown();
|
||||
unregisterScreenReceiver(context);
|
||||
WorkManager.getInstance(context).cancelUniqueWork("UpdateWidgetWork");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
Log.d(TAG, "Updating widget ID: " + appWidgetId);
|
||||
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
|
||||
|
||||
// Set up the pending intent to open the app when the widget is clicked
|
||||
Intent launchAppIntent = new Intent(context, MainActivity.class);
|
||||
PendingIntent launchAppPendingIntent = PendingIntent.getActivity(context, 0, launchAppIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
views.setOnClickPendingIntent(R.id.widget_layout, launchAppPendingIntent);
|
||||
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
|
||||
executorService.execute(new FetchBitcoinPriceTask(context, appWidgetManager, appWidgetId));
|
||||
}
|
||||
|
||||
scheduleNextUpdate(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
super.onReceive(context, intent);
|
||||
if (ACTION_UPDATE.equals(intent.getAction())) {
|
||||
Log.d(TAG, "Received update action");
|
||||
|
||||
ComponentName widget = new ComponentName(context, BitcoinPriceWidget.class);
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(widget);
|
||||
onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
if (isScreenOn) {
|
||||
scheduleWork(context);
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleNextUpdate(Context context) {
|
||||
Intent intent = new Intent(context, BitcoinPriceWidget.class);
|
||||
intent.setAction(ACTION_UPDATE);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
private void schedulePeriodicUpdates(Context context) {
|
||||
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(WidgetUpdateWorker.class,
|
||||
UPDATE_INTERVAL_MINUTES, TimeUnit.MINUTES)
|
||||
.setInitialDelay(UPDATE_INTERVAL_MINUTES, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||
try {
|
||||
alarmManager.setExact(AlarmManager.RTC, System.currentTimeMillis() + 300000, pendingIntent);
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Permission not granted for setting exact alarms", e);
|
||||
}
|
||||
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
|
||||
"UpdateWidgetWork",
|
||||
ExistingPeriodicWorkPolicy.REPLACE,
|
||||
workRequest
|
||||
);
|
||||
}
|
||||
|
||||
private void cancelUpdate(Context context) {
|
||||
Intent intent = new Intent(context, BitcoinPriceWidget.class);
|
||||
intent.setAction(ACTION_UPDATE);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
|
||||
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||
alarmManager.cancel(pendingIntent);
|
||||
private void registerScreenReceiver(Context context) {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_SCREEN_ON);
|
||||
filter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||
context.getApplicationContext().registerReceiver(screenReceiver, filter);
|
||||
}
|
||||
|
||||
private static class FetchBitcoinPriceTask implements Runnable {
|
||||
private final WeakReference<Context> contextRef;
|
||||
private final AppWidgetManager appWidgetManager;
|
||||
private final int appWidgetId;
|
||||
|
||||
FetchBitcoinPriceTask(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
this.contextRef = new WeakReference<>(context);
|
||||
this.appWidgetManager = appWidgetManager;
|
||||
this.appWidgetId = appWidgetId;
|
||||
}
|
||||
private void unregisterScreenReceiver(Context context) {
|
||||
context.getApplicationContext().unregisterReceiver(screenReceiver);
|
||||
}
|
||||
|
||||
private final BroadcastReceiver screenReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void run() {
|
||||
Context context = contextRef.get();
|
||||
if (context == null) return;
|
||||
|
||||
Log.d(TAG, "Starting to fetch Bitcoin price...");
|
||||
|
||||
String price = MarketAPI.fetchPrice("USD"); // Using hardcoded "USD" for now
|
||||
|
||||
if (price != null) {
|
||||
updateWidgetWithPrice(context, price);
|
||||
} else {
|
||||
handleError(context);
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction() != null) {
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
if (pm != null) {
|
||||
switch (intent.getAction()) {
|
||||
case Intent.ACTION_SCREEN_ON:
|
||||
isScreenOn = true;
|
||||
Log.d(TAG, "Screen ON");
|
||||
acquireWakeLock(context);
|
||||
scheduleWork(context);
|
||||
break;
|
||||
case Intent.ACTION_SCREEN_OFF:
|
||||
isScreenOn = false;
|
||||
Log.d(TAG, "Screen OFF");
|
||||
releaseWakeLock();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void updateWidgetWithPrice(Context context, 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();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (currentPrice != previousPrice) {
|
||||
views.setTextViewText(R.id.previous_price, "from " + currencyFormat.format(previousPrice));
|
||||
views.setViewVisibility(R.id.price_arrow, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.previous_price, View.VISIBLE);
|
||||
} else {
|
||||
views.setTextViewText(R.id.previous_price, "");
|
||||
views.setViewVisibility(R.id.price_arrow, View.GONE);
|
||||
views.setViewVisibility(R.id.previous_price, View.GONE);
|
||||
}
|
||||
} else {
|
||||
views.setImageViewResource(R.id.price_arrow, 0);
|
||||
views.setTextViewText(R.id.previous_price, "");
|
||||
views.setViewVisibility(R.id.price_arrow, View.GONE);
|
||||
views.setViewVisibility(R.id.previous_price, View.GONE);
|
||||
private void acquireWakeLock(Context context) {
|
||||
if (wakeLock == null) {
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
if (pm != null) {
|
||||
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||
wakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
}
|
||||
|
||||
private void handleError(Context context) {
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
|
||||
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, "");
|
||||
views.setViewVisibility(R.id.price_arrow, View.GONE);
|
||||
views.setViewVisibility(R.id.previous_price, View.GONE);
|
||||
Toast.makeText(context, "Failed to fetch Bitcoin price", Toast.LENGTH_SHORT).show();
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseWakeLock() {
|
||||
if (wakeLock != null && wakeLock.isHeld()) {
|
||||
wakeLock.release();
|
||||
wakeLock = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleWork(Context context) {
|
||||
Log.d(TAG, "Scheduling work for widget update");
|
||||
WorkManager.getInstance(context).enqueue(WidgetUpdateWorker.createWorkRequest());
|
||||
}
|
||||
}
|
@ -16,64 +16,70 @@ import com.facebook.soloader.SoLoader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||
import java.util.List;
|
||||
import androidx.work.ExistingPeriodicWorkPolicy;
|
||||
import androidx.work.PeriodicWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
|
||||
private final ReactNativeHost mReactNativeHost =
|
||||
new DefaultReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
private final ReactNativeHost mReactNativeHost =
|
||||
new DefaultReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
return packages;
|
||||
}
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||
return packages;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
@Override
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNewArchEnabled() {
|
||||
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
}
|
||||
@Override
|
||||
protected boolean isNewArchEnabled() {
|
||||
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean isHermesEnabled() {
|
||||
return BuildConfig.IS_HERMES_ENABLED;
|
||||
}
|
||||
};
|
||||
@Override
|
||||
protected Boolean isHermesEnabled() {
|
||||
return BuildConfig.IS_HERMES_ENABLED;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance();
|
||||
sharedI18nUtilInstance.allowRTL(getApplicationContext(), true);
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||
DefaultNewArchitectureEntryPoint.load();
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
SharedPreferences sharedPref = getApplicationContext().getSharedPreferences("group.io.bluewallet.bluewallet", Context.MODE_PRIVATE);
|
||||
|
||||
// Retrieve the "donottrack" value. Default to "0" if not found.
|
||||
String isDoNotTrackEnabled = sharedPref.getString("donottrack", "0");
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance();
|
||||
sharedI18nUtilInstance.allowRTL(getApplicationContext(), true);
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
DefaultNewArchitectureEntryPoint.load();
|
||||
}
|
||||
|
||||
SharedPreferences sharedPref = getApplicationContext().getSharedPreferences("group.io.bluewallet.bluewallet", Context.MODE_PRIVATE);
|
||||
String isDoNotTrackEnabled = sharedPref.getString("donottrack", "0");
|
||||
|
||||
if (!isDoNotTrackEnabled.equals("1")) {
|
||||
Bugsnag.start(this);
|
||||
}
|
||||
|
||||
|
||||
// Schedule periodic widget updates
|
||||
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(WidgetUpdateWorker.class, 4, TimeUnit.MINUTES).build();
|
||||
WorkManager.getInstance(this).enqueueUniquePeriodicWork("UpdateWidgetWork", ExistingPeriodicWorkPolicy.REPLACE, workRequest);
|
||||
|
||||
// Check if do not track is not enabled and initialize Bugsnag if so
|
||||
if (!isDoNotTrackEnabled.equals("1")) {
|
||||
// Initialize Bugsnag or your error tracking here
|
||||
Bugsnag.start(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
package io.bluewallet.bluewallet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@ -10,6 +13,7 @@ import java.net.URL;
|
||||
|
||||
public class MarketAPI {
|
||||
|
||||
private static final String TAG = "MarketAPI";
|
||||
private static final String HARD_CODED_JSON = "{\n" +
|
||||
" \"USD\": {\n" +
|
||||
" \"endPointKey\": \"USD\",\n" +
|
||||
@ -20,7 +24,7 @@ public class MarketAPI {
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
public static String fetchPrice(String currency) {
|
||||
public static String fetchPrice(Context context, String currency) {
|
||||
try {
|
||||
JSONObject json = new JSONObject(HARD_CODED_JSON);
|
||||
JSONObject currencyInfo = json.getJSONObject(currency);
|
||||
@ -28,6 +32,7 @@ public class MarketAPI {
|
||||
String endPointKey = currencyInfo.getString("endPointKey");
|
||||
|
||||
String urlString = buildURLString(source, endPointKey);
|
||||
Log.d(TAG, "Fetching from URL: " + urlString);
|
||||
URI uri = new URI(urlString);
|
||||
URL url = uri.toURL();
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
||||
|
@ -0,0 +1,80 @@
|
||||
package io.bluewallet.bluewallet;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
import androidx.work.Worker;
|
||||
import androidx.work.WorkerParameters;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class WidgetUpdateManager extends Worker {
|
||||
private static final String TAG = "WidgetUpdateManager";
|
||||
private static final String PREFS_NAME = "BitcoinPriceWidgetPrefs";
|
||||
private static final String PREF_PREFIX_KEY = "appwidget_";
|
||||
private static final String PREFS_LAST_UPDATE_TIME_KEY = "lastUpdateTime_";
|
||||
private static final String PREFS_LAST_PRICE_KEY = "lastPrice_";
|
||||
private static final String PREFS_PREV_PRICE_KEY = "prevPrice_";
|
||||
private static final String PREFS_PREV_UPDATE_TIME_KEY = "prevUpdateTime_";
|
||||
|
||||
public WidgetUpdateManager(Context context, WorkerParameters params) {
|
||||
super(context, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result doWork() {
|
||||
Context context = getApplicationContext();
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, BitcoinPriceWidget.class));
|
||||
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
|
||||
String previousPrice = prefs.getString(PREFS_PREV_PRICE_KEY + appWidgetId, "N/A");
|
||||
String lastPrice = prefs.getString(PREFS_LAST_PRICE_KEY + appWidgetId, "N/A");
|
||||
String lastUpdateTime = prefs.getString(PREFS_LAST_UPDATE_TIME_KEY + appWidgetId, "N/A");
|
||||
String previousUpdateTime = prefs.getString(PREFS_PREV_UPDATE_TIME_KEY + appWidgetId, "N/A");
|
||||
|
||||
Log.d(TAG, "Fetch completed with price: " + lastPrice + " at " + lastUpdateTime + ". Previous price: " + previousPrice + " at " + previousUpdateTime);
|
||||
|
||||
String price = MarketAPI.fetchPrice(context, "USD");
|
||||
if (price != null) {
|
||||
Log.d(TAG, "Fetch completed with price: " + price);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString(PREFS_PREV_PRICE_KEY + appWidgetId, lastPrice);
|
||||
editor.putString(PREFS_PREV_UPDATE_TIME_KEY + appWidgetId, lastUpdateTime);
|
||||
editor.putString(PREFS_LAST_PRICE_KEY + appWidgetId, price);
|
||||
editor.putString(PREFS_LAST_UPDATE_TIME_KEY + appWidgetId, DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date()));
|
||||
editor.apply();
|
||||
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
|
||||
views.setTextViewText(R.id.price_value, price);
|
||||
views.setTextViewText(R.id.last_updated_time, DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date()));
|
||||
views.setViewVisibility(R.id.price_value, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.last_updated_label, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.last_updated_time, View.VISIBLE);
|
||||
|
||||
if (!"N/A".equals(previousPrice)) {
|
||||
views.setViewVisibility(R.id.price_arrow_container, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.previous_price, View.VISIBLE);
|
||||
} else {
|
||||
views.setViewVisibility(R.id.price_arrow_container, View.GONE);
|
||||
views.setViewVisibility(R.id.previous_price, View.GONE);
|
||||
}
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
} else {
|
||||
Log.e(TAG, "Failed to fetch Bitcoin price");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package io.bluewallet.bluewallet;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.Worker;
|
||||
import androidx.work.WorkerParameters;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class WidgetUpdateWorker extends Worker {
|
||||
|
||||
private static final String TAG = "WidgetUpdateWorker";
|
||||
private static final String PREFS_NAME = "BitcoinPriceWidgetPrefs";
|
||||
private static final String PREF_PREFIX_KEY_CURRENT = "appwidget_current_";
|
||||
private static final String PREF_PREFIX_KEY_PREVIOUS = "appwidget_previous_";
|
||||
|
||||
public WidgetUpdateWorker(@NonNull Context context, @NonNull WorkerParameters params) {
|
||||
super(context, params);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Result doWork() {
|
||||
Context context = getApplicationContext();
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
ComponentName thisWidget = new ComponentName(context, BitcoinPriceWidget.class);
|
||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
|
||||
String prevPrice = prefs.getString(PREF_PREFIX_KEY_PREVIOUS + appWidgetId, "N/A");
|
||||
String currentPrice = prefs.getString(PREF_PREFIX_KEY_CURRENT + appWidgetId, "N/A");
|
||||
|
||||
Log.d(TAG, "Previous price: " + prevPrice);
|
||||
Log.d(TAG, "Current price: " + currentPrice);
|
||||
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
|
||||
|
||||
// Fetch the latest price
|
||||
String newPrice = MarketAPI.fetchPrice(context, "USD");
|
||||
if (newPrice != null) {
|
||||
String currentTime = new SimpleDateFormat("hh:mm a", Locale.getDefault()).format(new Date());
|
||||
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(Locale.getDefault());
|
||||
|
||||
// Update the widget views
|
||||
views.setTextViewText(R.id.price_value, currencyFormat.format(Double.parseDouble(newPrice)));
|
||||
views.setTextViewText(R.id.last_updated_time, currentTime);
|
||||
views.setViewVisibility(R.id.last_updated_label, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.last_updated_time, View.VISIBLE);
|
||||
|
||||
if (!prevPrice.equals("N/A") && !prevPrice.equals(newPrice)) {
|
||||
views.setViewVisibility(R.id.price_arrow_container, View.VISIBLE);
|
||||
views.setTextViewText(R.id.previous_price, currencyFormat.format(Double.parseDouble(prevPrice)));
|
||||
views.setViewVisibility(R.id.previous_price_label, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.previous_price, View.VISIBLE);
|
||||
if (Double.parseDouble(newPrice) > Double.parseDouble(prevPrice)) {
|
||||
views.setImageViewResource(R.id.price_arrow, android.R.drawable.arrow_up_float);
|
||||
} else {
|
||||
views.setImageViewResource(R.id.price_arrow, android.R.drawable.arrow_down_float);
|
||||
}
|
||||
} else {
|
||||
views.setViewVisibility(R.id.price_arrow_container, View.GONE);
|
||||
views.setViewVisibility(R.id.previous_price_label, View.GONE);
|
||||
views.setViewVisibility(R.id.previous_price, View.GONE);
|
||||
}
|
||||
|
||||
// Save the new price and time
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString(PREF_PREFIX_KEY_PREVIOUS + appWidgetId, currentPrice);
|
||||
editor.putString(PREF_PREFIX_KEY_CURRENT + appWidgetId, newPrice);
|
||||
editor.apply();
|
||||
|
||||
Log.d(TAG, "Fetch completed with price: " + newPrice + " at " + currentTime + ". Previous price: " + prevPrice);
|
||||
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
|
||||
// Log the next update time
|
||||
long nextUpdateTimeMillis = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(4);
|
||||
String nextUpdateTime = new SimpleDateFormat("hh:mm a", Locale.getDefault()).format(new Date(nextUpdateTimeMillis));
|
||||
Log.d(TAG, "Next fetch scheduled at: " + nextUpdateTime);
|
||||
} else {
|
||||
Log.e(TAG, "Failed to fetch Bitcoin price");
|
||||
views.setTextViewText(R.id.price_value, "Error");
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
}
|
||||
}
|
||||
|
||||
public static OneTimeWorkRequest createWorkRequest() {
|
||||
return new OneTimeWorkRequest.Builder(WidgetUpdateWorker.class).build();
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package io.bluewallet.bluewallet;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
public class WidgetUtils {
|
||||
|
||||
public static void updateAppWidget(Context context, RemoteViews views) {
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
ComponentName thisWidget = new ComponentName(context, BitcoinPriceWidget.class);
|
||||
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
|
||||
|
||||
for (int widgetId : allWidgetIds) {
|
||||
appWidgetManager.updateAppWidget(widgetId, views);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,11 +14,11 @@
|
||||
android:gravity="end">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/last_updated"
|
||||
android:id="@+id/last_updated_label"
|
||||
style="@style/WidgetTextSecondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:text="Last Updated:"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginEnd="8dp"/>
|
||||
@ -65,6 +65,16 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/previous_price_label"
|
||||
style="@style/WidgetTextPrimary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="From:"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/previous_price"
|
||||
style="@style/WidgetTextPrimary"
|
||||
@ -76,4 +86,11 @@
|
||||
android:layout_marginBottom="8dp"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loading_indicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"/>
|
||||
</LinearLayout>
|
@ -3,7 +3,7 @@
|
||||
android:initialLayout="@layout/widget_layout"
|
||||
android:minWidth="160dp"
|
||||
android:minHeight="140dp"
|
||||
android:updatePeriodMillis="300000"
|
||||
android:updatePeriodMillis="0"
|
||||
android:widgetCategory="home_screen"
|
||||
android:previewImage="@drawable/widget_preview"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
|
@ -1,7 +1,7 @@
|
||||
#Tue Jul 21 23:04:55 CDT 2020
|
||||
#Wed Jun 26 20:30:20 AST 2024
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
|
||||
networkTimeout=10000
|
Loading…
Reference in New Issue
Block a user