Compare commits

..

12 Commits

94 changed files with 1003 additions and 477 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@
/build
/captures
.externalNativeBuild
/tasksintegration/build

Binary file not shown.

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Tommaso Berlose
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

20
README.md Normal file
View File

@ -0,0 +1,20 @@
<img src="hero.png"/>
Another Widget
========
Another Widget intelligently summarizes the information you need most.
Watch the next events, the weather, and the information you want in an intuitive and elegant way. (Nope, reminders cannot be displayed because it's not allowed.)
While respecting the design of the application, there is a great opportunity to customize the information displayed and widget components.
Also, as much as possible, there are always updates and new features in the short run.
Help me developing with feedback and support me on how you can.
<div style="text-align:center"><a href="https://play.google.com/store/apps/details?id=com.tommasoberlose.anotherwidget" target="_blank"><img src="google-play-badge.png" height="100" /></a></div>
License
-------
Copyright (C) 2017-2020 Tommaso Berlose (http://tommasoberlose.com)
Another Widget binaries and source code can be used according to the [MIT Licence](LICENSE).

View File

@ -18,7 +18,7 @@ android {
applicationId "com.tommasoberlose.anotherwidget"
minSdkVersion 23
targetSdkVersion 29
versionCode 59
versionCode 65
versionName "2.0.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -59,15 +59,14 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// UI
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.2.0-alpha06'
implementation 'androidx.browser:browser:1.2.0'
implementation 'net.idik:slimadapter:2.1.2'
@ -78,6 +77,8 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation "androidx.work:work-runtime-ktx:2.3.4"
// EventBus
implementation 'org.greenrobot:eventbus:3.1.1'
@ -89,6 +90,8 @@ dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'joda-time:joda-time:2.9.9'
implementation 'me.everything:providers-android:1.0.1'
//Glide
implementation 'com.github.bumptech.glide:glide:4.11.0'
kapt 'com.github.bumptech.glide:compiler:4.11.0'
@ -104,6 +107,7 @@ dependencies {
implementation "androidx.core:core-ktx:1.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
implementation "androidx.palette:palette-ktx:1.0.0"
implementation 'androidx.core:core-ktx:1.2.0'
// Recommended: Add the Firebase SDK for Google Analytics.
implementation 'com.google.firebase:firebase-analytics:17.4.0'

Binary file not shown.

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.tommasoberlose.anotherwidget">
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.vending.BILLING" />
@ -16,19 +18,20 @@
android:name=".AWApplication"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main">
android:theme="@style/AppTheme"
tools:ignore="LockedOrientationActivity">
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.activities.ChooseApplicationActivity" android:launchMode="singleInstance" />
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" />
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" />
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" />
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" />
<activity android:name=".ui.activities.ChooseApplicationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
<receiver android:name=".ui.widgets.MainWidget">
@ -67,6 +70,8 @@
<action android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
<action android:name="android.intent.action.DATE_CHANGED" />
<action android:name="android.intent.action.TIME_SET" />
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>
<receiver
@ -79,6 +84,8 @@
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<action android:name="android.intent.action.TIME_SET" />
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>

View File

@ -34,7 +34,7 @@ class AWApplication : Application() {
private fun calibrateVersions() {
// 2.0 Tolerance
if (Preferences.clockTextSize > 50f) {
Preferences.clockTextSize = 46f
Preferences.clockTextSize = 32f
}
if (Preferences.textMainSize > 36f) {

View File

@ -1,10 +1,12 @@
package com.tommasoberlose.anotherwidget.db
import android.content.Context
import android.util.Log
import com.chibatching.kotpref.bulk
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.models.Event
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
import com.tommasoberlose.anotherwidget.services.UpdatesWorker
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import io.realm.Realm
import io.realm.RealmResults
@ -33,13 +35,10 @@ class EventRepository(val context: Context) {
remove(Preferences::nextEventEndDate)
remove(Preferences::nextEventCalendarId)
}
MainWidget.updateWidget(context)
}
fun saveNextEventData(event: Event) {
Preferences.nextEventId = event.id
MainWidget.updateWidget(context)
}
fun getNextEvent(): Event? = realm.where(Event::class.java).equalTo("id", Preferences.nextEventId).findFirst() ?: realm.where(Event::class.java).findFirst()
@ -57,7 +56,7 @@ class EventRepository(val context: Context) {
} else {
resetNextEventData()
}
UpdatesReceiver.setUpdates(context)
UpdatesWorker.setUpdates(context)
MainWidget.updateWidget(context)
}
@ -74,7 +73,7 @@ class EventRepository(val context: Context) {
} else {
resetNextEventData()
}
UpdatesReceiver.setUpdates(context)
UpdatesWorker.setUpdates(context)
MainWidget.updateWidget(context)
}

View File

@ -7,63 +7,11 @@ object Constants {
const val RESULT_APP_NAME = "RESULT_APP_NAME"
const val RESULT_APP_PACKAGE = "RESULT_APP_PACKAGE"
const val PREF_SHOW_EVENTS = "PREF_SHOW_EVENTS"
const val PREF_SHOW_WEATHER = "PREF_SHOW_WEATHER"
const val PREF_WEATHER_ICON = "PREF_WEATHER_ICON"
const val PREF_WEATHER_TEMP = "PREF_WEATHER_TEMP"
const val PREF_WEATHER_TEMP_UNIT = "PREF_WEATHER_TEMP_UNIT"
const val PREF_WEATHER_REAL_TEMP_UNIT = "PREF_WEATHER_REAL_TEMP_UNIT"
const val PREF_CALENDAR_ALL_DAY = "PREF_CALENDAR_ALL_DAY"
const val PREF_CALENDAR_FILTER = "PREF_CALENDAR_FILTER"
const val PREF_EVENT_ID = "PREF_EVENT_ID"
const val PREF_NEXT_EVENT_ID = "PREF_NEXT_EVENT_ID"
const val PREF_NEXT_EVENT_NAME = "PREF_NEXT_EVENT_NAME"
const val PREF_NEXT_EVENT_START_DATE = "PREF_NEXT_EVENT_START_DATE"
const val PREF_NEXT_EVENT_ALL_DAY = "PREF_NEXT_EVENT_ALL_DAY"
const val PREF_NEXT_EVENT_LOCATION = "PREF_NEXT_EVENT_LOCATION"
const val PREF_NEXT_EVENT_END_DATE = "PREF_NEXT_EVENT_END_DATE"
const val PREF_NEXT_EVENT_CALENDAR_ID = "PREF_NEXT_EVENT_CALENDAR_ID"
const val PREF_CUSTOM_LOCATION_LAT = "PREF_CUSTOM_LOCATION_LAT"
const val PREF_CUSTOM_LOCATION_LON = "PREF_CUSTOM_LOCATION_LON"
const val PREF_CUSTOM_LOCATION_ADD = "PREF_CUSTOM_LOCATION_ADD"
const val PREF_HOUR_FORMAT = "PREF_HOUR_FORMAT"
const val PREF_ITA_FORMAT_DATE = "PREF_ITA_FORMAT_DATE"
const val PREF_WEATHER_REFRESH_PERIOD = "PREF_WEATHER_REFRESH_PERIOD"
const val PREF_SHOW_UNTIL = "PREF_SHOW_UNTIL"
const val PREF_CALENDAR_APP_NAME = "PREF_CALENDAR_APP_NAME"
const val PREF_CALENDAR_APP_PACKAGE = "PREF_CALENDAR_APP_PACKAGE"
const val PREF_WEATHER_APP_NAME = "PREF_WEATHER_APP_NAME"
const val PREF_WEATHER_APP_PACKAGE = "PREF_WEATHER_APP_PACKAGE"
const val PREF_WEATHER_PROVIDER_API_KEY = "PREF_WEATHER_PROVIDER_API_KEY"
const val PREF_EVENT_APP_NAME = "PREF_EVENT_APP_NAME"
const val PREF_EVENT_APP_PACKAGE = "PREF_EVENT_APP_PACKAGE"
const val PREF_SHOW_EVENT_LOCATION = "PREF_SHOW_EVENT_LOCATION"
const val PREF_TEXT_COLOR = "PREF_TEXT_COLOR"
const val PREF_TEXT_MAIN_SIZE = "PREF_TEXT_MAIN_SIZE"
const val PREF_TEXT_SECOND_SIZE = "PREF_TEXT_SECOND_SIZE"
const val PREF_TEXT_CLOCK_SIZE = "PREF_TEXT_CLOCK_SIZE"
const val PREF_WEATHER_PROVIDER = "PREF_WEATHER_PROVIDER"
const val PREF_SHOW_CLOCK = "PREF_SHOW_CLOCK"
const val PREF_CLOCK_APP_NAME = "PREF_CLOCK_APP_NAME"
const val PREF_CLOCK_APP_PACKAGE = "PREF_CLOCK_APP_PACKAGE"
const val PREF_TEXT_SHADOW = "PREF_TEXT_SHADOW"
const val PREF_SHOW_DIFF_TIME = "PREF_SHOW_DIFF_TIME"
const val PREF_SHOW_DECLINED_EVENTS = "PREF_SHOW_DECLINED_EVENTS"
const val PREF_OPEN_WEATHER_API_KEY = "PREF_OPEN_WEATHER_API_KEY"
const val PREF_DARK_SKY_API_KEY = "PREF_DARK_SKY_API_KEY"
const val PREF_WU_API_KEY = "PREF_WU_API_KEY"
const val PREF_SECOND_ROW_INFORMATION = "PREF_SECOND_ROW_INFORMATION"
const val PREF_CUSTOM_FONT = "PREF_CUSTOM_FONT"
const val PREF_CUSTOM_FONT_FILE = "PREF_CUSTOM_FONT_FILE"
const val PREF_SHOW_NEXT_EVENT = "PREF_SHOW_NEXT_EVENT"
const val PREF_SHOW_WIDGET_PREVIEW = "PREF_SHOW_WIDGET_PREVIEW"
const val PREF_SHOW_GPS_NOTIFICATION = "PREF_SHOW_GPS_NOTIFICATION"
const val CUSTOM_FONT_PRODUCT_SANS = 1
const val itDateFormat = "EEEE, d MMM"
const val engDateFormat = "EEEE, MMM d"
const val goodHourFormat = "HH:mm"
const val badHourFormat = "hh:mm a"
enum class ClockBottomMargin(val value: Int) {
NONE(0),
SMALL(1),
MEDIUM(2),
LARGE(3)
}
}

View File

@ -10,15 +10,14 @@ object Preferences : KotprefModel() {
var darkThemePreference by intPref(default = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) MODE_NIGHT_FOLLOW_SYSTEM else MODE_NIGHT_AUTO_BATTERY)
var showEvents by booleanPref(key = "PREF_SHOW_EVENTS", default = false)
var showWeather by booleanPref(key = "PREF_SHOW_WEATHER")
var weatherIcon by stringPref(key = "PREF_WEATHER_ICON")
var weatherTemp by floatPref(key = "PREF_WEATHER_TEMP")
var showWeather by booleanPref(key = "PREF_SHOW_WEATHER", default = false)
var weatherIcon by stringPref(key = "PREF_WEATHER_ICON", default = "")
var weatherTemp by floatPref(key = "PREF_WEATHER_TEMP", default = 0f)
var weatherTempUnit by stringPref(key = "PREF_WEATHER_TEMP_UNIT", default = "F")
var weatherRealTempUnit by stringPref(key = "PREF_WEATHER_REAL_TEMP_UNIT", default = "F")
var calendarAllDay by booleanPref(key = "PREF_CALENDAR_ALL_DAY", default = false)
var calendarAllDay by booleanPref(key = "PREF_CALENDAR_ALL_DAY", default = true)
var calendarFilter by stringPref(key = "PREF_CALENDAR_FILTER", default = "")
var eventId by intPref(key = "PREF_EVENT_ID", default = -1)
var nextEventId by longPref(key = "PREF_NEXT_EVENT_ID", default = -1)
var nextEventName by stringPref(key = "PREF_NEXT_EVENT_NAME")
var nextEventStartDate by longPref(key = "PREF_NEXT_EVENT_START_DATE")
@ -29,7 +28,6 @@ object Preferences : KotprefModel() {
var customLocationLat by stringPref(key = "PREF_CUSTOM_LOCATION_LAT", default = "")
var customLocationLon by stringPref(key = "PREF_CUSTOM_LOCATION_LON", default = "")
var customLocationAdd by stringPref(key = "PREF_CUSTOM_LOCATION_ADD", default = "")
var hourFormat by stringPref(key = "PREF_HOUR_FORMAT", default = "12")
var dateFormat by stringPref(default = "")
var weatherRefreshPeriod by intPref(key = "PREF_WEATHER_REFRESH_PERIOD", default = 1)
var showUntil by intPref(key = "PREF_SHOW_UNTIL", default = 1)
@ -40,28 +38,25 @@ object Preferences : KotprefModel() {
var weatherProviderApi by stringPref(key = "PREF_WEATHER_PROVIDER_API_KEY", default = "")
var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "")
var eventAppPackage by stringPref(key = "PREF_EVENT_APP_PACKAGE", default = "")
var showEventLocation by stringPref(key = "PREF_SHOW_EVENT_LOCATION", default = "")
var openEventDetails by booleanPref(default = true)
var textGlobalColor by stringPref(key = "PREF_TEXT_COLOR", default = "#FFFFFF")
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f)
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.value)
var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false)
var clockAppName by stringPref(key = "PREF_CLOCK_APP_NAME", default = "")
var clockAppPackage by stringPref(key = "PREF_CLOCK_APP_PACKAGE", default = "")
var showNextAlarm by booleanPref(default = true)
var showNextAlarm by booleanPref(default = false)
var textShadow by intPref(key = "PREF_TEXT_SHADOW", default = 1)
var showDiffTime by booleanPref(key = "PREF_SHOW_DIFF_TIME")
var showDeclinedEvents by booleanPref(key = "PREF_SHOW_DECLINED_EVENTS", default = true)
var openWeatherApiKey by stringPref(key = "PREF_OPEN_WEATHER_API_KEY", default = "")
var darkSkyApiKey by stringPref(key = "PREF_DARK_SKY_API_KEY", default = "")
var wuApiKey by stringPref(key = "PREF_WU_API_KEY", default = "")
var secondRowInformation by intPref(key = "PREF_SECOND_ROW_INFORMATION", default = 1)
var showDiffTime by booleanPref(key = "PREF_SHOW_DIFF_TIME", default = true)
var showDeclinedEvents by booleanPref(key = "PREF_SHOW_DECLINED_EVENTS", default = false)
var secondRowInformation by intPref(key = "PREF_SECOND_ROW_INFORMATION", default = 0)
var customFont by intPref(key = "PREF_CUSTOM_FONT", default = Constants.CUSTOM_FONT_PRODUCT_SANS)
var customFontFile by stringPref(key = "PREF_CUSTOM_FONT_FILE")
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
var showGpsInformation by booleanPref(key = "PREF_SHOW_GPS_NOTIFICATION", default = true)
var showWallpaper by booleanPref(default = false)
var showWallpaper by booleanPref(default = true)
var showBigClockWarning by booleanPref(default = true)
var showWeatherWarning by booleanPref(default = true)
}

View File

@ -11,7 +11,7 @@ object AlarmHelper {
val alarm = nextAlarmClock
return if (
alarm != null
&& alarm.triggerTime - Calendar.getInstance().timeInMillis > 2 * 60 * 1000
&& alarm.triggerTime - Calendar.getInstance().timeInMillis > 10 * 60 * 1000
&& alarm.triggerTime - Calendar.getInstance().timeInMillis < 12 * 60 * 60 * 1000
) {
"%s %s".format(

View File

@ -7,6 +7,7 @@ import android.util.Log
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.drawToBitmap
import com.google.firebase.crashlytics.FirebaseCrashlytics
import java.lang.Exception
@ -19,10 +20,11 @@ object BitmapHelper {
view.measure(measuredWidth, measuredHeight)
return try {
Log.d("ciao", "bitmap ${view.measuredWidth}, ${view.measuredHeight} - draw = ${draw}")
val btm = Bitmap.createBitmap(
view.measuredWidth,
view.measuredHeight,
Bitmap.Config.ARGB_8888
if (draw) Bitmap.Config.ARGB_8888 else Bitmap.Config.ALPHA_8
)
if (draw) {
//Bind a canvas to it
@ -35,7 +37,7 @@ object BitmapHelper {
btm
} catch (ex: Exception) {
FirebaseCrashlytics.getInstance().recordException(ex)
Bitmap.createBitmap(5, 5, Bitmap.Config.ARGB_8888)
Bitmap.createBitmap(5, 5, Bitmap.Config.ALPHA_8)
}
}

View File

@ -10,6 +10,7 @@ import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.models.Event
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
import com.tommasoberlose.anotherwidget.services.UpdatesWorker
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
@ -124,7 +125,8 @@ object CalendarHelper {
eventRepository.resetNextEventData()
}
UpdatesReceiver.setUpdates(context)
UpdatesWorker.setUpdates(context)
Log.d("ciao", "force update? 7")
MainWidget.updateWidget(context)
EventBus.getDefault().post(MainActivity.UpdateUiMessageEvent())

View File

@ -30,35 +30,6 @@ object IntentHelper {
}
}
fun getCalendarIntent(context: Context): Intent {
return when (Preferences.calendarAppPackage) {
"" -> {
Intent(Intent.ACTION_MAIN).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
addCategory(Intent.CATEGORY_APP_CALENDAR)
}
}
"_" -> {
Intent()
}
else -> {
val pm: PackageManager = context.packageManager
try {
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
addCategory(Intent.CATEGORY_LAUNCHER)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
} catch (e: Exception) {
e.printStackTrace()
Intent(Intent.ACTION_MAIN).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
addCategory(Intent.CATEGORY_APP_CALENDAR)
}
}
}
}
}
fun getWeatherIntent(context: Context): Intent {
return when (Preferences.weatherAppPackage) {
"" -> {
@ -91,15 +62,12 @@ object IntentHelper {
}
}
fun getEventIntent(context: Context, e: Event): Intent {
return when (Preferences.eventAppPackage) {
fun getCalendarIntent(context: Context): Intent {
return when (Preferences.calendarAppPackage) {
"" -> {
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
Intent(Intent.ACTION_VIEW).apply {
data = uri
Intent(Intent.ACTION_MAIN).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
addCategory(Intent.CATEGORY_APP_CALENDAR)
}
}
"_" -> {
@ -107,25 +75,46 @@ object IntentHelper {
}
else -> {
val pm: PackageManager = context.packageManager
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
try {
pm.getLaunchIntentForPackage(Preferences.eventAppPackage)!!.apply {
action = Intent.ACTION_VIEW
data = uri
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
addCategory(Intent.CATEGORY_LAUNCHER)
// addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
// putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
} catch (ex: Exception) {
} catch (e: Exception) {
e.printStackTrace()
Intent(Intent.ACTION_MAIN).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
addCategory(Intent.CATEGORY_APP_CALENDAR)
}
}
}
}
}
fun getEventIntent(context: Context, e: Event, forceEventDetails: Boolean = false): Intent {
return when (Preferences.openEventDetails || forceEventDetails) {
true -> {
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
if (Preferences.calendarAppPackage == "") {
Intent(Intent.ACTION_VIEW).apply {
data = uri
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
}
} else {
getCalendarIntent(context).apply {
action = Intent.ACTION_VIEW
data = uri
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
}
}
}
false -> {
getCalendarIntent(context)
}
}
}

View File

@ -2,6 +2,8 @@ package com.tommasoberlose.anotherwidget.helpers
import android.Manifest
import android.content.Context
import android.os.Build
import android.util.Log
import com.google.android.gms.location.LocationServices
import com.kwabenaberko.openweathermaplib.constants.Units
import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper
@ -24,7 +26,7 @@ object WeatherHelper {
val networkApi = WeatherNetworkApi(context)
if (Preferences.customLocationAdd != "") {
networkApi.updateWeather()
} else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
} else if (context.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION)) {
LocationServices.getFusedLocationProviderClient(context).lastLocation.addOnCompleteListener { task ->
if (task.isSuccessful) {
val location = task.result

View File

@ -0,0 +1,51 @@
package com.tommasoberlose.anotherwidget.helpers
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.res.Configuration.ORIENTATION_PORTRAIT
object WidgetHelper {
class WidgetSizeProvider(
private val context: Context,
private val appWidgetManager: AppWidgetManager
) {
fun getWidgetsSize(widgetId: Int): Pair<Int, Int> {
val isPortrait = context.resources.configuration.orientation == ORIENTATION_PORTRAIT
val width = getWidgetWidth(isPortrait, widgetId)
val height = getWidgetHeight(isPortrait, widgetId)
val widthInPx = context.dip(width)
val heightInPx = context.dip(height)
return widthInPx to heightInPx
}
private fun getWidgetWidth(isPortrait: Boolean, widgetId: Int): Int =
if (isPortrait) {
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
} else {
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
}
private fun getWidgetHeight(isPortrait: Boolean, widgetId: Int): Int =
if (isPortrait) {
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
} else {
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
}
private fun getWidgetSizeInDp(widgetId: Int, key: String): Int =
appWidgetManager.getAppWidgetOptions(widgetId).getInt(key, 0)
private fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()
}
fun Pair<Int, Int>.reduceDimensionWithMaxWidth(width: Int): Pair<Int, Int> {
return if (first < width) {
this
} else {
val factor = width / first
width to second * factor
}
}
}

View File

@ -1,6 +1,7 @@
package com.tommasoberlose.anotherwidget.network
import android.content.Context
import android.util.Log
import com.kwabenaberko.openweathermaplib.constants.Units
import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper
import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeatherCallback
@ -23,9 +24,7 @@ class WeatherNetworkApi(val context: Context) {
Preferences.weatherTemp = currentWeather.main.temp.toFloat()
Preferences.weatherIcon = currentWeather.weather[0].icon
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
MainWidget.updateWidget(
context
)
MainWidget.updateWidget(context)
EventBus.getDefault().post(MainActivity.UpdateUiMessageEvent())
}

View File

@ -12,7 +12,6 @@ class NewCalendarEventReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val eventRepository = EventRepository(context)
Log.d("ciao", "nuovo evento")
when (intent.action) {
Intent.ACTION_PROVIDER_CHANGED,
Intent.ACTION_TIME_CHANGED -> {

View File

@ -21,45 +21,17 @@ class UpdatesReceiver : BroadcastReceiver() {
when (intent.action) {
Intent.ACTION_BOOT_COMPLETED,
Intent.ACTION_MY_PACKAGE_REPLACED,
Intent.ACTION_TIME_CHANGED,
Intent.ACTION_TIMEZONE_CHANGED,
Intent.ACTION_LOCALE_CHANGED,
Actions.ACTION_CALENDAR_UPDATE -> CalendarHelper.updateEventList(context)
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
Intent.ACTION_DATE_CHANGED,
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED -> MainWidget.updateWidget(context)
}
}
companion object {
fun setUpdates(context: Context) {
removeUpdates(context)
val eventRepository = EventRepository(context)
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
eventRepository.getEvents().forEach { event ->
val hoursDiff = Period(Calendar.getInstance().timeInMillis, event.startDate).hours
// Update the widget every hour till the event
(0 .. hoursDiff).forEach {
setExact(
AlarmManager.RTC_WAKEUP,
(event.startDate + 1000) - it * 1000 * 60* 60,
PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0)
)
}
// Update the widget one second after the event is finished
setExact(
AlarmManager.RTC_WAKEUP,
event.endDate + 1000,
PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0)
)
}
}
}
fun removeUpdates(context: Context) {
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
cancel(PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java), 0))
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
Actions.ACTION_TIME_UPDATE -> {
Log.d("ciao", "force update? 4 - ${intent.action}")
MainWidget.updateWidget(context)
}
}
}

View File

@ -8,6 +8,7 @@ import android.content.Intent
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import com.tommasoberlose.anotherwidget.services.WeatherWorker
import java.util.*
@ -17,68 +18,9 @@ class WeatherReceiver : BroadcastReceiver() {
when (intent.action) {
Intent.ACTION_BOOT_COMPLETED,
Intent.ACTION_MY_PACKAGE_REPLACED,
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
Actions.ACTION_WEATHER_UPDATE -> WeatherHelper.updateWeather(context)
}
}
companion object {
fun setUpdates(context: Context) {
removeUpdates(context)
if (Preferences.showWeather && Preferences.weatherProviderApi != "") {
WeatherHelper.updateWeather(context)
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
val pi = PendingIntent.getBroadcast(
context,
1,
Intent(context, WeatherReceiver::class.java).apply {
action = Actions.ACTION_WEATHER_UPDATE
},
0
)
val refresh: Long = when (Preferences.weatherRefreshPeriod) {
0 -> 30
1 -> 60
2 -> 60 * 3
3 -> 60 * 6
4 -> 60 * 12
5 -> 60 * 24
else -> 60
}
val now = Calendar.getInstance().apply {
set(Calendar.MILLISECOND, 0)
set(Calendar.SECOND, 0)
}
setRepeating(AlarmManager.RTC_WAKEUP, now.timeInMillis, 1000 * 60 * refresh, pi)
}
}
}
fun setOneTimeUpdate(context: Context) {
// Update the weather in a few minuter when the api key has been changed
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
val pi = PendingIntent.getBroadcast(context, 1, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
val now = Calendar.getInstance().apply {
set(Calendar.MILLISECOND, 0)
set(Calendar.SECOND, 0)
}
listOf(10, 15, 20).forEach {
setExact(AlarmManager.RTC_WAKEUP, now.timeInMillis + 1000 * 60 * it, pi)
}
}
}
fun removeUpdates(context: Context) {
val intent = Intent(context, WeatherReceiver::class.java)
val sender = PendingIntent.getBroadcast(context, 1, intent, 0)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(sender)
Intent.ACTION_TIMEZONE_CHANGED,
Intent.ACTION_LOCALE_CHANGED,
Intent.ACTION_TIME_CHANGED -> WeatherWorker.setUpdates(context)
}
}
}

View File

@ -0,0 +1,51 @@
package com.tommasoberlose.anotherwidget.services
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
import org.joda.time.Period
import java.util.*
import java.util.concurrent.TimeUnit
class UpdatesWorker(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) {
override fun doWork(): Result {
CalendarHelper.updateEventList(applicationContext)
return Result.success()
}
companion object {
private const val JOB_TAG = "UPDATES_WORKER"
fun setUpdates(context: Context) {
removeUpdates(context)
val now = Calendar.getInstance().timeInMillis
val workManager = WorkManager.getInstance(context)
val eventRepository = EventRepository(context)
eventRepository.getEvents().forEach { event ->
val hoursDiff = Period(Calendar.getInstance().timeInMillis, event.startDate).hours
// Update the widget every hour till the event
(0 .. hoursDiff).forEach {
workManager.enqueue(OneTimeWorkRequestBuilder<UpdatesWorker>().setInitialDelay((event.startDate + 1000) - now - it * 1000 * 60* 60, TimeUnit.MILLISECONDS).build())
}
// Update the widget one second after the event is finished
workManager.enqueue(OneTimeWorkRequestBuilder<UpdatesWorker>().setInitialDelay(event.endDate + 1000 - now, TimeUnit.MILLISECONDS).build())
}
}
fun removeUpdates(context: Context) {
WorkManager.getInstance(context).cancelAllWorkByTag(JOB_TAG)
}
}
}

View File

@ -0,0 +1,58 @@
package com.tommasoberlose.anotherwidget.services
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.work.*
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
import java.util.*
import java.util.concurrent.TimeUnit
class WeatherWorker(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) {
override fun doWork(): Result {
WeatherHelper.updateWeather(applicationContext)
return Result.success()
}
companion object {
private const val JOB_TAG = "WEATHER_WORKER"
fun setUpdates(context: Context) {
removeUpdates(context)
if (Preferences.showWeather && Preferences.weatherProviderApi != "") {
WeatherHelper.updateWeather(context)
WorkManager.getInstance(context).enqueue(PeriodicWorkRequestBuilder<WeatherWorker>(
when (Preferences.weatherRefreshPeriod) {
0 -> 30
1 -> 60
2 -> 60L * 3
3 -> 60L * 6
4 -> 60L * 12
5 -> 60L * 24
else -> 60
}
, TimeUnit.MINUTES)
.addTag(JOB_TAG)
.build())
}
}
fun setOneTimeUpdate(context: Context) {
val workManager = WorkManager.getInstance(context)
listOf(10L, 15L, 20L).forEach {
workManager.enqueue(OneTimeWorkRequestBuilder<WeatherWorker>().setInitialDelay(it, TimeUnit.MINUTES).addTag(JOB_TAG).build())
}
}
fun removeUpdates(context: Context) {
WorkManager.getInstance(context).cancelAllWorkByTag(JOB_TAG)
}
}
}

View File

@ -5,6 +5,7 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.location.Address
import android.location.Geocoder
import android.os.Build
import android.os.Bundle
import com.tommasoberlose.anotherwidget.R
import android.text.Editable
@ -125,7 +126,7 @@ class CustomLocationActivity : AppCompatActivity() {
private fun requirePermission() {
Dexter.withContext(this)
.withPermissions(
Manifest.permission.ACCESS_FINE_LOCATION
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {

View File

@ -5,6 +5,7 @@ import android.app.Activity
import android.appwidget.AppWidgetManager
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
@ -19,6 +20,7 @@ import androidx.lifecycle.lifecycleScope
import com.google.android.material.tabs.TabLayoutMediator
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.global.RequestCode
import com.tommasoberlose.anotherwidget.helpers.BitmapHelper
@ -32,13 +34,12 @@ import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.getCurrentWallpaper
import com.tommasoberlose.anotherwidget.utils.toPixel
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.android.synthetic.main.the_widget_sans.*
import kotlinx.coroutines.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.lang.Exception
class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
@ -69,10 +70,9 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
}.attach()
// Init clock
clock.setTextColor(ColorHelper.getFontColor())
clock.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
clock.format12Hour = "hh:mm"
clock.isVisible = Preferences.showClock
time.setTextColor(ColorHelper.getFontColor())
time.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
time.isVisible = Preferences.showClock
preview.layoutParams = preview.layoutParams.apply {
height = 160.toPixel(this@MainActivity) + if (Preferences.showClock) 100.toPixel(this@MainActivity) else 0
@ -82,7 +82,6 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
subscribeUi(viewModel)
updateUI()
CalendarHelper.updateEventList(this)
WeatherHelper.updateWeather(this)
}
@ -90,27 +89,42 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
private fun updateUI() {
preview.setCardBackgroundColor(getColor(if (ColorHelper.getFontColor().isColorDark()) android.R.color.white else R.color.colorAccent))
val generatedView = MainWidget.generateWidgetView(this@MainActivity)
generatedView.measure(0, 0)
preview.measure(0, 0)
uiJob?.cancel()
uiJob = lifecycleScope.launch(Dispatchers.IO) {
delay(200)
val generatedView = MainWidget.generateWidgetView(this@MainActivity)
withContext(Dispatchers.Main) {
generatedView.measure(0, 0)
preview.measure(0, 0)
try {
// Try to recycle old bitmaps
(bitmap_container.drawable as BitmapDrawable).bitmap.recycle()
} catch (ignore: Exception) {}
}
val bitmap = BitmapHelper.getBitmapFromView(generatedView, if (preview.width > 0) preview.width else generatedView.measuredWidth, generatedView.measuredHeight)
withContext(Dispatchers.Main) {
// Clock
clock.setTextColor(ColorHelper.getFontColor())
clock.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
clock.format12Hour = "hh:mm"
time.setTextColor(ColorHelper.getFontColor())
time.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
time.format12Hour = "hh:mm"
if ((Preferences.showClock && !clock.isVisible) || (!Preferences.showClock && clock.isVisible)) {
// Clock bottom margin
clock_bottom_margin_none.isVisible = Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value
clock_bottom_margin_small.isVisible = Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value
clock_bottom_margin_medium.isVisible = Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value
clock_bottom_margin_large.isVisible = Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value
if ((Preferences.showClock && !time.isVisible) || (!Preferences.showClock && time.isVisible)) {
if (Preferences.showClock) {
clock.layoutParams = clock.layoutParams.apply {
time.layoutParams = time.layoutParams.apply {
height = RelativeLayout.LayoutParams.WRAP_CONTENT
}
clock.measure(0, 0)
time.measure(0, 0)
}
val initialHeight = clock.measuredHeight
val initialHeight = time.measuredHeight
ValueAnimator.ofFloat(
if (Preferences.showClock) 0f else 1f,
if (Preferences.showClock) 1f else 0f
@ -118,19 +132,19 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
duration = 500L
addUpdateListener {
val animatedValue = animatedValue as Float
clock.layoutParams = clock.layoutParams.apply {
time.layoutParams = time.layoutParams.apply {
height = (initialHeight * animatedValue).toInt()
}
}
addListener(
onStart = {
if (Preferences.showClock) {
clock.isVisible = true
time.isVisible = true
}
},
onEnd = {
if (!Preferences.showClock) {
clock.isVisible = false
time.isVisible = false
}
}
)
@ -149,13 +163,13 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
}
}.start()
} else {
clock.layoutParams = clock.layoutParams.apply {
time.layoutParams = time.layoutParams.apply {
height = RelativeLayout.LayoutParams.WRAP_CONTENT
}
clock.measure(0, 0)
time.measure(0, 0)
}
widget_bitmap.setImageBitmap(bitmap)
bitmap_container.setImageBitmap(bitmap)
widget_loader.animate().scaleX(0f).scaleY(0f).start()
widget.animate().alpha(1f).start()
}

View File

@ -5,6 +5,7 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -69,7 +70,8 @@ class AdvancedSettingsFragment : Fragment() {
setupListener()
app_version.text = "v%s".format(BuildConfig.VERSION_NAME)
app_version.text = "v%s (%s)".format(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)
requirePermission()
}
private fun subscribeUi(
@ -117,7 +119,7 @@ class AdvancedSettingsFragment : Fragment() {
action_show_wallpaper.setOnClickListener {
maintainScrollPosition {
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_title_show_wallpaper))
.setSelectedValue(Preferences.showWallpaper)
.setSelectedValue(Preferences.showWallpaper && activity?.checkGrantedPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == true)
.addItem(
getString(R.string.settings_visible),
true
@ -174,6 +176,7 @@ class AdvancedSettingsFragment : Fragment() {
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {
Preferences.showWallpaper = false
Preferences.showWallpaper = report.areAllPermissionsGranted()
}
}

View File

@ -89,6 +89,7 @@ class CalendarSettingsFragment : Fragment() {
binding.isCalendarEnabled = it
if (it) {
requirePermission()
CalendarHelper.setEventUpdatesAndroidN(requireContext())
} else {
CalendarHelper.removeEventUpdatesAndroidN(requireContext())
@ -147,9 +148,9 @@ class CalendarSettingsFragment : Fragment() {
}
})
viewModel.eventAppName.observe(viewLifecycleOwner, Observer {
viewModel.openEventDetails.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
event_app_label.text = if (it != "") it else getString(R.string.default_calendar_app)
open_event_details_label.text = if (it) getString(R.string.default_event_app) else getString(R.string.default_calendar_app)
}
})
@ -301,8 +302,15 @@ class CalendarSettingsFragment : Fragment() {
}
}
action_event_app.setOnClickListener {
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java), RequestCode.EVENT_APP_REQUEST_CODE.code)
action_open_event_details.setOnClickListener {
if (Preferences.showEvents) {
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_event_app_title)).setSelectedValue(Preferences.openEventDetails)
.addItem(getString(R.string.default_event_app), true)
.addItem(getString(R.string.default_calendar_app), false)
.addOnSelectItemListener { value ->
Preferences.openEventDetails = value
}.show()
}
}
action_calendar_app.setOnClickListener {

View File

@ -83,6 +83,17 @@ class ClockSettingsFragment : Fragment() {
}
})
viewModel.clockBottomMargin.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
clock_bottom_margin_label.text = when (it) {
Constants.ClockBottomMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
Constants.ClockBottomMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
Constants.ClockBottomMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
}
}
})
viewModel.showNextAlarm.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
show_next_alarm_label.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
@ -116,12 +127,14 @@ class ClockSettingsFragment : Fragment() {
}.show()
}
action_show_next_alarm.setOnClickListener {
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.showNextAlarm)
.addItem(getString(R.string.settings_visible), true)
.addItem(getString(R.string.settings_not_visible), false)
action_clock_bottom_margin_size.setOnClickListener {
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.clockBottomMargin)
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_none), Constants.ClockBottomMargin.NONE.value)
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_small), Constants.ClockBottomMargin.SMALL.value)
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_medium), Constants.ClockBottomMargin.MEDIUM.value)
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_large), Constants.ClockBottomMargin.LARGE.value)
.addOnSelectItemListener { value ->
Preferences.showNextAlarm = value
Preferences.clockBottomMargin = value
}.show()
}
@ -132,6 +145,15 @@ class ClockSettingsFragment : Fragment() {
)
}
}
action_show_next_alarm.setOnClickListener {
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.showNextAlarm)
.addItem(getString(R.string.settings_visible), true)
.addItem(getString(R.string.settings_not_visible), false)
.addOnSelectItemListener { value ->
Preferences.showNextAlarm = value
}.show()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

View File

@ -3,8 +3,8 @@ package com.tommasoberlose.anotherwidget.ui.fragments
import android.Manifest
import android.app.Activity
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -28,6 +28,7 @@ import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.global.RequestCode
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
import com.tommasoberlose.anotherwidget.services.WeatherWorker
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
import com.tommasoberlose.anotherwidget.ui.activities.CustomLocationActivity
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
@ -115,6 +116,7 @@ class WeatherSettingsFragment : Fragment() {
temp_unit.text =
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
}
checkLocationPermission()
})
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner, Observer {
@ -133,9 +135,9 @@ class WeatherSettingsFragment : Fragment() {
}
private fun checkLocationPermission() {
if (activity?.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) == true) {
if (activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) == true) {
location_permission_alert_icon.isVisible = false
WeatherReceiver.setUpdates(requireContext())
WeatherWorker.setUpdates(requireContext())
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
location_permission_alert_icon.isVisible = true
location_permission_alert_icon.setOnClickListener {
@ -210,7 +212,7 @@ class WeatherSettingsFragment : Fragment() {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
Constants.RESULT_CODE_CUSTOM_LOCATION -> {
WeatherReceiver.setUpdates(requireContext())
WeatherWorker.setUpdates(requireContext())
checkLocationPermission()
}
RequestCode.WEATHER_APP_REQUEST_CODE.code -> {
@ -221,7 +223,7 @@ class WeatherSettingsFragment : Fragment() {
MainWidget.updateWidget(requireContext())
}
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
WeatherReceiver.setOneTimeUpdate(requireContext())
WeatherWorker.setOneTimeUpdate(requireContext())
}
}
}
@ -231,7 +233,7 @@ class WeatherSettingsFragment : Fragment() {
private fun requirePermission() {
Dexter.withContext(requireContext())
.withPermissions(
Manifest.permission.ACCESS_FINE_LOCATION
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {

View File

@ -21,10 +21,9 @@ class MainViewModel : ViewModel() {
val showDiffTime = Preferences.asLiveData(Preferences::showDiffTime)
val showDeclinedEvents = Preferences.asLiveData(Preferences::showDeclinedEvents)
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
val openEventDetails = Preferences.asLiveData(Preferences::openEventDetails)
val calendarAppName = Preferences.asLiveData(Preferences::calendarAppName)
val eventAppName = Preferences.asLiveData(Preferences::eventAppName)
// Clock Settings
val showClock = Preferences.asLiveData(Preferences::showClock)
@ -33,6 +32,7 @@ class MainViewModel : ViewModel() {
val clockAppName = Preferences.asLiveData(Preferences::clockAppName)
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
val dateFormat = Preferences.asLiveData(Preferences::dateFormat)
val clockBottomMargin = Preferences.asLiveData(Preferences::clockBottomMargin)
val showBigClockWarning = Preferences.asLiveData(Preferences::showBigClockWarning)

View File

@ -20,21 +20,25 @@ import android.widget.RemoteViews
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.*
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper.reduceDimensionWithMaxWidth
import com.tommasoberlose.anotherwidget.receivers.NewCalendarEventReceiver
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver
import com.tommasoberlose.anotherwidget.services.UpdatesWorker
import com.tommasoberlose.anotherwidget.services.WeatherWorker
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.convertSpToPixels
import com.tommasoberlose.anotherwidget.utils.getCapWordString
import com.tommasoberlose.anotherwidget.utils.toPixel
import kotlinx.android.synthetic.main.the_widget.view.*
import java.lang.Exception
import java.text.DateFormat
import java.util.*
import java.util.concurrent.TimeUnit
@ -55,7 +59,7 @@ class MainWidget : AppWidgetProvider() {
override fun onEnabled(context: Context) {
CalendarHelper.updateEventList(context)
WeatherReceiver.setUpdates(context)
WeatherWorker.setUpdates(context)
if (Preferences.showEvents) {
CalendarHelper.setEventUpdatesAndroidN(context)
@ -65,8 +69,10 @@ class MainWidget : AppWidgetProvider() {
}
override fun onDisabled(context: Context) {
UpdatesReceiver.removeUpdates(context)
WeatherReceiver.removeUpdates(context)
if (getWidgetCount(context) == 0) {
UpdatesWorker.removeUpdates(context)
WeatherWorker.removeUpdates(context)
}
}
companion object {
@ -81,26 +87,26 @@ class MainWidget : AppWidgetProvider() {
context.sendBroadcast(update)
}
fun getWidgetCount(context: Context): Int {
val widgetManager = AppWidgetManager.getInstance(context)
val widgetComponent = ComponentName(context, MainWidget::class.java)
return widgetManager.getAppWidgetIds(widgetComponent).size
}
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager,
appWidgetId: Int) {
val displayMetrics = Resources.getSystem().displayMetrics
var height = 110.toPixel(context)
val width = displayMetrics.widthPixels
if (Preferences.showClock) {
height += Preferences.clockTextSize.convertSpToPixels(context).toInt() + 16.toPixel(context)
}
if (Preferences.textMainSize > 30 && Preferences.textSecondSize > 22) {
height += 24.toPixel(context)
}
generateWidgetView(context, appWidgetId, appWidgetManager, width - 16.toPixel(context))
val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId).reduceDimensionWithMaxWidth(1200)
generateWidgetView(context, appWidgetId, appWidgetManager, dimensions.first - 8.toPixel(context) /*width - 16.toPixel(context)*/)
}
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int) {
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
val generatedView = generateWidgetView(context)
views.setImageViewBitmap(R.id.bitmap_container, BitmapHelper.getBitmapFromView(generatedView, width = w - 32.toPixel(context)))
views.setImageViewBitmap(R.id.bitmap_container, BitmapHelper.getBitmapFromView(generatedView, width = w))
// Clock
views = updateClockView(context, views, appWidgetId)
@ -113,107 +119,233 @@ class MainWidget : AppWidgetProvider() {
}
private fun updateCalendarView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
val eventRepository = EventRepository(context)
try {
val eventRepository = EventRepository(context)
views.setImageViewBitmap(R.id.empty_date_rect, BitmapHelper.getBitmapFromView(v.empty_date, draw = false))
views.setImageViewBitmap(
R.id.empty_date_rect,
BitmapHelper.getBitmapFromView(v.empty_date, draw = false)
)
views.setViewVisibility(R.id.empty_layout_rect, View.VISIBLE)
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
views.setViewVisibility(R.id.second_row_rect, View.GONE)
views.setViewVisibility(R.id.empty_layout_rect, View.VISIBLE)
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
views.setViewVisibility(R.id.second_row_rect, View.GONE)
val calPIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getCalendarIntent(context), 0)
views.setOnClickPendingIntent(R.id.empty_date_rect, calPIntent)
val calPIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getCalendarIntent(context),
0
)
views.setOnClickPendingIntent(R.id.empty_date_rect, calPIntent)
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
views.setImageViewBitmap(R.id.action_next_rect, BitmapHelper.getBitmapFromView(v.action_next, draw = false))
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
views.setOnClickPendingIntent(R.id.action_next_rect, PendingIntent.getBroadcast(context, widgetID, Intent(context, NewCalendarEventReceiver::class.java).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT }, 0))
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
views.setImageViewBitmap(
R.id.action_next_rect,
BitmapHelper.getBitmapFromView(v.action_next, draw = false)
)
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
views.setOnClickPendingIntent(
R.id.action_next_rect,
PendingIntent.getBroadcast(
context,
widgetID,
Intent(
context,
NewCalendarEventReceiver::class.java
).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT },
0
)
)
views.setImageViewBitmap(R.id.action_previous_rect, BitmapHelper.getBitmapFromView(v.action_previous, draw = false))
views.setViewVisibility(R.id.action_previous_rect, View.VISIBLE)
views.setOnClickPendingIntent(R.id.action_previous_rect, PendingIntent.getBroadcast(context, widgetID, Intent(context, NewCalendarEventReceiver::class.java).apply { action = Actions.ACTION_GO_TO_PREVIOUS_EVENT }, 0))
} else {
views.setViewVisibility(R.id.action_next_rect, View.GONE)
views.setViewVisibility(R.id.action_previous_rect, View.GONE)
views.setImageViewBitmap(
R.id.action_previous_rect,
BitmapHelper.getBitmapFromView(v.action_previous, draw = false)
)
views.setViewVisibility(R.id.action_previous_rect, View.VISIBLE)
views.setOnClickPendingIntent(
R.id.action_previous_rect,
PendingIntent.getBroadcast(
context,
widgetID,
Intent(
context,
NewCalendarEventReceiver::class.java
).apply { action = Actions.ACTION_GO_TO_PREVIOUS_EVENT },
0
)
)
} else {
views.setViewVisibility(R.id.action_next_rect, View.GONE)
views.setViewVisibility(R.id.action_previous_rect, View.GONE)
}
val pIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getEventIntent(context, nextEvent),
0
)
views.setOnClickPendingIntent(R.id.next_event_rect, pIntent)
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, pIntent)
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
views.setImageViewBitmap(
R.id.next_event_difference_time_rect,
BitmapHelper.getBitmapFromView(
v.next_event_difference_time,
draw = false
)
)
views.setViewVisibility(R.id.next_event_difference_time_rect, View.VISIBLE)
} else {
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
}
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
val mapIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address),
0
)
views.setOnClickPendingIntent(R.id.second_row_rect, mapIntent)
} else {
val pIntentDetail = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getEventIntent(
context,
nextEvent,
forceEventDetails = true
),
0
)
views.setOnClickPendingIntent(R.id.second_row_rect, pIntentDetail)
}
views.setImageViewBitmap(
R.id.next_event_rect,
BitmapHelper.getBitmapFromView(v.next_event, draw = false)
)
views.setImageViewBitmap(
R.id.second_row_rect,
BitmapHelper.getBitmapFromView(v.second_row, draw = false)
)
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
} else if (Preferences.showNextAlarm && nextAlarm != "") {
val clockIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getClockIntent(context),
0
)
views.setOnClickPendingIntent(R.id.second_row_rect, clockIntent)
views.setImageViewBitmap(
R.id.next_event_rect,
BitmapHelper.getBitmapFromView(v.next_event, draw = false)
)
views.setImageViewBitmap(
R.id.second_row_rect,
BitmapHelper.getBitmapFromView(v.second_row, draw = false)
)
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
}
val pIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getEventIntent(context, nextEvent), 0)
views.setOnClickPendingIntent(R.id.next_event_rect, pIntent)
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, pIntent)
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
views.setImageViewBitmap(R.id.next_event_difference_time_rect, BitmapHelper.getBitmapFromView(v.next_event_difference_time, draw = false))
views.setViewVisibility(R.id.next_event_difference_time_rect, View.VISIBLE)
} else {
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
}
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
val mapIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address), 0)
views.setOnClickPendingIntent(R.id.second_row_rect, mapIntent)
} else {
views.setOnClickPendingIntent(R.id.second_row_rect, pIntent)
}
views.setImageViewBitmap(R.id.next_event_rect, BitmapHelper.getBitmapFromView(v.next_event, draw = false))
views.setImageViewBitmap(R.id.second_row_rect, BitmapHelper.getBitmapFromView(v.second_row, draw = false))
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
} else if (Preferences.showNextAlarm && nextAlarm != "") {
val clockIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getClockIntent(context), 0)
views.setOnClickPendingIntent(R.id.second_row_rect, clockIntent)
views.setImageViewBitmap(R.id.next_event_rect, BitmapHelper.getBitmapFromView(v.next_event, draw = false))
views.setImageViewBitmap(R.id.second_row_rect, BitmapHelper.getBitmapFromView(v.second_row, draw = false))
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
} catch (ex: Exception) {
FirebaseCrashlytics.getInstance().recordException(ex)
}
return views
}
private fun updateWeatherView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
try {
if (Preferences.showWeather && Preferences.weatherIcon != "") {
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
views.setViewVisibility(R.id.calendar_weather_rect, View.VISIBLE)
if (Preferences.showWeather && Preferences.weatherIcon != "") {
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
views.setViewVisibility(R.id.calendar_weather_rect, View.VISIBLE)
val i = Intent(context, WidgetClickListenerReceiver::class.java)
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0)
val i = Intent(context, WidgetClickListenerReceiver::class.java)
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0)
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
views.setOnClickPendingIntent(R.id.calendar_weather_rect, weatherPIntent)
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
views.setOnClickPendingIntent(R.id.calendar_weather_rect, weatherPIntent)
views.setImageViewBitmap(
R.id.weather_rect,
BitmapHelper.getBitmapFromView(v.weather, draw = false)
)
views.setImageViewBitmap(R.id.weather_rect, BitmapHelper.getBitmapFromView(v.weather, draw = false))
views.setImageViewBitmap(R.id.calendar_weather_rect, BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false))
} else {
views.setViewVisibility(R.id.weather_rect, View.GONE)
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
views.setImageViewBitmap(
R.id.calendar_weather_rect,
BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false)
)
} else {
views.setViewVisibility(R.id.weather_rect, View.GONE)
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
}
} catch (ex: Exception) {
FirebaseCrashlytics.getInstance().recordException(ex)
}
return views
}
private fun updateClockView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews {
if (!Preferences.showClock) {
views.setViewVisibility(R.id.time, View.GONE)
} else {
views.setTextColor(R.id.time, ColorHelper.getFontColor())
views.setTextViewTextSize(R.id.time, TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(context))
val clockPIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getClockIntent(context), 0)
views.setOnClickPendingIntent(R.id.time, clockPIntent)
views.setViewVisibility(R.id.time, View.VISIBLE)
try {
if (!Preferences.showClock) {
views.setViewVisibility(R.id.time, View.GONE)
views.setViewVisibility(R.id.clock_bottom_margin_none, View.GONE)
views.setViewVisibility(R.id.clock_bottom_margin_small, View.GONE)
views.setViewVisibility(R.id.clock_bottom_margin_medium, View.GONE)
views.setViewVisibility(R.id.clock_bottom_margin_large, View.GONE)
} else {
views.setTextColor(R.id.time, ColorHelper.getFontColor())
views.setTextViewTextSize(
R.id.time,
TypedValue.COMPLEX_UNIT_SP,
Preferences.clockTextSize.toPixel(context)
)
val clockPIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getClockIntent(context),
0
)
views.setOnClickPendingIntent(R.id.time, clockPIntent)
views.setViewVisibility(R.id.time, View.VISIBLE)
views.setViewVisibility(
R.id.clock_bottom_margin_none,
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.clock_bottom_margin_small,
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.clock_bottom_margin_medium,
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.clock_bottom_margin_large,
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value) View.VISIBLE else View.GONE
)
}
} catch (ex: Exception) {
FirebaseCrashlytics.getInstance().recordException(ex)
}
return views

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M7.29,7c0.45,0 0.67,-0.54 0.35,-0.85l-2.29,-2.3c-0.2,-0.2 -0.51,-0.2 -0.71,0l-2.29,2.3c-0.31,0.31 -0.09,0.85 0.36,0.85L4,7v10L2.71,17c-0.45,0 -0.67,0.54 -0.35,0.85l2.29,2.29c0.2,0.2 0.51,0.2 0.71,0l2.29,-2.29c0.31,-0.31 0.09,-0.85 -0.36,-0.85L6,17L6,7h1.29zM11,7h10c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1L11,5c-0.55,0 -1,0.45 -1,1s0.45,1 1,1zM21,17L11,17c-0.55,0 -1,0.45 -1,1s0.45,1 1,1h10c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1zM21,11L11,11c-0.55,0 -1,0.45 -1,1s0.45,1 1,1h10c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M11,8.75v3.68c0,0.35 0.19,0.68 0.49,0.86l3.12,1.85c0.36,0.21 0.82,0.09 1.03,-0.26c0.21,-0.36 0.1,-0.82 -0.26,-1.03l-2.87,-1.71v-3.4C12.5,8.34 12.16,8 11.75,8S11,8.34 11,8.75zM21,9.5V4.21c0,-0.45 -0.54,-0.67 -0.85,-0.35l-1.78,1.78c-1.81,-1.81 -4.39,-2.85 -7.21,-2.6c-4.19,0.38 -7.64,3.75 -8.1,7.94C2.46,16.4 6.69,21 12,21c4.59,0 8.38,-3.44 8.93,-7.88c0.07,-0.6 -0.4,-1.12 -1,-1.12c-0.5,0 -0.92,0.37 -0.98,0.86c-0.43,3.49 -3.44,6.19 -7.05,6.14c-3.71,-0.05 -6.84,-3.18 -6.9,-6.9C4.94,8.2 8.11,5 12,5c1.93,0 3.68,0.79 4.95,2.05l-2.09,2.09C14.54,9.46 14.76,10 15.21,10h5.29C20.78,10 21,9.78 21,9.5z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -76,22 +76,7 @@
android:id="@+id/widget"
android:alpha="0"
android:gravity="center">
<TextClock
android:id="@+id/clock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:lineSpacingMultiplier="1"
android:lineSpacingExtra="0dp"
android:includeFontPadding="false"
android:visibility="gone"
android:padding="0dp"
style="@style/AnotherWidget.Title" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/widget_bitmap"
tools:ignore="ContentDescription" />
<include layout="@layout/the_widget_sans" />
</LinearLayout>
<ProgressBar
android:layout_width="48dp"

View File

@ -203,7 +203,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_event_note"
android:src="@drawable/round_code"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
@ -371,6 +371,43 @@
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_open_event_details"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_event_note"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_event_app_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/open_event_details_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -408,43 +445,6 @@
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_event_app"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_add_to_home_screen"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_event_app_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/event_app_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@ -152,13 +152,13 @@
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_show_next_alarm"
android:id="@+id/action_clock_bottom_margin_size"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_alarm"
android:src="@drawable/round_format_line_spacing"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
@ -170,11 +170,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_show_next_alarm_title"/>
android:text="@string/settings_clock_bottom_margin_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/show_next_alarm_label"
android:id="@+id/clock_bottom_margin_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
@ -215,27 +215,64 @@
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_show_next_alarm"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_alarm"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/small_clock_warning"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:paddingBottom="32dp"
android:duplicateParentState="true"
android:textSize="14sp"
android:text="@string/clock_warning"
android:textColor="@color/colorPrimaryText"
android:letterSpacing="0"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:textAllCaps="false" />
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_show_next_alarm_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/show_next_alarm_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/small_clock_warning"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:paddingBottom="32dp"
android:duplicateParentState="true"
android:textSize="14sp"
android:text="@string/clock_warning"
android:textColor="@color/colorPrimaryText"
android:letterSpacing="0"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:textAllCaps="false" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</layout>

View File

@ -250,7 +250,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_schedule"
android:src="@drawable/round_update"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"

View File

@ -19,8 +19,32 @@
android:visibility="gone"
android:lines="1"
android:maxLines="1"
android:layout_marginBottom="16dp"
style="@style/AnotherWidget.Title"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="-16dp"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_none" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="-8dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_small" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="2dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_medium" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="10dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_large" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
@ -108,7 +132,7 @@
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:scaleType="fitCenter"
android:id="@+id/bitmap_container"/>
</RelativeLayout>

View File

@ -0,0 +1,201 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="add_widget">Widget hinzufügen</string>
<string name="button_request_permission">Rechte erteilen</string>
<string name="title_permission_calendar">Sehen Sie Ihre Termine</string>
<string name="title_permission_location">Kontrolliere das Wetter</string>
<string name="description_permission_calendar">Gewähren Sie Zugriff auf Ihren Kalender, um Ereignisse in Ihrem
Widget anzuzeigen.\n\t
</string>
<string name="description_permission_location">Gewähren Sie Zugriff auf Ihren Ort, um das Wetter in Ihrem Widget
anzuzeigen.\n\t
</string>
<string name="settings_filter_calendar_title">Veranstaltungen filtern</string>
<string name="action_share">Teilen</string>
<string name="action_rate">App bewertern</string>
<string name="action_support">Ünterstützten Sie mich</string>
<string name="all_set_title">Gut gemacht!</string>
<string name="notification_subtitle">Sehen Sie sich Ihre Ereignisse und das Wetter in einem anderen Widget an.
</string>
<string name="notification_title">Holen Sie mehr aus Ihrem Widget heraus</string>
<string name="all_set_subtitle">Sie haben die Konfiguration abgeschlossen. Achten Sie auf Updates.</string>
<string name="all_set_btn">Bleiben Sie aktuell</string>
<string name="action_about">Über</string>
<string name="h_code">Std</string>
<string name="min_code">" Min"</string>
<string name="in_code">in</string>
<string name="action_project">Projekt</string>
<string name="settings_unit_title">Messeinheit</string>
<string name="settings_unit_subtitle">Wählen Sie die Einheit der Temperaturmessung</string>
<string name="settings_filter_calendar_subtitle">Sichtbarkeit der Kalender</string>
<string name="settings_all_day_title">Ganztag-Veranstaltungen</string>
<string name="settings_all_day_subtitle_visible">Sichtbar</string>
<string name="settings_all_day_subtitle_gone">Nicht sichtbar</string>
<string name="main_calendar">Kalender-Account</string>
<string name="settings_calendar_title">Kalender-Einstellungen</string>
<string name="settings_weather_title">Wetter-Einstellungen</string>
<string name="settings_general_title">Allgemeine Einstellungen</string>
<string name="calendar_settings_list_error">Fehler beim Laden der Kalenderliste</string>
<string name="settings_hour_format_title">Stundenformat</string>
<string name="settings_hour_format_subtitle_12">12 Stunden AM/PM</string>
<string name="settings_hour_format_subtitle_24">24 Stunden</string>
<string name="all_day">Ganztag-Veranstaltung</string>
<string name="settings_date_format_title">Datumsformat</string>
<string name="settings_weather_refresh_period_title">Aktualisierungszeitraum</string>
<string name="settings_weather_refresh_period_subtitle_0">30 Minuten</string>
<string name="settings_weather_refresh_period_subtitle_1">1 Stunde</string>
<string name="settings_weather_refresh_period_subtitle_2">3 Stunden</string>
<string name="settings_weather_refresh_period_subtitle_3">6 Stunden</string>
<string name="settings_weather_refresh_period_subtitle_4">12 Stunden</string>
<string name="settings_weather_refresh_period_subtitle_5">24 Stunden</string>
<string name="settings_custom_location_title">" Benutzerdefinierte Position"</string>
<string name="custom_location_gps">Geo-Lokalisierung</string>
<string name="action_refresh_widget">Widget erneuern</string>
<string name="show_events_visible">Veranstaltungen sind sichtbar</string>
<string name="show_events_not_visible">Veranstaltungen sind nicht sichtbar</string>
<string name="show_weather_visible">Wetterinfos sind sichtbar</string>
<string name="show_weather_not_visible">Wetterinfos sind nicht sichtbar</string>
<string name="settings_show_until_subtitle_0">3 Stunden später</string>
<string name="settings_show_until_subtitle_1">6 Stunden später</string>
<string name="settings_show_until_subtitle_2">12 Stunden später</string>
<string name="settings_show_until_subtitle_3">24 Stunden später</string>
<string name="settings_show_until_subtitle_4">3 Tage später</string>
<string name="settings_show_until_subtitle_5">7 Tage später</string>
<string name="settings_show_until_title">Sehen Sie die Ereignisse höchstens bis</string>
<string name="day_char">T</string>
<string name="error_opening_uri">Fehler beim Öffnen der URL: Link in die Zwischenablage kopiert.</string>
<string name="loading_text">Daten werden geladen...</string>
<string name="error_opening_app">Fehler beim Öffnen der App.</string>
<string name="settings_calendar_app_title">Standard Kalender-App</string>
<string name="settings_weather_app_title">Beim Klick auf\'s Wetter öffnet sich</string>
<string name="default_name">Standardapp</string>
<string name="action_choose_application">App wählen</string>
<string name="settings_weather_provider_api_key_title">Wetter-Anbieter</string>
<string name="settings_weather_provider_api_key_subtitle_all_set">Der Wetteranbieter ist korrekt konfiguriert
</string>
<string name="settings_weather_provider_api_key_subtitle_not_set">Der Wetteranbieter muss konfiguriert werden
</string>
<string name="notification_gps_title">GPS einschalten</string>
<string name="notification_gps_subtitle">Google Awareness benötigt aktives GPS zum Arbeiten.</string>
<string name="action_feedback">Rückmeldung</string>
<string name="feedback_title">AW Rückmeldung</string>
<string name="feedback_chooser_title">E-Mail senden...</string>
<string name="feedback_error">Fehler beim Senden der E-Mail.</string>
<string name="api_key_hint">OpenWeather API Key</string>
<string name="action_save">Speichern</string>
<string name="error_no_calendar">Keine Kalender gefunden</string>
<string name="api_key_info_title">Was ist zu tun</string>
<string name="api_key_info_text">
<![CDATA[Another Widget ist eine kostenlose Anwendung und wird ohne Bannerwerbung bleiben.<BR /> <BR />Aufgrund seines großen Erfolges, der sicherlich meine Erwartungen übertrifft, unterstützt der Wetteranbieter nicht alle ankommenden Anfragen (einfach, weil es kostenlos und daher begrenzt ist).<BR /><BR />Ich muss jeden von Ihnen bitten, ein Konto bei OpenWeather persönlich zu registrieren. Der Vorgang dauert nur ein paar Minuten, und wenn der Schlüssel aktiviert ist, haben Sie keine Probleme mit dem Wetter.<BR /><BR />Ich entschuldige mich für die Unannehmlichkeiten und stütze mich weiter!]]></string>
<string name="api_key_title_1">Registrierung eines OpenWeather Kontos</string>
<string name="api_key_subtitle_1">Registrieren Sie ein kostenloses Konto bei OpenWeather. Es wird nur ein paar
Minuten dauern.
</string>
<string name="api_key_title_2">API-Key kopieren</string>
<string name="api_key_subtitle_2">Greifen Sie über Ihre Kontoeinstellungen auf das API-Schlüsselmenü zu und kopieren
Sie den Standardschlüssel.
</string>
<string name="api_key_title_3">Fügen Sie den Schlüssel zur App hinzu</string>
<string name="api_key_subtitle_3">Geben Sie den Schlüssel in diesem Abschnitt ein und speichern Sie ihn. Sobald der
Schlüssel aktiviert ist, ist das Wetter sichtbar.
</string>
<string name="api_key_info_start">Hi zusammen!</string>
<string name="action_open_provider">Öffnen von OpenWeatherMap.com</string>
<string name="api_key_info_all_set">
<![CDATA[Es kann bis zu <b> zehn Minuten </b> dauern, bis der API-Schlüssel aktiviert wird.<BR /><i> Entspannen </ i> Sie! Das Wetter wird aktualisiert, sobald es verfügbar ist !!]]></string>
<string name="well_done">Gut gemacht!</string>
<string name="hs_code">Std</string>
<string name="tomorrow">Morgen</string>
<string name="today">Heute</string>
<string name="settings_event_app_title">Klick auf die Veranstaltung öffnet</string>
<string name="settings_second_row_info_title">Informationen der zweiten Reihe</string>
<string name="settings_font_color_title">Textfarbe</string>
<string name="title_main_text_size">Schriftgröße erste Reihe</string>
<string name="title_second_text_size">Schriftgröße zweite Reihe</string>
<string name="settings_clock_title">Einstellung der Uhr</string>
<string name="settings_second_row_info_subtitle_1">Zeige Ereignisadresse anstelle von Zeit</string>
<string name="settings_second_row_info_subtitle_0">Zeige Ereignisszeit</string>
<string name="settings_second_row_info_subtitle_2">Zeige nächste Erinnerung</string>
<string name="settings_clock_app_title">Klick der Uhr öffnet</string>
<string name="title_show_clock">Uhr anzeigen</string>
<string name="description_show_clock">Zeigt die Zeit über Ereignisse und Wetter an</string>
<string name="show_clock_visible">Uhr ist sichtbar</string>
<string name="show_clock_not_visible">Uhr ist nicht sichtbar</string>
<string name="settings_clock_text_size_title">Schriftgrößte der Uhr</string>
<string name="title_text_shadow">Schatten des Textes</string>
<string name="settings_text_shadow_subtitle_none">Keins</string>
<string name="settings_text_shadow_subtitle_low">Niedrig</string>
<string name="settings_text_shadow_subtitle_high">Hoch</string>
<string name="advanced_settings_title">Erweiterte Einstellungen</string>
<string name="settings_product_sans_font_title">Product Sans Font</string>
<string name="settings_product_sans_font_subtitle">Durch die Verwendung von Product Sans wurde die Möglichkeit zum
Antippen von Widget-Elementen deaktiviert. Ich arbeite dran.
</string>
<string name="settings_show_diff_time_title">Zeit für die Veranstaltung</string>
<string name="settings_visible">Sichtbar</string>
<string name="settings_not_visible">Nicht sichtbar</string>
<string name="settings_show_declined_events_title">Abgelehnte Ereignisse</string>
<string name="default_weather_app">Google Wetter</string>
<string name="default_event_app">Veranstalungsdetails</string>
<string name="default_calendar_app">Standard Kalender-App</string>
<string name="default_clock_app">Standard Uhr-App</string>
<string name="settings_show_until_subtitle_7">1 Stunde später</string>
<string name="settings_show_until_subtitle_6">30 Minuten später</string>
<string name="action_default">Default</string>
<string name="action_none">Deaktiviert</string>
<string name="settings_custom_font_title">Widget Schriftart</string>
<string name="custom_font_subtitle_0">Geräte Schriftart</string>
<string name="custom_font_subtitle_1">Produkt Schriftart</string>
<string name="action_go_to_next_event">Zeige nächste Veranstaltung</string>
<string name="settings_show_multiple_events_title">Zähler für mehrere Ereignisse</string>
<string name="support_main_title">Unterstütze den Entwickler mit</string>
<string name="support_translations_title">Bei der Übersetzung helfen</string>
<string name="support_translations_subtitle">Öffne einen pull request auf GitHub</string>
<string name="support_website_title">Schauen Sie sich meine anderen Projekte an</string>
<string name="support_website_subtitle">Selber Entwickler, mehr Möglichkeiten</string>
<string name="error">Ops, da ist etwas falsch gelaufen!</string>
<string name="thanks">Danke für Ihre Unterstützung</string>
<string name="donation_coffee">Einen italenischen Kaffee</string>
<string name="donation_donuts">Einige glasierte Donuts</string>
<string name="donation_dinner">Ein teueres Abendessen</string>
<string name="donation_breakfast">Ein englischen Frühstück</string>
<string name="donation_lunch">Ein schnelles Mittagsessen</string>
<string name="background_service_title">Another Widget läuft</string>
<string name="background_service_subtitle">AW läuft im Hintergrund</string>
<string name="action_show_widget_preview">Zeige die Widget Vorschau</string>
<string name="action_hide_widget_preview">Verstecke die Widget Vorschau</string>
<string name="error_widget_notification_title">GPS ist aus</string>
<string name="error_widget_notification_subtitle">GPS wieder aktivieren, damit ein Another Widget
Wetterinformationen mit der Google Awareness API aktualisieren kann.
</string>
<!-- TODO -->
<string name="error_weather_api_key">The provider is not configured correctly, do you still want to go back?</string>
<string name="settings_show_next_alarm_title">Show next alarm when possible</string>
<string name="open_location_settings">Location settings</string>
<string name="change_provider">Change provider</string>
<string name="disable_notification">Disable notification</string>
<string name="settings_theme_title">Theme</string>
<string name="support_main_subtitle">Devs always need a lot of coffee</string>
<string name="settings_subtitle_dark_theme_light">Light</string>
<string name="settings_subtitle_dark_theme_dark">Dark</string>
<string name="settings_subtitle_dark_theme_by_battery_saver">Set by Battery Saver</string>
<string name="settings_subtitle_dark_theme_follow_system">Follow the system theme</string>
<string name="settings_subtitle_dark_theme_default">Default</string>
<string name="search">Search</string>
<string name="settings_title_show_wallpaper">Show wallpaper</string>
<string name="support_refresh_widget_subtitle">Force the restart of the widget service</string>
<string name="account_events">Account events</string>
<string name="clock_warning">Due to technological limitations, the clock won\'t have the custom font and the text shadows selected in the typography section.</string>
<string name="weather_warning">Google Awareness weather has been deprecated. It\'s now required an OpenWeather API key to show the weather in the widget.</string>
<string name="custom_date_format">Custom date format</string>
<string name="settings_app_version_title">App version</string>
<string name="support_dev_subtitle">This is a single developer project,\nso thank you for the support!</string>
<string name="settings_feedback_subtitle">This is an open-source project, feel free to help.</string>
<string name="settings_feedback_title">Feedback and feature requests</string>
<string name="settings_clock_bottom_margin_title">Clock bottom margin</string>
<string name="settings_clock_bottom_margin_subtitle_none">None</string>
<string name="settings_clock_bottom_margin_subtitle_small">Small</string>
<string name="settings_clock_bottom_margin_subtitle_medium">Medium</string>
<string name="settings_clock_bottom_margin_subtitle_large">Large</string>
</resources>

View File

@ -60,7 +60,7 @@
<string name="error_opening_uri">Erreur lors de l\'ouverture de l\'URL : Lien copié dans le presse-papiers.</string>
<string name="loading_text">Chargement des données…</string>
<string name="error_opening_app">Erreur lors de l\'ouverture de l\'app.</string>
<string name="settings_calendar_app_title">Taper sur la date ouvre</string>
<string name="settings_calendar_app_title">App calendrier par défaut</string>
<string name="settings_weather_app_title">Taper sur la météo ouvre</string>
<string name="default_name">App par défaut</string>
<string name="action_choose_application">Choisir une application</string>
@ -86,7 +86,7 @@
<string name="api_key_title_3">Saisissez la clé dans l\'app</string>
<string name="api_key_subtitle_3">Collez la clé dans le champ ci-dessus et enregistrez-la. Une fois la clé activée, la météo deviendra visible.</string>
<string name="api_key_info_start">Bonjour tout le monde !</string>
<string name="action_open_provider">Aller sur le site d\'OpenWeather</string>
<string name="action_open_provider">Aller sur le site d\'OpenWeatherMap</string>
<string name="api_key_info_all_set"><![CDATA[Cela peut prendre jusqu\'à <b> 10 minutes </b> avant que votre clé API soit activée. La météo sera mise à jour dès qu\'elle sera disponible !]]></string>
<string name="well_done">Bien joué !</string>
<string name="hs_code">h</string>
@ -120,7 +120,7 @@
<string name="settings_not_visible">Non visible</string>
<string name="settings_show_declined_events_title">Événements refusés</string>
<string name="default_weather_app">Google Weather</string>
<string name="default_event_app">Détails de l\'événement dans Google Agenda</string>
<string name="default_event_app">Détails de l\'événement</string>
<string name="default_calendar_app">App calendrier par défaut</string>
<string name="default_clock_app">App horloge par défaut</string>
<string name="settings_show_until_subtitle_7">1 heure après</string>
@ -171,4 +171,9 @@
<string name="support_dev_subtitle">Ceci est un projet de développeur unique,\ndonc merci pour le soutien!</string>
<string name="settings_feedback_subtitle">Ceci est un projet open-source, n\'hésitez pas à aider.</string>
<string name="settings_feedback_title">Commentaires et suggestions</string>
<string name="settings_clock_bottom_margin_title">Marge inférieure de l\'horloge</string>
<string name="settings_clock_bottom_margin_subtitle_none">Aucun</string>
<string name="settings_clock_bottom_margin_subtitle_small">Petit</string>
<string name="settings_clock_bottom_margin_subtitle_medium">Moyen</string>
<string name="settings_clock_bottom_margin_subtitle_large">Grand</string>
</resources>

View File

@ -61,7 +61,7 @@
<string name="error_opening_uri">Errore apertura URL: Link copiato negli appunti.</string>
<string name="loading_text">Caricamento…</string>
<string name="error_opening_app">Errore apertura App.</string>
<string name="settings_calendar_app_title">La data apre</string>
<string name="settings_calendar_app_title">Applicazione predefinita calendario</string>
<string name="settings_weather_app_title">Il meteo apre</string>
<string name="default_name">App Predefinita</string>
<string name="action_choose_application">Scegli Applicazione</string>
@ -80,8 +80,8 @@
<string name="error_no_calendar">Nessun calendario trovato.</string>
<string name="api_key_info_title">Cosa fare</string>
<string name="api_key_title_1">Registrati su OpenWeather</string>
<string name="action_open_provider">Apri OpenWeather.com</string>
<string name="api_key_subtitle_1">Registra un account gratuito su OpenWeather.com in pochi minuti.</string>
<string name="action_open_provider">Apri OpenWeatherMap.com</string>
<string name="api_key_subtitle_1">Registra un account gratuito su OpenWeatherMap.com in pochi minuti.</string>
<string name="api_key_subtitle_2">Accedi alle chiavi API nelle impostazioni e copia la chiave di default.</string>
<string name="api_key_subtitle_3">Aggiungi la chiave all\'applicazione in questa sezione e, una volta che la chiave sarà attivata, apparirà il meteo.</string>
<string name="api_key_title_2">Copia la chiave API</string>
@ -120,7 +120,7 @@
<string name="settings_show_declined_events_title">Event Rifiutati</string>
<string name="settings_visible">Visibile</string>
<string name="settings_not_visible">Non Visibile</string>
<string name="default_event_app">Dettagli Evento Google Calendar</string>
<string name="default_event_app">Dettagli evento</string>
<string name="default_calendar_app">App Calendario di Default</string>
<string name="default_weather_app">Meteo Google</string>
<string name="default_clock_app">App Orologio di Default</string>
@ -172,4 +172,9 @@
<string name="support_dev_subtitle">Grazie per supportare il progetto!</string>
<string name="settings_feedback_subtitle">Contribuisci a questo progetto open source.</string>
<string name="settings_feedback_title">Feedback</string>
<string name="settings_clock_bottom_margin_title">Margine inferiore orologio</string>
<string name="settings_clock_bottom_margin_subtitle_none">Nessuno</string>
<string name="settings_clock_bottom_margin_subtitle_small">Piccolo</string>
<string name="settings_clock_bottom_margin_subtitle_medium">Medio</string>
<string name="settings_clock_bottom_margin_subtitle_large">Grande</string>
</resources>

View File

@ -66,7 +66,7 @@
<string name="error_opening_uri">Error opening URL: Link copied to clipboard.</string>
<string name="loading_text">Loading Data…</string>
<string name="error_opening_app">Error opening app.</string>
<string name="settings_calendar_app_title">Tap on date opens</string>
<string name="settings_calendar_app_title">Calendar default application</string>
<string name="settings_weather_app_title">Tap on weather opens</string>
<string name="default_name">Default app</string>
<string name="action_choose_application">Choose application</string>
@ -93,7 +93,7 @@
<string name="api_key_title_3">Enter the key to the app</string>
<string name="api_key_subtitle_3">Paste the key into the field above and save it. Once the key is activated the weather will become visible.</string>
<string name="api_key_info_start">Hi Everyone!</string>
<string name="action_open_provider">Go to OpenWeather.com</string>
<string name="action_open_provider">Go to OpenWeatherMap.com</string>
<string name="api_key_info_all_set"><![CDATA[It may take up to <b>ten minutes</b> before your API key is activated. The weather will be updated as soon as it is available!]]></string>
<string name="well_done">Well Done!</string>
<string name="hs_code">h</string>
@ -125,12 +125,12 @@
<string name="beta" translatable="false">Beta</string>
<string name="settings_product_sans_font_title">Product Sans Font</string>
<string name="settings_product_sans_font_subtitle">Using Product Sans disabled the possibility to tap widget elements. I\'m working on it.</string>
<string name="settings_show_diff_time_title">Time left in the event</string>
<string name="settings_show_diff_time_title">Time left to the event</string>
<string name="settings_visible">Visible</string>
<string name="settings_not_visible">Hidden</string>
<string name="settings_show_declined_events_title">Declined events</string>
<string name="default_weather_app">Google Weather</string>
<string name="default_event_app">Google Calendar event details</string>
<string name="default_event_app">Event details</string>
<string name="default_calendar_app">Default calendar app</string>
<string name="default_clock_app">Default clock app</string>
<string name="settings_show_until_subtitle_7">1 hour later</string>
@ -183,4 +183,9 @@
<string name="settings_feedback_subtitle">This is an open-source project, feel free to help.</string>
<string name="settings_feedback_title">Feedback and feature requests</string>
<string name="title_tasksintegration" translatable="false">Google Tasks</string>
<string name="settings_clock_bottom_margin_title">Clock bottom margin</string>
<string name="settings_clock_bottom_margin_subtitle_none">None</string>
<string name="settings_clock_bottom_margin_subtitle_small">Small</string>
<string name="settings_clock_bottom_margin_subtitle_medium">Medium</string>
<string name="settings_clock_bottom_margin_subtitle_large">Large</string>
</resources>

View File

@ -10,5 +10,5 @@
android:minResizeWidth="300dp"
android:previewImage="@drawable/widget_preview"
android:resizeMode="vertical|horizontal"
android:updatePeriodMillis="60000"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen" />

BIN
google-play-badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
hero.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -3,8 +3,8 @@
xmlns:dist="http://schemas.android.com/apk/distribution"
featureSplit="tasksintegration"
package="com.tommasoberlose.anotherwidget"
android:versionCode="59"
android:versionName="2.0.4" >
android:versionCode="64"
android:versionName="2.0.5" >
<uses-sdk
android:minSdkVersion="23"

View File

@ -1 +1 @@
#Mon May 04 02:02:08 CEST 2020
#Mon May 04 20:02:45 CEST 2020

View File

@ -1,4 +1,4 @@
#Mon May 04 15:26:16 CEST 2020
#Tue May 05 14:08:04 CEST 2020
base.0=/Users/tommaso/Documents/MyCode/another-widget/tasksintegration/build/intermediates/dex/debug/mergeProjectDexDebug/out/classes.dex
path.0=classes.dex
renamed.0=classes.dex

View File

@ -4,8 +4,8 @@
featureSplit="tasksintegration"
package="com.tommasoberlose.anotherwidget"
android:targetSandboxVersion="2"
android:versionCode="59"
android:versionName="2.0.4" >
android:versionCode="64"
android:versionName="2.0.5" >
<uses-sdk
android:minSdkVersion="23"

View File

@ -3,8 +3,8 @@
3 xmlns:dist="http://schemas.android.com/apk/distribution"
4 featureSplit="tasksintegration"
5 package="com.tommasoberlose.anotherwidget"
6 android:versionCode="59"
7 android:versionName="2.0.4" >
6 android:versionCode="64"
7 android:versionName="2.0.5" >
8
9 <uses-sdk
10 android:minSdkVersion="23"

View File

@ -3,8 +3,8 @@
xmlns:dist="http://schemas.android.com/apk/distribution"
featureSplit="tasksintegration"
package="com.tommasoberlose.anotherwidget"
android:versionCode="59"
android:versionName="2.0.4" >
android:versionCode="64"
android:versionName="2.0.5" >
<uses-sdk
android:minSdkVersion="23"

View File

@ -3,8 +3,8 @@
xmlns:dist="http://schemas.android.com/apk/distribution"
featureSplit="tasksintegration"
package="com.tommasoberlose.anotherwidget"
android:versionCode="59"
android:versionName="2.0.4" >
android:versionCode="64"
android:versionName="2.0.5" >
<uses-sdk android:targetSdkVersion="29" />