diff --git a/app/build.gradle b/app/build.gradle index 9f732b1..7aa2b7a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,6 +6,8 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' +apply plugin: 'io.fabric' + android { compileSdkVersion 26 buildToolsVersion "26.0.2" @@ -13,7 +15,7 @@ android { applicationId "com.tommasoberlose.anotherwidget" minSdkVersion 19 targetSdkVersion 26 - versionCode 5 + versionCode 11 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } @@ -23,9 +25,6 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - dataBinding { - enabled = true - } } dependencies { @@ -42,6 +41,11 @@ dependencies { compile 'com.mcxiaoke.volley:library:1.0.6@aar' compile 'com.android.support:customtabs:26.1.0' compile 'com.android.support:cardview-v7:26.1.0' - compile 'com.heinrichreimersoftware:material-intro:1.6.2' kapt 'com.android.databinding:compiler:2.3.3' + compile('com.crashlytics.sdk.android:crashlytics:2.7.0@aar') { + transitive = true; + } + compile 'com.android.support:design:26.1.0' + compile 'com.github.rubensousa:bottomsheetbuilder:1.6.0' + compile 'com.github.johnhiott:DarkSkyApi:v0.1.5' } diff --git a/app/fabric.properties b/app/fabric.properties new file mode 100644 index 0000000..ec998b0 --- /dev/null +++ b/app/fabric.properties @@ -0,0 +1,3 @@ +#Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public. +#Wed Oct 11 22:01:24 CEST 2017 +apiSecret=df2efbce5a4f9101ba6923b7dfa5725a5283ee08c3e748ccfafb01a5070bb532 diff --git a/app/release/output.json b/app/release/output.json index 76b5fcc..53a2cf9 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":5},"path":"app-release.apk","properties":{"packageId":"com.tommasoberlose.anotherwidget","split":"","minSdkVersion":"19"}}] \ No newline at end of file +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":11},"path":"app-release.apk","properties":{"packageId":"com.tommasoberlose.anotherwidget","split":"","minSdkVersion":"19"}}] \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 48a41b4..83723f1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,7 +4,7 @@ - + @@ -41,6 +41,7 @@ android:priority="1000"> + @@ -51,6 +52,9 @@ android:exported="false"> + + + + + - + + + \ No newline at end of file diff --git a/app/src/main/assets/fonts/product_sans_bold.ttf b/app/src/main/assets/fonts/product_sans_bold.ttf new file mode 100755 index 0000000..d847195 Binary files /dev/null and b/app/src/main/assets/fonts/product_sans_bold.ttf differ diff --git a/app/src/main/assets/fonts/product_sans_bold_italic.ttf b/app/src/main/assets/fonts/product_sans_bold_italic.ttf new file mode 100755 index 0000000..129d12d Binary files /dev/null and b/app/src/main/assets/fonts/product_sans_bold_italic.ttf differ diff --git a/app/src/main/assets/fonts/product_sans_italic.ttf b/app/src/main/assets/fonts/product_sans_italic.ttf new file mode 100755 index 0000000..5fc56d4 Binary files /dev/null and b/app/src/main/assets/fonts/product_sans_italic.ttf differ diff --git a/app/src/main/assets/fonts/product_sans_regular.ttf b/app/src/main/assets/fonts/product_sans_regular.ttf new file mode 100755 index 0000000..c0442ee Binary files /dev/null and b/app/src/main/assets/fonts/product_sans_regular.ttf differ diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/object/Constants.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/object/Constants.kt index 4aaddec..2aaecad 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/object/Constants.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/object/Constants.kt @@ -1,5 +1,6 @@ package com.tommasoberlose.anotherwidget.`object` +import android.annotation.SuppressLint import java.text.SimpleDateFormat import java.util.* @@ -7,10 +8,13 @@ import java.util.* * Created by tommaso on 05/10/17. */ +@SuppressLint("SimpleDateFormat") object Constants { val CALENDAR_REQUEST_CODE = 1 val LOCATION_REQUEST_CODE = 2 + val RESULT_CODE_CUSTOM_LOCATION = 45 + val PREF_FIRST_STEP = "PREF_FIRST_STEP" val PREF_WEATHER_ICON = "PREF_WEATHER_ICON" val PREF_WEATHER_TEMP = "PREF_WEATHER_TEMP" @@ -21,12 +25,22 @@ object Constants { val PREF_NEXT_EVENT_ID = "PREF_NEXT_EVENT_ID" val PREF_NEXT_EVENT_NAME = "PREF_NEXT_EVENT_NAME" val PREF_NEXT_EVENT_START_DATE = "PREF_NEXT_EVENT_START_DATE" + val PREF_NEXT_EVENT_ALL_DAY = "PREF_NEXT_EVENT_ALL_DAY" val PREF_NEXT_EVENT_END_DATE = "PREF_NEXT_EVENT_END_DATE" val PREF_NEXT_EVENT_CALENDAR_ID = "PREF_NEXT_EVENT_CALENDAR_ID" + val PREF_CUSTOM_LOCATION_LAT = "PREF_CUSTOM_LOCATION_LAT" + val PREF_CUSTOM_LOCATION_LON = "PREF_CUSTOM_LOCATION_LON" + val PREF_CUSTOM_LOCATION_ADD = "PREF_CUSTOM_LOCATION_ADD" + val PREF_HOUR_FORMAT = "PREF_HOUR_FORMAT" + val PREF_ITA_FORMAT_DATE = "PREF_ITA_FORMAT_DATE" + val PREF_WEATHER_REFRESH_PERIOD = "PREF_WEATHER_REFRESH_PERIOD" - val dateFormat = SimpleDateFormat("EEEE, MMM d", Locale.getDefault()) - val hourFormat = SimpleDateFormat("HH:mm", Locale.getDefault()) + val itDateFormat = SimpleDateFormat("EEEE, d MMM") + val engDateFormat = SimpleDateFormat("EEEE, MMM d") + val goodHourFormat = SimpleDateFormat("HH:mm") + val badHourFormat = SimpleDateFormat("KK:mm aa") val ACTION_TIME_UPDATE = "com.tommasoberlose.anotherwidget.action.ACTION_TIME_UPDATE" + val ACTION_CALENDAR_UPDATE = "com.tommasoberlose.anotherwidget.action.ACTION_CALENDAR_UPDATE" val ACTION_WEATHER_UPDATE = "com.tommasoberlose.anotherwidget.action.ACTION_WEATHER_UPDATE" } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/object/Event.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/object/Event.kt index ebbbd27..e626fe9 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/object/Event.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/object/Event.kt @@ -14,13 +14,15 @@ class Event { var startDate: Long = 0 var endDate: Long = 0 var calendarID: Int = 0 + var allDay: Boolean = false - constructor(id:Int, title:String, startDate:Long, endDate:Long, calendarID: Int) { + constructor(id:Int, title:String, startDate:Long, endDate:Long, calendarID: Int, allDay: Boolean) { this.id = id this.title = title this.startDate = startDate this.endDate = endDate this.calendarID = calendarID + this.allDay = allDay } constructor(eventCursor: Cursor, instanceCursor: Cursor) { @@ -29,6 +31,7 @@ class Event { endDate = instanceCursor.getLong(2) title = eventCursor.getString(0) + allDay = !eventCursor.getString(1).equals("0") calendarID = eventCursor.getInt(2) } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receiver/UpdatesReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receiver/UpdatesReceiver.kt index 274b356..b5f4db8 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receiver/UpdatesReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receiver/UpdatesReceiver.kt @@ -6,31 +6,42 @@ import android.content.Context import android.content.Intent import android.app.AlarmManager import android.app.PendingIntent +import android.icu.text.LocaleDisplayNames +import android.preference.PreferenceManager +import android.util.Log import com.tommasoberlose.anotherwidget.`object`.Constants +import com.tommasoberlose.anotherwidget.`object`.Event import com.tommasoberlose.anotherwidget.util.CalendarUtil import com.tommasoberlose.anotherwidget.util.Util +import java.util.* class UpdatesReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - if (intent.action.equals(Intent.ACTION_BOOT_COMPLETED) || intent.action.equals(Intent.ACTION_INSTALL_PACKAGE) || intent.action.equals(Constants.ACTION_TIME_UPDATE)) { - Util.updateWidget(context) + if (intent.action.equals(Intent.ACTION_BOOT_COMPLETED) || intent.action.equals(Intent.ACTION_MY_PACKAGE_REPLACED)) { + setUpdates(context) + } else if (intent.action.equals(Constants.ACTION_TIME_UPDATE)) { + val e: Event = CalendarUtil.getNextEvent(context) + if (e.id == 0 || e.endDate < Calendar.getInstance().timeInMillis) { + CalendarUtil.updateEventList(context) + } else { + Util.updateWidget(context) + } + } else if (intent.action.equals(Constants.ACTION_CALENDAR_UPDATE)) { + CalendarUtil.updateEventList(context) } } fun setUpdates(context: Context) { removeUpdates(context) + CalendarUtil.updateEventList(context) - if (Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR)) { - CalendarUtil.updateEventList(context) - - val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager - val i = Intent(context, UpdatesReceiver::class.java) - i.action = Constants.ACTION_TIME_UPDATE - val pi = PendingIntent.getBroadcast(context, 0, i, 0) - am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), (1000 * 60).toLong(), pi) - } + val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + val i = Intent(context, UpdatesReceiver::class.java) + i.action = Constants.ACTION_TIME_UPDATE + val pi = PendingIntent.getBroadcast(context, 0, i, 0) + am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), (1000 * 60).toLong(), pi) } fun removeUpdates(context: Context) { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receiver/WeatherReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receiver/WeatherReceiver.kt index c829a9c..4ec4ee9 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receiver/WeatherReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receiver/WeatherReceiver.kt @@ -6,6 +6,9 @@ import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.content.SharedPreferences +import android.preference.PreferenceManager +import android.util.Log import com.tommasoberlose.anotherwidget.`object`.Constants import com.tommasoberlose.anotherwidget.util.Util import com.tommasoberlose.anotherwidget.util.WeatherUtil @@ -13,23 +16,32 @@ import com.tommasoberlose.anotherwidget.util.WeatherUtil class WeatherReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - if (intent.action.equals(Intent.ACTION_BOOT_COMPLETED) || intent.action.equals(Intent.ACTION_INSTALL_PACKAGE) || intent.action.equals(Constants.ACTION_WEATHER_UPDATE)) { - WeatherUtil.getWeather(context) + if (intent.action.equals(Intent.ACTION_BOOT_COMPLETED) || intent.action.equals(Intent.ACTION_MY_PACKAGE_REPLACED)) { + setUpdates(context) + } else if (intent.action.equals(Constants.ACTION_WEATHER_UPDATE)) { + WeatherUtil.updateWeather(context) } } fun setUpdates(context: Context) { + val SP: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) removeUpdates(context) + WeatherUtil.updateWeather(context) - if (Util.checkGrantedPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)) { - WeatherUtil.getWeather(context) - - val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager - val i = Intent(context, WeatherReceiver::class.java) - i.action = Constants.ACTION_WEATHER_UPDATE - val pi = PendingIntent.getBroadcast(context, 1, i, 0) - am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), (1000 * 60 * 60 * 2).toLong(), pi) // 2 hour + val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + val i = Intent(context, WeatherReceiver::class.java) + i.action = Constants.ACTION_WEATHER_UPDATE + val pi = PendingIntent.getBroadcast(context, 1, i, 0) + val refresh: Long = when (SP.getInt(Constants.PREF_WEATHER_REFRESH_PERIOD, 1)) { + 0 -> 30 + 1 -> 60 + 2 -> 60 * 3 + 3 -> 60 * 6 + 4 -> 60 * 12 + 5 -> 60 * 24 + else -> 60 } + am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * refresh, pi) } fun removeUpdates(context: Context) { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/CustomLocationActivity.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/CustomLocationActivity.kt new file mode 100644 index 0000000..c535e19 --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/CustomLocationActivity.kt @@ -0,0 +1,80 @@ +package com.tommasoberlose.anotherwidget.ui.activity + +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Context +import android.location.Address +import android.location.Geocoder +import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import android.preference.PreferenceManager +import android.transition.Slide +import android.view.Gravity +import com.tommasoberlose.anotherwidget.R +import android.support.v4.view.ViewCompat.setAlpha +import android.support.v4.view.ViewCompat.animate +import android.text.Editable +import android.text.TextWatcher +import android.util.Log +import android.view.View +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.Toast +import com.tommasoberlose.anotherwidget.`object`.Constants +import com.tommasoberlose.anotherwidget.util.WeatherUtil +import kotlinx.android.synthetic.main.activity_custom_location.* + + +class CustomLocationActivity : AppCompatActivity() { + + @SuppressLint("ApplySharedPref") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_custom_location) + + val SP = PreferenceManager.getDefaultSharedPreferences(this) + + val list = ArrayList() + val addressesList = ArrayList
() + val thread: Thread = Thread() + + var adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, list) + list_view.adapter = adapter + + list_view.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> + SP.edit() + .putString(Constants.PREF_CUSTOM_LOCATION_LAT, addressesList[position].latitude.toString()) + .putString(Constants.PREF_CUSTOM_LOCATION_LON, addressesList[position].longitude.toString()) + .putString(Constants.PREF_CUSTOM_LOCATION_ADD, addressesList[position].getAddressLine(0)) + .commit() + setResult(Activity.RESULT_OK) + finish() + } + + location.addTextChangedListener(object: TextWatcher { + override fun afterTextChanged(text: Editable?) { + val coder = Geocoder(this@CustomLocationActivity) + try { + val addresses = coder.getFromLocationName(text.toString(), 10) as ArrayList
+ list.clear() + addressesList.clear() + + addresses.mapTo(list) { it.getAddressLine(0) } + addresses.mapTo(addressesList) { it } + + adapter = ArrayAdapter(this@CustomLocationActivity, R.layout.custom_location_item, list) + list_view.adapter = adapter + } catch (ignored: Exception) { + Toast.makeText(this@CustomLocationActivity, "Erroreeeee", Toast.LENGTH_SHORT).show() + } + } + + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + } + + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + } + }) + + } +} diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/MainActivity.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/MainActivity.kt index 82ab7c9..f47077f 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/MainActivity.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/MainActivity.kt @@ -2,6 +2,7 @@ package com.tommasoberlose.anotherwidget.ui.activity import android.Manifest import android.annotation.SuppressLint +import android.app.Activity import android.app.AlertDialog import android.content.pm.PackageManager import android.support.v7.app.AppCompatActivity @@ -16,8 +17,6 @@ import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.util.Util import com.tommasoberlose.anotherwidget.receiver.UpdatesReceiver import com.tommasoberlose.anotherwidget.receiver.WeatherReceiver -import kotlinx.android.synthetic.main.activity_main.* -import kotlinx.android.synthetic.main.the_widget.* import java.util.* import java.util.concurrent.TimeUnit import android.content.Intent @@ -25,8 +24,18 @@ import android.content.BroadcastReceiver import com.tommasoberlose.anotherwidget.util.CalendarUtil import com.tommasoberlose.anotherwidget.util.WeatherUtil import android.content.DialogInterface +import android.graphics.drawable.Drawable +import android.support.v4.content.ContextCompat import android.util.Log +import android.view.MenuItem +import android.widget.Toast +import com.crashlytics.android.Crashlytics +import com.github.rubensousa.bottomsheetbuilder.BottomSheetBuilder +import com.github.rubensousa.bottomsheetbuilder.BottomSheetMenuDialog import com.tommasoberlose.anotherwidget.`object`.CalendarSelector +import io.fabric.sdk.android.Fabric +import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.the_widget.* class MainActivity : AppCompatActivity() { @@ -41,9 +50,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - receiver - - // TODO Util.showIntro(this) + Fabric.with(this, Crashlytics()) action_support.setOnClickListener(object: View.OnClickListener { override fun onClick(p0: View?) { @@ -80,15 +87,11 @@ class MainActivity : AppCompatActivity() { override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { when (requestCode) { - Constants.CALENDAR_REQUEST_CODE -> if (permissions.size != 1 || grantResults.size != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { - UpdatesReceiver().removeUpdates(this) - } else { - UpdatesReceiver().setUpdates(this) + Constants.CALENDAR_REQUEST_CODE -> if (!(permissions.size != 1 || grantResults.size != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED)) { + CalendarUtil.updateEventList(this) } - Constants.LOCATION_REQUEST_CODE -> if (permissions.size != 1 || grantResults.size != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { - WeatherReceiver().removeUpdates(this) - } else { - WeatherReceiver().setUpdates(this) + Constants.LOCATION_REQUEST_CODE -> if (!(permissions.size != 1 || grantResults.size != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED)) { + WeatherUtil.updateWeather(this) } } } @@ -107,11 +110,11 @@ class MainActivity : AppCompatActivity() { } }) } else { - if (!Util.checkGrantedPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)) { + if (!Util.checkGrantedPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) { no_location_permission_container.visibility = View.VISIBLE request_location.setOnClickListener(object: View.OnClickListener { override fun onClick(view: View?) { - ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), Constants.LOCATION_REQUEST_CODE) + ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), Constants.LOCATION_REQUEST_CODE) } }) } else { @@ -123,18 +126,36 @@ class MainActivity : AppCompatActivity() { internal fun updateAppWidget() { - widget_bg.setImageDrawable(Util.getCurrentWallpaper(this)) - updateCalendarView() - updateLocationView() + val wallpaper: Drawable? = Util.getCurrentWallpaper(this) + if (wallpaper != null) { + widget_bg.setImageDrawable(wallpaper) + updateCalendarView() + updateLocationView() + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (requestCode == Constants.RESULT_CODE_CUSTOM_LOCATION) { + if (resultCode == Activity.RESULT_OK) { + updateSettings() + WeatherUtil.updateWeather(this) + } + } } fun updateCalendarView() { + val SP = PreferenceManager.getDefaultSharedPreferences(this) val now = Calendar.getInstance() val calendarLayout = Util.checkGrantedPermission(this, Manifest.permission.READ_CALENDAR) empty_layout.visibility = View.VISIBLE calendar_layout.visibility = View.GONE - empty_date.text = String.format("%s%s", Constants.dateFormat.format(now.time)[0].toUpperCase(), Constants.dateFormat.format(now.time).substring(1)) + var dateStringValue: String = String.format("%s%s", Constants.engDateFormat.format(now.time)[0].toUpperCase(), Constants.engDateFormat.format(now.time).substring(1)) + if (SP.getBoolean(Constants.PREF_ITA_FORMAT_DATE, false)) { + dateStringValue = String.format("%s%s", Constants.itDateFormat.format(now.time)[0].toUpperCase(), Constants.itDateFormat.format(now.time).substring(1)) + } + empty_date.text = dateStringValue + //empty_date.setImageBitmap(Util.buildUpdate(this, String.format("%s%s", Constants.dateFormat.format(now.time)[0].toUpperCase(), Constants.dateFormat.format(now.time).substring(1)), "fonts/product_sans_regular.ttf")) if (calendarLayout) { val e = CalendarUtil.getNextEvent(this) @@ -148,18 +169,25 @@ class MainActivity : AppCompatActivity() { var time = "" val hour = TimeUnit.MILLISECONDS.toHours(difference) if (hour > 0) { - time = hour.toString() + getString(R.string.h_code) + time = hour.toString() + getString(R.string.h_code) + " " } val minutes = TimeUnit.MILLISECONDS.toMinutes(difference - hour * 3600 * 1000) if (minutes > 0) { - time += " " + minutes + getString(R.string.min_code) + time += "" + minutes + getString(R.string.min_code) } next_event.text = String.format("%s %s %s", e.title, getString(R.string.in_code), time) } else { next_event.text = String.format("%s", e.title) } - next_event_date.text = String.format("%s - %s", Constants.hourFormat.format(e.startDate), Constants.hourFormat.format(e.endDate)) + + if (!e.allDay) { + val startHour: String = if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) Constants.badHourFormat.format(e.startDate) else Constants.goodHourFormat.format(e.startDate) + val endHour: String = if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) Constants.badHourFormat.format(e.endDate) else Constants.goodHourFormat.format(e.endDate) + next_event_date.text = String.format("%s - %s", startHour, endHour) + } else { + next_event_date.text = dateStringValue + } empty_layout.visibility = View.GONE calendar_layout.visibility = View.VISIBLE @@ -168,7 +196,7 @@ class MainActivity : AppCompatActivity() { } fun updateLocationView() { - val locationLayout = Util.checkGrantedPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) + val locationLayout = Util.checkGrantedPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) val SP = PreferenceManager.getDefaultSharedPreferences(this) if (locationLayout && SP.contains(Constants.PREF_WEATHER_TEMP) && SP.contains(Constants.PREF_WEATHER_ICON)) { @@ -202,40 +230,92 @@ class MainActivity : AppCompatActivity() { temp_unit.text = if (SP.getString(Constants.PREF_WEATHER_TEMP_UNIT, "F").equals("F")) getString(R.string.fahrenheit) else getString(R.string.celsius) action_change_unit.setOnClickListener { SP.edit().putString(Constants.PREF_WEATHER_TEMP_UNIT, if (SP.getString(Constants.PREF_WEATHER_TEMP_UNIT, "F").equals("F")) "C" else "F").commit() - WeatherUtil.getWeather(this) + sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE)) updateSettings() } all_day_label.text = if (SP.getBoolean(Constants.PREF_CALENDAR_ALL_DAY, false)) getString(R.string.settings_all_day_subtitle_visible) else getString(R.string.settings_all_day_subtitle_gone) action_show_all_day.setOnClickListener { SP.edit().putBoolean(Constants.PREF_CALENDAR_ALL_DAY, !SP.getBoolean(Constants.PREF_CALENDAR_ALL_DAY, false)).commit() - updateUI() - CalendarUtil.updateEventList(this) + sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE)) + updateSettings() + } + + hour_format_label.text = if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) getString(R.string.settings_hour_format_subtitle_12) else getString(R.string.settings_hour_format_subtitle_24) + action_hour_format.setOnClickListener { + SP.edit().putString(Constants.PREF_HOUR_FORMAT, if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) "24" else "12").commit() + sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE)) + updateSettings() + } + + val now = Calendar.getInstance() + var dateStringValue: String = String.format("%s%s", Constants.engDateFormat.format(now.time)[0].toUpperCase(), Constants.engDateFormat.format(now.time).substring(1)) + if (SP.getBoolean(Constants.PREF_ITA_FORMAT_DATE, false)) { + dateStringValue = String.format("%s%s", Constants.itDateFormat.format(now.time)[0].toUpperCase(), Constants.itDateFormat.format(now.time).substring(1)) + } + date_format_label.text = dateStringValue + action_date_format.setOnClickListener { + SP.edit().putBoolean(Constants.PREF_ITA_FORMAT_DATE, !SP.getBoolean(Constants.PREF_ITA_FORMAT_DATE, false)).commit() + updateSettings() + Util.updateWidget(this) + } + + label_weather_refresh_period.text = getString(Util.getRefreshPeriodString(SP.getInt(Constants.PREF_WEATHER_REFRESH_PERIOD, 1))) + action_weather_refresh_period.setOnClickListener { + val dialog: BottomSheetMenuDialog = BottomSheetBuilder(this, R.style.Theme_Design_Light_BottomSheetDialog) + .setMode(BottomSheetBuilder.MODE_LIST) + .setMenu(R.menu.weather_refresh_period_menu) + .setIconTintColor(ContextCompat.getColor(this, R.color.black_50)) + .delayDismissOnItemClick(false) + .setItemClickListener({ item: MenuItem -> + SP.edit().putInt(Constants.PREF_WEATHER_REFRESH_PERIOD, when (item.itemId) { + R.id.refresh_1 -> 1 + R.id.refresh_2 -> 2 + R.id.refresh_3 -> 3 + R.id.refresh_4 -> 4 + R.id.refresh_5 -> 5 + else -> 1 + }).commit() + updateSettings() + WeatherReceiver().setUpdates(this@MainActivity) + }) + .createDialog() + + dialog.show() + } + + label_custom_location.text = SP.getString(Constants.PREF_CUSTOM_LOCATION_ADD, getString(R.string.custom_location_gps)) + action_custom_location.setOnClickListener { + startActivityForResult(Intent(this, CustomLocationActivity::class.java), Constants.RESULT_CODE_CUSTOM_LOCATION) } action_filter_calendar.setOnClickListener { val calendarSelectorList: List = CalendarUtil.getCalendarList(this) var calFiltered = SP.getString(Constants.PREF_CALENDAR_FILTER, "") + if (!calendarSelectorList.isEmpty()) { + val calNames = calendarSelectorList.map { if (it.name.equals(it.account_name)) String.format("%s: %s", getString(R.string.main_calendar), it.name) else it.name }.toTypedArray() + val calSelected = calendarSelectorList.map { !calFiltered.contains(" " + Integer.toString(it.id) + ",") }.toBooleanArray() - val calNames = calendarSelectorList.map { if (it.name.equals(it.account_name)) String.format("%s: %s", getString(R.string.main_calendar), it.name) else it.name }.toTypedArray() - val calSelected = calendarSelectorList.map { !calFiltered.contains(" " + Integer.toString(it.id)+",") }.toBooleanArray() - - AlertDialog.Builder(this).setTitle(getString(R.string.settings_filter_calendar_subtitle)) - .setMultiChoiceItems(calNames, calSelected, - DialogInterface.OnMultiChoiceClickListener { dialog, item, isChecked -> - val dialogItem: String = String.format(" %s%s", calendarSelectorList.get(item).id, ",") - calFiltered = calFiltered.replace(dialogItem, ""); - if (!isChecked) { - calFiltered += dialogItem - } - }) - .setPositiveButton(android.R.string.ok, { dialog: DialogInterface, _: Int -> - SP.edit().putString(Constants.PREF_CALENDAR_FILTER, calFiltered).commit() - CalendarUtil.updateEventList(this) - }) - .setNegativeButton(android.R.string.cancel, null) - .show() + AlertDialog.Builder(this).setTitle(getString(R.string.settings_filter_calendar_subtitle)) + .setMultiChoiceItems(calNames, calSelected, + DialogInterface.OnMultiChoiceClickListener { dialog, item, isChecked -> + val dialogItem: String = String.format(" %s%s", calendarSelectorList.get(item).id, ",") + calFiltered = calFiltered.replace(dialogItem, ""); + if (!isChecked) { + calFiltered += dialogItem + } + }) + .setPositiveButton(android.R.string.ok, { dialog: DialogInterface, _: Int -> + SP.edit().putString(Constants.PREF_CALENDAR_FILTER, calFiltered).commit() + sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE)) + updateSettings() + }) + .setNegativeButton(android.R.string.cancel, null) + .show() + } else { + Toast.makeText(this, R.string.calendar_settings_list_error, Toast.LENGTH_SHORT).show() + } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/SplashActivity.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/SplashActivity.kt deleted file mode 100644 index ba4b70f..0000000 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activity/SplashActivity.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.tommasoberlose.anotherwidget.ui.activity - -import android.Manifest -import android.os.Bundle -import com.tommasoberlose.anotherwidget.R -import com.heinrichreimersoftware.materialintro.app.IntroActivity -import com.heinrichreimersoftware.materialintro.slide.SimpleSlide - - -class SplashActivity : IntroActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - isButtonNextVisible = true - isButtonBackVisible = false - isButtonCtaVisible = false - buttonCtaTintMode = BUTTON_CTA_TINT_MODE_TEXT - - addSlide(SimpleSlide.Builder() - .title(R.string.app_name) - .background(R.color.colorPrimary) - .backgroundDark(R.color.colorPrimaryDark) - .build()) - - addSlide(SimpleSlide.Builder() - .title(R.string.title_permission_calendar) - .description(R.string.description_permission_calendar) - .background(R.color.colorPrimary) - .backgroundDark(R.color.colorPrimaryDark) - .permission(Manifest.permission.READ_CALENDAR) - .build()) - - addSlide(SimpleSlide.Builder() - .title(R.string.title_permission_location) - .description(R.string.description_permission_location) - .background(R.color.colorPrimary) - .backgroundDark(R.color.colorPrimaryDark) - .permission(Manifest.permission.ACCESS_COARSE_LOCATION) - .build()) - } -} diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/view/TitleTextView.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/view/TitleTextView.kt new file mode 100644 index 0000000..5531ece --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/view/TitleTextView.kt @@ -0,0 +1,49 @@ +package com.tommasoberlose.anotherwidget.ui.view + +import android.content.Context +import android.graphics.Typeface +import android.content.res.TypedArray +import android.util.AttributeSet +import android.util.Log +import android.widget.TextView +import com.tommasoberlose.anotherwidget.R + + +/** + * Created by tommaso on 12/10/17. + */ +class TitleTextView : TextView { + + constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) { + init(context, attrs) + } + + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { + init(context, attrs) + } + + constructor(context: Context) : super(context) {} + + fun init(context: Context, attrs: AttributeSet) { + try { + val ta = context.obtainStyledAttributes(attrs, R.styleable.FontText) + + if (ta != null) { + val fontAsset = ta.getString(R.styleable.FontText_typefaceAsset) + + if (fontAsset != null && !fontAsset.isEmpty()) { + val tf = Typeface.createFromAsset(getContext().assets, fontAsset) + + if (tf != null) + typeface = tf + else + Log.i("FontText", String.format("Could not create a font from asset: %s", fontAsset)) + } + ta.recycle() + } + } catch (e: Exception) { + Log.i("FontText", "Could not create a font from asset") + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widget/TheWidget.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widget/TheWidget.kt index 6929e36..a7fdb2b 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widget/TheWidget.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widget/TheWidget.kt @@ -24,6 +24,13 @@ import android.content.ContentUris import android.util.Log import com.tommasoberlose.anotherwidget.util.CalendarUtil import com.tommasoberlose.anotherwidget.util.WeatherUtil +import android.graphics.Typeface +import android.net.Uri +import android.widget.TextClock +import android.widget.TextView +import android.content.ComponentName + + /** @@ -63,95 +70,109 @@ class TheWidget : AppWidgetProvider() { } fun updateCalendarView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews { - val now = Calendar.getInstance() - val calendarLayout = Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR) + val SP = PreferenceManager.getDefaultSharedPreferences(context) + val now = Calendar.getInstance() + val calendarLayout = Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR) - views.setViewVisibility(R.id.empty_layout, View.VISIBLE) - views.setViewVisibility(R.id.calendar_layout, View.GONE) - views.setTextViewText(R.id.empty_date, Constants.dateFormat.format(now.time)[0].toUpperCase() + Constants.dateFormat.format(now.time).substring(1)) + views.setViewVisibility(R.id.empty_layout, View.VISIBLE) + views.setViewVisibility(R.id.calendar_layout, View.GONE) + var dateStringValue: String = String.format("%s%s", Constants.engDateFormat.format(now.time)[0].toUpperCase(), Constants.engDateFormat.format(now.time).substring(1)) + if (SP.getBoolean(Constants.PREF_ITA_FORMAT_DATE, false)) { + dateStringValue = String.format("%s%s", Constants.itDateFormat.format(now.time)[0].toUpperCase(), Constants.itDateFormat.format(now.time).substring(1)) + } + views.setTextViewText(R.id.empty_date, dateStringValue) + //views.setImageViewBitmap(R.id.empty_date, Util.buildUpdate(context, Constants.dateFormat.format(now.time)[0].toUpperCase() + Constants.dateFormat.format(now.time).substring(1), "fonts/product_sans_regular.ttf")) - val calIntent = Intent(Intent.ACTION_MAIN) - calIntent.addCategory(Intent.CATEGORY_APP_CALENDAR) - val calPIntent = PendingIntent.getActivity(context, widgetID, calIntent, 0) - views.setOnClickPendingIntent(R.id.main_layout, calPIntent) + val calIntent = Intent(Intent.ACTION_MAIN) + calIntent.addCategory(Intent.CATEGORY_APP_CALENDAR) + val calPIntent = PendingIntent.getActivity(context, widgetID, calIntent, 0) + views.setOnClickPendingIntent(R.id.main_layout, calPIntent) - if (calendarLayout) { - val e = CalendarUtil.getNextEvent(context) + if (calendarLayout) { + val e = CalendarUtil.getNextEvent(context) - if (e.id != 0) { - val difference = e.startDate - now.timeInMillis + if (e.id != 0) { + val difference = e.startDate - now.timeInMillis - if (difference > 1000 * 60) { - var time = "" - val hour = TimeUnit.MILLISECONDS.toHours(difference) - if (hour > 0) { - time = hour.toString() + context.getString(R.string.h_code) - } - val minutes = TimeUnit.MILLISECONDS.toMinutes(difference - hour * 3600 * 1000) - if (minutes > 0) { - time += " " + minutes + context.getString(R.string.min_code) - } - - views.setTextViewText(R.id.next_event, String.format("%s %s %s", e.title, context.getString(R.string.in_code), time)) - } else { - views.setTextViewText(R.id.next_event, String.format("%s", e.title)) + if (difference > 1000 * 60) { + var time = "" + val hour = TimeUnit.MILLISECONDS.toHours(difference) + if (hour > 0) { + time = hour.toString() + context.getString(R.string.h_code) + " " + } + val minutes = TimeUnit.MILLISECONDS.toMinutes(difference - hour * 3600 * 1000) + if (minutes > 0) { + time += "" + minutes + context.getString(R.string.min_code) } - views.setTextViewText(R.id.next_event_date, String.format("%s - %s", Constants.hourFormat.format(e.startDate), Constants.hourFormat.format(e.endDate))) - views.setViewVisibility(R.id.empty_layout, View.GONE) - views.setViewVisibility(R.id.calendar_layout, View.VISIBLE) - - val builder = CalendarContract.CONTENT_URI.buildUpon() - builder.appendPath("time") - ContentUris.appendId(builder, e.startDate) - val intent = Intent(Intent.ACTION_VIEW) - .setData(builder.build()) - val pIntent = PendingIntent.getActivity(context, widgetID, intent, 0) - views.setOnClickPendingIntent(R.id.main_layout, pIntent) + views.setTextViewText(R.id.next_event, String.format("%s %s %s", e.title, context.getString(R.string.in_code), time)) + } else { + views.setTextViewText(R.id.next_event, String.format("%s", e.title)) } - } - return views + if (!e.allDay) { + val startHour: String = if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) Constants.badHourFormat.format(e.startDate) else Constants.goodHourFormat.format(e.startDate) + val endHour: String = if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) Constants.badHourFormat.format(e.endDate) else Constants.goodHourFormat.format(e.endDate) + views.setTextViewText(R.id.next_event_date, String.format("%s - %s", startHour, endHour)) + } else { + views.setTextViewText(R.id.next_event_date, dateStringValue) + } + + views.setViewVisibility(R.id.empty_layout, View.GONE) + views.setViewVisibility(R.id.calendar_layout, View.VISIBLE) + + val builder = CalendarContract.CONTENT_URI.buildUpon() + builder.appendPath("time") + ContentUris.appendId(builder, e.startDate) + val intent = Intent(Intent.ACTION_VIEW) + .setData(builder.build()) + val pIntent = PendingIntent.getActivity(context, widgetID, intent, 0) + views.setOnClickPendingIntent(R.id.main_layout, pIntent) + } } - fun updateLocationView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews { - val locationLayout = Util.checkGrantedPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) + return views + } - val SP = PreferenceManager.getDefaultSharedPreferences(context) - if (locationLayout && SP.contains(Constants.PREF_WEATHER_TEMP) && SP.contains(Constants.PREF_WEATHER_ICON)) { - views.setViewVisibility(R.id.weather, View.VISIBLE) - views.setViewVisibility(R.id.calendar_weather, View.VISIBLE) - val temp = String.format(Locale.getDefault(), "%.0f °%s", SP.getFloat(Constants.PREF_WEATHER_TEMP, 0f), SP.getString(Constants.PREF_WEATHER_TEMP_UNIT, "F")) + fun updateLocationView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews { + val locationLayout = Util.checkGrantedPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) + + val SP = PreferenceManager.getDefaultSharedPreferences(context) + if (locationLayout && SP.contains(Constants.PREF_WEATHER_TEMP) && SP.contains(Constants.PREF_WEATHER_ICON)) { + views.setViewVisibility(R.id.weather, View.VISIBLE) + views.setViewVisibility(R.id.calendar_weather, View.VISIBLE) + val temp = String.format(Locale.getDefault(), "%.0f °%s", SP.getFloat(Constants.PREF_WEATHER_TEMP, 0f), SP.getString(Constants.PREF_WEATHER_TEMP_UNIT, "F")) - views.setViewVisibility(R.id.weather_icon, View.VISIBLE) - views.setViewVisibility(R.id.empty_weather_icon, View.VISIBLE) - val icon: String = SP.getString(Constants.PREF_WEATHER_ICON, "") - if (icon.equals("")) { - views.setViewVisibility(R.id.weather_icon, View.GONE) - views.setViewVisibility(R.id.empty_weather_icon, View.GONE) - } else { - views.setImageViewResource(R.id.weather_icon, WeatherUtil.getWeatherIconResource(icon)) - views.setImageViewResource(R.id.empty_weather_icon, WeatherUtil.getWeatherIconResource(icon)) - } - - views.setTextViewText(R.id.temp, temp) - views.setTextViewText(R.id.calendar_temp, temp) - - val weatherIntent = Intent("com.google.android.googlequicksearchbox.GOOGLE_SEARCH") - weatherIntent.addCategory(Intent.CATEGORY_DEFAULT) - weatherIntent.putExtra("type", "string") - weatherIntent.putExtra("query", "weather") - val weatherPIntent = PendingIntent.getActivity(context, widgetID, weatherIntent, 0) - - views.setOnClickPendingIntent(R.id.weather, weatherPIntent) - views.setOnClickPendingIntent(R.id.calendar_weather, weatherPIntent) + views.setViewVisibility(R.id.weather_icon, View.VISIBLE) + views.setViewVisibility(R.id.empty_weather_icon, View.VISIBLE) + val icon: String = SP.getString(Constants.PREF_WEATHER_ICON, "") + if (icon.equals("")) { + views.setViewVisibility(R.id.weather_icon, View.GONE) + views.setViewVisibility(R.id.empty_weather_icon, View.GONE) } else { - views.setViewVisibility(R.id.weather, View.GONE) - views.setViewVisibility(R.id.calendar_weather, View.GONE) + views.setImageViewResource(R.id.weather_icon, WeatherUtil.getWeatherIconResource(icon)) + views.setImageViewResource(R.id.empty_weather_icon, WeatherUtil.getWeatherIconResource(icon)) } - return views + + views.setTextViewText(R.id.temp, temp) + views.setTextViewText(R.id.calendar_temp, temp) + + val weatherIntent: Intent = Intent(Intent.ACTION_VIEW) + weatherIntent.addCategory(Intent.CATEGORY_DEFAULT) + weatherIntent.data = Uri.parse("dynact://velour/weather/ProxyActivity") + weatherIntent.component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline") + + val weatherPIntent = PendingIntent.getActivity(context, widgetID, weatherIntent, 0) + + views.setOnClickPendingIntent(R.id.weather, weatherPIntent) + views.setOnClickPendingIntent(R.id.calendar_weather, weatherPIntent) + } else { + views.setViewVisibility(R.id.weather, View.GONE) + views.setViewVisibility(R.id.calendar_weather, View.GONE) + } + return views } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/util/CalendarUtil.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/util/CalendarUtil.kt index caf993e..82d4b95 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/util/CalendarUtil.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/util/CalendarUtil.kt @@ -5,6 +5,7 @@ import android.annotation.SuppressLint import android.content.ContentUris import android.content.Context import android.content.SharedPreferences +import android.net.Uri import android.preference.PreferenceManager import android.provider.CalendarContract import android.util.Log @@ -25,7 +26,7 @@ object CalendarUtil { val now = Calendar.getInstance() val hourLimit = Calendar.getInstance() - hourLimit.add(Calendar.HOUR, 6) + hourLimit.add(Calendar.HOUR, 8) val builder = CalendarContract.Instances.CONTENT_URI.buildUpon() ContentUris.appendId(builder, now.timeInMillis) @@ -33,41 +34,53 @@ object CalendarUtil { if (!Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR)) { resetNextEventData(context) - } + } else { - val instanceCursor = context.contentResolver.query(builder.build(), arrayOf(CalendarContract.Instances.EVENT_ID, CalendarContract.Instances.BEGIN, CalendarContract.Instances.END), null, null, null) - instanceCursor.moveToFirst() + val instanceCursor = context.contentResolver.query(builder.build(), arrayOf(CalendarContract.Instances.EVENT_ID, CalendarContract.Instances.BEGIN, CalendarContract.Instances.END), null, null, null) + if (instanceCursor != null && instanceCursor.count > 0) { + instanceCursor.moveToFirst() + for (i in 0 until instanceCursor.count) { + val ID = instanceCursor.getInt(0) + val eventCursor = context.contentResolver.query(CalendarContract.Events.CONTENT_URI, arrayOf(CalendarContract.Events.TITLE, CalendarContract.Events.ALL_DAY, CalendarContract.Events.CALENDAR_ID), + CalendarContract.Events._ID + " is ?", + arrayOf(Integer.toString(ID)), null) - for (i in 0 until instanceCursor.count) { - val ID = instanceCursor.getInt(0) + if (eventCursor != null && eventCursor.count > 0) { + eventCursor.moveToFirst() - val eventCursor = context.contentResolver.query(CalendarContract.Events.CONTENT_URI, arrayOf(CalendarContract.Events.TITLE, CalendarContract.Events.ALL_DAY, CalendarContract.Events.CALENDAR_ID), - CalendarContract.Events._ID + " is ?", - arrayOf(Integer.toString(ID)), null) - eventCursor.moveToFirst() + for (j in 0 until eventCursor.count) { + val e = Event(eventCursor, instanceCursor) + val allDay: Boolean = !eventCursor.getString(1).equals("0") + if ((SP.getBoolean(Constants.PREF_CALENDAR_ALL_DAY, false) || !allDay) && !(SP.getString(Constants.PREF_CALENDAR_FILTER, "").contains(" " + e.calendarID + ","))) { + eventList.add(e) + } + eventCursor.moveToNext() + } + } - for (j in 0 until eventCursor.count) { - val e = Event(eventCursor, instanceCursor) - val allDay: Boolean = !eventCursor.getString(1).equals("0") - if (e.endDate - now.timeInMillis > 1000 * 60 * 30 && (SP.getBoolean(Constants.PREF_CALENDAR_ALL_DAY, false) || !allDay) && !(SP.getString(Constants.PREF_CALENDAR_FILTER, "").contains(" " + e.calendarID + ","))) { - eventList.add(e) + eventCursor.close() + + instanceCursor.moveToNext() } - eventCursor.moveToNext() } - eventCursor.close() + instanceCursor.close() - instanceCursor.moveToNext() - } - - instanceCursor.close() - - if (eventList.isEmpty()) { - resetNextEventData(context) - } else { - saveNextEventData(context, eventList.get(0)) + if (eventList.isEmpty()) { + resetNextEventData(context) + } else { + Collections.sort(eventList, { event: Event, event1: Event -> + if (event.startDate > event1.startDate) { + return@sort 1 + } else if (event.startDate < event1.startDate) { + return@sort -1 + } + return@sort 0 + }) + saveNextEventData(context, eventList.get(0)) + } } } @@ -79,24 +92,54 @@ object CalendarUtil { return calendarList } - val calendarCursor = context.contentResolver.query(CalendarContract.Calendars.CONTENT_URI, - arrayOf(CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME, CalendarContract.Calendars.ACCOUNT_NAME), - null, - null, - null) ?: return calendarList + try { + val calendarCursor = context.contentResolver.query(Uri.parse("content://com.android.calendar/calendars"), + arrayOf(CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME, CalendarContract.Calendars.ACCOUNT_NAME), + null, + null, + null) - calendarCursor.moveToFirst() + if (calendarCursor != null && calendarCursor.count > 0) { - for (j in 0 until calendarCursor.count) { - calendarList.add(CalendarSelector(calendarCursor.getInt(0), calendarCursor.getString(1), calendarCursor.getString(2))) - calendarCursor.moveToNext() + calendarCursor.moveToFirst() + + for (j in 0 until calendarCursor.count) { + calendarList.add(CalendarSelector(calendarCursor.getInt(0), calendarCursor.getString(1), calendarCursor.getString(2))) + calendarCursor.moveToNext() + } + } + + calendarCursor.close() + } catch (ignored: Exception) { + try { + val calendarCursor = context.contentResolver.query(CalendarContract.Calendars.CONTENT_URI, + arrayOf(CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME, CalendarContract.Calendars.ACCOUNT_NAME), + null, + null, + null) + + if (calendarCursor != null && calendarCursor.count > 0) { + + calendarCursor.moveToFirst() + + for (j in 0 until calendarCursor.count) { + calendarList.add(CalendarSelector(calendarCursor.getInt(0), calendarCursor.getString(1), calendarCursor.getString(2))) + calendarCursor.moveToNext() + } + } + + calendarCursor.close() + } catch (ignore: Exception) { + + } finally { + return calendarList + } + } finally { + return calendarList } - - calendarCursor.close() - - return calendarList } + @SuppressLint("ApplySharedPref") fun resetNextEventData(context: Context) { val SP: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) SP.edit() @@ -104,8 +147,10 @@ object CalendarUtil { .remove(Constants.PREF_NEXT_EVENT_NAME) .remove(Constants.PREF_NEXT_EVENT_START_DATE) .remove(Constants.PREF_NEXT_EVENT_END_DATE) + .remove(Constants.PREF_NEXT_EVENT_ALL_DAY) .remove(Constants.PREF_NEXT_EVENT_CALENDAR_ID) - .apply() + .commit() + Util.updateWidget(context) } @SuppressLint("ApplySharedPref") @@ -116,6 +161,7 @@ object CalendarUtil { .putString(Constants.PREF_NEXT_EVENT_NAME, event.title) .putLong(Constants.PREF_NEXT_EVENT_START_DATE, event.startDate) .putLong(Constants.PREF_NEXT_EVENT_END_DATE, event.endDate) + .putBoolean(Constants.PREF_NEXT_EVENT_ALL_DAY, event.allDay) .putInt(Constants.PREF_NEXT_EVENT_CALENDAR_ID, event.calendarID) .commit() Util.updateWidget(context) @@ -123,6 +169,6 @@ object CalendarUtil { fun getNextEvent(context: Context): Event { val SP: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) - return Event(SP.getInt(Constants.PREF_NEXT_EVENT_ID, 0), SP.getString(Constants.PREF_NEXT_EVENT_NAME, ""), SP.getLong(Constants.PREF_NEXT_EVENT_START_DATE, 0), SP.getLong(Constants.PREF_NEXT_EVENT_END_DATE, 0), SP.getInt(Constants.PREF_NEXT_EVENT_CALENDAR_ID, 0)) + return Event(SP.getInt(Constants.PREF_NEXT_EVENT_ID, 0), SP.getString(Constants.PREF_NEXT_EVENT_NAME, ""), SP.getLong(Constants.PREF_NEXT_EVENT_START_DATE, 0), SP.getLong(Constants.PREF_NEXT_EVENT_END_DATE, 0), SP.getInt(Constants.PREF_NEXT_EVENT_CALENDAR_ID, 0), SP.getBoolean(Constants.PREF_NEXT_EVENT_ALL_DAY, false)) } } \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/util/Util.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/util/Util.kt index 860b677..97e32f2 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/util/Util.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/util/Util.kt @@ -1,7 +1,6 @@ package com.tommasoberlose.anotherwidget.util import android.Manifest -import android.annotation.SuppressLint import android.app.Notification import android.app.NotificationManager import android.app.PendingIntent @@ -9,35 +8,25 @@ import android.app.WallpaperManager import android.appwidget.AppWidgetManager import android.content.* import android.content.pm.PackageManager +import android.content.res.Resources +import android.graphics.* import android.graphics.drawable.Drawable -import android.location.Location -import android.location.LocationListener -import android.location.LocationManager import android.net.Uri -import android.os.Bundle -import android.preference.PreferenceManager -import android.provider.CalendarContract -import android.support.annotation.DrawableRes import android.support.customtabs.CustomTabsIntent import android.support.v4.app.NotificationCompat import android.support.v4.content.ContextCompat -import android.util.Log -import com.survivingwithandroid.weather.lib.WeatherClient -import com.survivingwithandroid.weather.lib.WeatherConfig -import com.survivingwithandroid.weather.lib.exception.WeatherLibException -import com.survivingwithandroid.weather.lib.model.CurrentWeather -import com.survivingwithandroid.weather.lib.provider.openweathermap.OpenweathermapProviderType -import com.survivingwithandroid.weather.lib.request.WeatherRequest +import android.util.DisplayMetrics import com.tommasoberlose.anotherwidget.R -import com.tommasoberlose.anotherwidget.`object`.Constants -import com.tommasoberlose.anotherwidget.`object`.Event import com.tommasoberlose.anotherwidget.ui.activity.MainActivity -import com.tommasoberlose.anotherwidget.ui.activity.SplashActivity import com.tommasoberlose.anotherwidget.ui.widget.TheWidget +import android.graphics.Bitmap +import android.graphics.drawable.BitmapDrawable +import android.support.annotation.StringRes +import android.util.TypedValue + + -import java.util.ArrayList -import java.util.Calendar /** * Created by tommaso on 05/10/17. @@ -102,16 +91,70 @@ object Util { context.startActivity(Intent.createChooser(sendIntent, context.getString(R.string.action_share))); } - fun showIntro(context: Context) { - val SP: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) - val firstTime: Boolean = SP.getBoolean(Constants.PREF_FIRST_STEP, true) - // TODO SP.edit().putBoolean(Constants.PREF_FIRST_STEP, false).apply() - if (firstTime) { - context.startActivity(Intent(context, SplashActivity::class.java)) + fun getCurrentWallpaper(context: Context): Drawable? { + var wallpaper: Drawable? = null + try { + wallpaper = WallpaperManager.getInstance(context).drawable + } catch (e: Exception) { + wallpaper = BitmapDrawable(context.resources, getResizedBitmap(BitmapFactory.decodeResource(context.resources, R.drawable.pixel_2_wallpaper), 800)) + } finally { + return wallpaper } } - fun getCurrentWallpaper(context: Context): Drawable { - return WallpaperManager.getInstance(context).getDrawable(); + fun buildUpdate(context: Context, time: String, fontPath: String): Bitmap { + val myBitmap:Bitmap = Bitmap.createBitmap(convertDpToPixel(300f, context).toInt(), convertDpToPixel(40f, context).toInt(), Bitmap.Config.ARGB_8888) + val myCanvas: Canvas = Canvas(myBitmap) + val paint: Paint = Paint() + val clock: Typeface = Typeface.createFromAsset(context.assets, fontPath) + paint.isAntiAlias = true + paint.isSubpixelText = true + paint.typeface = clock + paint.style = Paint.Style.FILL + paint.color = Color.WHITE + paint.textSize = convertSpToPixels(14f, context) + paint.textAlign = Paint.Align.CENTER + paint.setShadowLayer(5f,0f, 0f, R.color.black_50) + myCanvas.drawText("Ultra Pixel Meeting Ciao Ciao", convertDpToPixel(150f, context), convertDpToPixel(20f, context), paint) + return myBitmap; + } + + fun convertDpToPixel(dp: Float, context: Context): Float { + val resources: Resources = context.resources + val metrics: DisplayMetrics = resources.displayMetrics + val px: Float = dp * (metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT) + return px + } + + fun convertSpToPixels(sp: Float, context: Context): Float { + return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.resources.displayMetrics) + } + + fun getResizedBitmap(image: Bitmap, maxSize: Int): Bitmap { + var width = image.width + var height = image.height + + val bitmapRatio = width.toFloat() / height.toFloat() + if (bitmapRatio > 1) { + width = maxSize + height = (width / bitmapRatio).toInt() + } else { + height = maxSize + width = (height * bitmapRatio).toInt() + } + + return Bitmap.createScaledBitmap(image, width, height, true) + } + + fun getRefreshPeriodString(period: Int): Int { + return when (period) { + 0 -> R.string.settings_weather_refresh_period_subtitle_0 + 1 -> R.string.settings_weather_refresh_period_subtitle_1 + 2 -> R.string.settings_weather_refresh_period_subtitle_2 + 3 -> R.string.settings_weather_refresh_period_subtitle_3 + 4 -> R.string.settings_weather_refresh_period_subtitle_4 + 5 -> R.string.settings_weather_refresh_period_subtitle_5 + else -> R.string.settings_weather_refresh_period_subtitle_0 + } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/util/WeatherUtil.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/util/WeatherUtil.kt index a6f8473..cec117c 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/util/WeatherUtil.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/util/WeatherUtil.kt @@ -4,9 +4,7 @@ import android.Manifest import android.annotation.SuppressLint import android.content.Context import android.content.SharedPreferences -import android.location.Location -import android.location.LocationListener -import android.location.LocationManager +import android.location.* import android.os.Bundle import android.preference.PreferenceManager import com.survivingwithandroid.weather.lib.WeatherClient @@ -18,83 +16,108 @@ import com.survivingwithandroid.weather.lib.request.WeatherRequest import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.`object`.Constants + /** * Created by tommaso on 08/10/17. */ object WeatherUtil { + val API_KEY_1 = "43e744ad8ff91b09ea62dbc7d0e7c1dd" + val API_KEY_2 = "61cde158f4bcc2e5cd18de7b9d000702" - - fun getWeather(context: Context) { - if (!Util.checkGrantedPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)) { - return - } + fun updateWeather(context: Context) { val SP: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + if (SP.getString(Constants.PREF_CUSTOM_LOCATION_ADD, "").equals("") || SP.getString(Constants.PREF_CUSTOM_LOCATION_LAT, "").equals("") || SP.getString(Constants.PREF_CUSTOM_LOCATION_LON, "").equals("")) { - val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager - getCurrentWeather(context, locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)) - - locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0f, object: LocationListener { - override fun onLocationChanged(location: Location) { - locationManager.removeUpdates(this) - getCurrentWeather(context, location) + if (!Util.checkGrantedPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)) { + return } - @SuppressLint("ApplySharedPref") - override fun onProviderDisabled(p0: String?) { - } + val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + getCurrentWeather(context, locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)) + getCurrentWeather(context, locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)) - @SuppressLint("ApplySharedPref") - override fun onProviderEnabled(p0: String?) { - } + locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0f, object : LocationListener { + override fun onLocationChanged(location: Location) { + locationManager.removeUpdates(this) + getCurrentWeather(context, location) + } - override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?) { - } - }) + @SuppressLint("ApplySharedPref") + override fun onProviderDisabled(p0: String?) { + } + + @SuppressLint("ApplySharedPref") + override fun onProviderEnabled(p0: String?) { + } + + override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?) { + } + }) + } else { + weatherNetworkRequest(context, SP.getString(Constants.PREF_CUSTOM_LOCATION_LAT, "").toDouble(), SP.getString(Constants.PREF_CUSTOM_LOCATION_LON, "").toDouble()) + + } } @SuppressLint("ApplySharedPref") fun getCurrentWeather(context: Context, location: Location?) { if (location != null) { - val SP: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) - - try { - val config = WeatherConfig() - config.unitSystem = if (SP.getString(Constants.PREF_WEATHER_TEMP_UNIT, "F").equals("C")) WeatherConfig.UNIT_SYSTEM.M else WeatherConfig.UNIT_SYSTEM.I - config.lang = "en" // If you want to use english - config.maxResult = 1 // Max number of cities retrieved - config.numDays = 1 // Max num of days in the forecast - config.ApiKey = "43e744ad8ff91b09ea62dbc7d0e7c1dd"; - - val client = WeatherClient.ClientBuilder().attach(context) - .httpClient(com.survivingwithandroid.weather.lib.client.volley.WeatherClientDefault::class.java) - .provider(OpenweathermapProviderType()) - .config(config) - .build() - - client.getCurrentCondition(WeatherRequest(location.longitude, location.latitude), object : WeatherClient.WeatherEventListener { - @SuppressLint("ApplySharedPref") - override fun onWeatherRetrieved(currentWeather: CurrentWeather) { - SP.edit() - .putFloat(Constants.PREF_WEATHER_TEMP, currentWeather.weather.temperature.temp) - .putString(Constants.PREF_WEATHER_ICON, currentWeather.weather.currentCondition.icon) - .commit() - Util.updateWidget(context) - } - - @SuppressLint("ApplySharedPref") - override fun onWeatherError(e: WeatherLibException?) { - } - - @SuppressLint("ApplySharedPref") - override fun onConnectionError(throwable: Throwable?) { - } - }) - } catch (t: Exception) { - } + weatherNetworkRequest(context, location.latitude, location.longitude) } } + fun weatherNetworkRequest(context: Context, latitude: Double, longitude: Double) { + val SP: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + + try { + val config = WeatherConfig() + config.unitSystem = if (SP.getString(Constants.PREF_WEATHER_TEMP_UNIT, "F").equals("C")) WeatherConfig.UNIT_SYSTEM.M else WeatherConfig.UNIT_SYSTEM.I + config.lang = "en" // If you want to use english + config.maxResult = 1 // Max number of cities retrieved + config.numDays = 1 // Max num of days in the forecast + config.ApiKey = API_KEY_2 + + val client = WeatherClient.ClientBuilder().attach(context) + .httpClient(com.survivingwithandroid.weather.lib.client.volley.WeatherClientDefault::class.java) + .provider(OpenweathermapProviderType()) + .config(config) + .build() + + client.getCurrentCondition(WeatherRequest(longitude, latitude), object : WeatherClient.WeatherEventListener { + @SuppressLint("ApplySharedPref") + override fun onWeatherRetrieved(currentWeather: CurrentWeather) { + SP.edit() + .putFloat(Constants.PREF_WEATHER_TEMP, currentWeather.weather.temperature.temp) + .putString(Constants.PREF_WEATHER_ICON, currentWeather.weather.currentCondition.icon) + .commit() + Util.updateWidget(context) + } + + @SuppressLint("ApplySharedPref") + override fun onWeatherError(e: WeatherLibException?) { + removeWeather(context, SP) + } + + @SuppressLint("ApplySharedPref") + override fun onConnectionError(throwable: Throwable?) { + removeWeather(context, SP) + } + }) + } catch (t: Exception) { + removeWeather(context, SP) + } + } + + @SuppressLint("ApplySharedPref") + fun removeWeather(context: Context, SP: SharedPreferences) { + SP.edit(). + remove(Constants.PREF_WEATHER_TEMP) + .remove(Constants.PREF_WEATHER_ICON) + .commit() + Util.updateWidget(context) + } + fun getWeatherIconResource(icon: String): Int { when (icon) { "01d" -> { diff --git a/app/src/main/res/drawable-hdpi/ic_action_refresh_0.png b/app/src/main/res/drawable-hdpi/ic_action_refresh_0.png new file mode 100644 index 0000000..8f325d3 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_refresh_0.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_refresh_1.png b/app/src/main/res/drawable-hdpi/ic_action_refresh_1.png new file mode 100644 index 0000000..92f97dc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_refresh_1.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_refresh_2.png b/app/src/main/res/drawable-hdpi/ic_action_refresh_2.png new file mode 100644 index 0000000..3312987 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_refresh_2.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_refresh_3.png b/app/src/main/res/drawable-hdpi/ic_action_refresh_3.png new file mode 100644 index 0000000..3e3eba4 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_refresh_3.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_refresh_4.png b/app/src/main/res/drawable-hdpi/ic_action_refresh_4.png new file mode 100644 index 0000000..99fa173 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_refresh_4.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_refresh_5.png b/app/src/main/res/drawable-hdpi/ic_action_refresh_5.png new file mode 100644 index 0000000..c0dbdc2 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_refresh_5.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_refresh_0.png b/app/src/main/res/drawable-mdpi/ic_action_refresh_0.png new file mode 100644 index 0000000..6fcbb48 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_refresh_0.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_refresh_1.png b/app/src/main/res/drawable-mdpi/ic_action_refresh_1.png new file mode 100644 index 0000000..42d0255 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_refresh_1.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_refresh_2.png b/app/src/main/res/drawable-mdpi/ic_action_refresh_2.png new file mode 100644 index 0000000..f8a2ee2 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_refresh_2.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_refresh_3.png b/app/src/main/res/drawable-mdpi/ic_action_refresh_3.png new file mode 100644 index 0000000..6aa4952 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_refresh_3.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_refresh_4.png b/app/src/main/res/drawable-mdpi/ic_action_refresh_4.png new file mode 100644 index 0000000..9df5110 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_refresh_4.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_refresh_5.png b/app/src/main/res/drawable-mdpi/ic_action_refresh_5.png new file mode 100644 index 0000000..586be1d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_refresh_5.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_refresh_0.png b/app/src/main/res/drawable-xhdpi/ic_action_refresh_0.png new file mode 100644 index 0000000..622cbbb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_refresh_0.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_refresh_1.png b/app/src/main/res/drawable-xhdpi/ic_action_refresh_1.png new file mode 100644 index 0000000..567957a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_refresh_1.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_refresh_2.png b/app/src/main/res/drawable-xhdpi/ic_action_refresh_2.png new file mode 100644 index 0000000..3e65f43 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_refresh_2.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_refresh_3.png b/app/src/main/res/drawable-xhdpi/ic_action_refresh_3.png new file mode 100644 index 0000000..2474cfb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_refresh_3.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_refresh_4.png b/app/src/main/res/drawable-xhdpi/ic_action_refresh_4.png new file mode 100644 index 0000000..c26691a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_refresh_4.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_refresh_5.png b/app/src/main/res/drawable-xhdpi/ic_action_refresh_5.png new file mode 100644 index 0000000..1c028ba Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_refresh_5.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_refresh_0.png b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_0.png new file mode 100644 index 0000000..2a3f745 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_0.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_refresh_1.png b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_1.png new file mode 100644 index 0000000..51b6a23 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_1.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_refresh_2.png b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_2.png new file mode 100644 index 0000000..a8d0b32 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_2.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_refresh_3.png b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_3.png new file mode 100644 index 0000000..996b045 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_3.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_refresh_4.png b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_4.png new file mode 100644 index 0000000..07688b9 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_4.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_refresh_5.png b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_5.png new file mode 100644 index 0000000..15ad096 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_refresh_5.png differ diff --git a/app/src/main/res/drawable/clear_day.png b/app/src/main/res/drawable/clear_day.png index 26a6137..170ea9f 100755 Binary files a/app/src/main/res/drawable/clear_day.png and b/app/src/main/res/drawable/clear_day.png differ diff --git a/app/src/main/res/drawable/clear_night.png b/app/src/main/res/drawable/clear_night.png index ab9d246..c43b8bb 100755 Binary files a/app/src/main/res/drawable/clear_night.png and b/app/src/main/res/drawable/clear_night.png differ diff --git a/app/src/main/res/drawable/cloudy_weather.png b/app/src/main/res/drawable/cloudy_weather.png index add6383..e8d3984 100755 Binary files a/app/src/main/res/drawable/cloudy_weather.png and b/app/src/main/res/drawable/cloudy_weather.png differ diff --git a/app/src/main/res/drawable/haze_day.png b/app/src/main/res/drawable/haze_day.png index df9de56..a5ad3ef 100755 Binary files a/app/src/main/res/drawable/haze_day.png and b/app/src/main/res/drawable/haze_day.png differ diff --git a/app/src/main/res/drawable/haze_night.png b/app/src/main/res/drawable/haze_night.png index df33c58..cb1be7f 100755 Binary files a/app/src/main/res/drawable/haze_night.png and b/app/src/main/res/drawable/haze_night.png differ diff --git a/app/src/main/res/drawable/haze_weather.png b/app/src/main/res/drawable/haze_weather.png index 805953e..2cc0af0 100755 Binary files a/app/src/main/res/drawable/haze_weather.png and b/app/src/main/res/drawable/haze_weather.png differ diff --git a/app/src/main/res/drawable/mostly_cloudy.png b/app/src/main/res/drawable/mostly_cloudy.png index 0e64be7..f0c5615 100755 Binary files a/app/src/main/res/drawable/mostly_cloudy.png and b/app/src/main/res/drawable/mostly_cloudy.png differ diff --git a/app/src/main/res/drawable/mostly_cloudy_night.png b/app/src/main/res/drawable/mostly_cloudy_night.png index a38045c..fd47811 100755 Binary files a/app/src/main/res/drawable/mostly_cloudy_night.png and b/app/src/main/res/drawable/mostly_cloudy_night.png differ diff --git a/app/src/main/res/drawable/partly_cloudy.png b/app/src/main/res/drawable/partly_cloudy.png index 809cda5..c50a7c3 100755 Binary files a/app/src/main/res/drawable/partly_cloudy.png and b/app/src/main/res/drawable/partly_cloudy.png differ diff --git a/app/src/main/res/drawable/partly_cloudy_night.png b/app/src/main/res/drawable/partly_cloudy_night.png index 1cf8c12..57c0c76 100755 Binary files a/app/src/main/res/drawable/partly_cloudy_night.png and b/app/src/main/res/drawable/partly_cloudy_night.png differ diff --git a/app/src/main/res/drawable/pixel_2_wallpaper.jpg b/app/src/main/res/drawable/pixel_2_wallpaper.jpg new file mode 100644 index 0000000..3d4140c Binary files /dev/null and b/app/src/main/res/drawable/pixel_2_wallpaper.jpg differ diff --git a/app/src/main/res/drawable/rain_snow.png b/app/src/main/res/drawable/rain_snow.png index eb3199b..7de3b2b 100755 Binary files a/app/src/main/res/drawable/rain_snow.png and b/app/src/main/res/drawable/rain_snow.png differ diff --git a/app/src/main/res/drawable/rain_snow_day.png b/app/src/main/res/drawable/rain_snow_day.png index b401e1f..2dd6ca4 100755 Binary files a/app/src/main/res/drawable/rain_snow_day.png and b/app/src/main/res/drawable/rain_snow_day.png differ diff --git a/app/src/main/res/drawable/rain_snow_night.png b/app/src/main/res/drawable/rain_snow_night.png index 12b27af..5ffa81a 100755 Binary files a/app/src/main/res/drawable/rain_snow_night.png and b/app/src/main/res/drawable/rain_snow_night.png differ diff --git a/app/src/main/res/drawable/rainy_day.png b/app/src/main/res/drawable/rainy_day.png index 537a01f..52b2156 100755 Binary files a/app/src/main/res/drawable/rainy_day.png and b/app/src/main/res/drawable/rainy_day.png differ diff --git a/app/src/main/res/drawable/rainy_night.png b/app/src/main/res/drawable/rainy_night.png index dfef460..df84943 100755 Binary files a/app/src/main/res/drawable/rainy_night.png and b/app/src/main/res/drawable/rainy_night.png differ diff --git a/app/src/main/res/drawable/rainy_weather.png b/app/src/main/res/drawable/rainy_weather.png index ddb2bd5..a0e3f65 100755 Binary files a/app/src/main/res/drawable/rainy_weather.png and b/app/src/main/res/drawable/rainy_weather.png differ diff --git a/app/src/main/res/drawable/showcase.png b/app/src/main/res/drawable/showcase.png index 4e15c6f..c55602a 100755 Binary files a/app/src/main/res/drawable/showcase.png and b/app/src/main/res/drawable/showcase.png differ diff --git a/app/src/main/res/drawable/snow_day.png b/app/src/main/res/drawable/snow_day.png index bfae201..dc33e0c 100755 Binary files a/app/src/main/res/drawable/snow_day.png and b/app/src/main/res/drawable/snow_day.png differ diff --git a/app/src/main/res/drawable/snow_night.png b/app/src/main/res/drawable/snow_night.png index 84a96ab..c2a9f6d 100755 Binary files a/app/src/main/res/drawable/snow_night.png and b/app/src/main/res/drawable/snow_night.png differ diff --git a/app/src/main/res/drawable/snow_weather.png b/app/src/main/res/drawable/snow_weather.png index bf3de5f..3c3ddca 100755 Binary files a/app/src/main/res/drawable/snow_weather.png and b/app/src/main/res/drawable/snow_weather.png differ diff --git a/app/src/main/res/drawable/storm_weather.png b/app/src/main/res/drawable/storm_weather.png index c7d0cb0..682cf22 100755 Binary files a/app/src/main/res/drawable/storm_weather.png and b/app/src/main/res/drawable/storm_weather.png differ diff --git a/app/src/main/res/drawable/storm_weather_day.png b/app/src/main/res/drawable/storm_weather_day.png index 9743fc1..04329e4 100755 Binary files a/app/src/main/res/drawable/storm_weather_day.png and b/app/src/main/res/drawable/storm_weather_day.png differ diff --git a/app/src/main/res/drawable/storm_weather_night.png b/app/src/main/res/drawable/storm_weather_night.png index aa9b298..beb7269 100755 Binary files a/app/src/main/res/drawable/storm_weather_night.png and b/app/src/main/res/drawable/storm_weather_night.png differ diff --git a/app/src/main/res/drawable/thunder_day.png b/app/src/main/res/drawable/thunder_day.png index 3d97d30..f4322ca 100755 Binary files a/app/src/main/res/drawable/thunder_day.png and b/app/src/main/res/drawable/thunder_day.png differ diff --git a/app/src/main/res/drawable/thunder_night.png b/app/src/main/res/drawable/thunder_night.png index 883c124..43e90c3 100755 Binary files a/app/src/main/res/drawable/thunder_night.png and b/app/src/main/res/drawable/thunder_night.png differ diff --git a/app/src/main/res/drawable/thunder_weather.png b/app/src/main/res/drawable/thunder_weather.png index 80edb08..20cf33c 100755 Binary files a/app/src/main/res/drawable/thunder_weather.png and b/app/src/main/res/drawable/thunder_weather.png differ diff --git a/app/src/main/res/drawable/unknown.png b/app/src/main/res/drawable/unknown.png index b9f62e9..cb74192 100755 Binary files a/app/src/main/res/drawable/unknown.png and b/app/src/main/res/drawable/unknown.png differ diff --git a/app/src/main/res/drawable/windy_day.png b/app/src/main/res/drawable/windy_day.png index 5dc15e4..f7fd6b9 100755 Binary files a/app/src/main/res/drawable/windy_day.png and b/app/src/main/res/drawable/windy_day.png differ diff --git a/app/src/main/res/drawable/windy_night.png b/app/src/main/res/drawable/windy_night.png index c4f76ca..d41f5eb 100755 Binary files a/app/src/main/res/drawable/windy_night.png and b/app/src/main/res/drawable/windy_night.png differ diff --git a/app/src/main/res/drawable/windy_weather.png b/app/src/main/res/drawable/windy_weather.png index b571fa1..55173a0 100755 Binary files a/app/src/main/res/drawable/windy_weather.png and b/app/src/main/res/drawable/windy_weather.png differ diff --git a/app/src/main/res/layout/activity_custom_location.xml b/app/src/main/res/layout/activity_custom_location.xml new file mode 100644 index 0000000..e902b13 --- /dev/null +++ b/app/src/main/res/layout/activity_custom_location.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 8e917ad..df4a556 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -59,14 +59,63 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:paddingTop="20dp" - android:paddingBottom="20dp"> + android:paddingTop="8dp" + android:paddingBottom="8dp"> + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/custom_location_item.xml b/app/src/main/res/layout/custom_location_item.xml new file mode 100644 index 0000000..99cafe2 --- /dev/null +++ b/app/src/main/res/layout/custom_location_item.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/the_widget.xml b/app/src/main/res/layout/the_widget.xml index d7c5e4f..ffd834a 100644 --- a/app/src/main/res/layout/the_widget.xml +++ b/app/src/main/res/layout/the_widget.xml @@ -1,6 +1,7 @@ @@ -83,6 +87,7 @@ android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" + android:layout_marginBottom="2dp" android:text="@string/divider" style="@style/AnotherWidget.Subtitle"/> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index d41c959..13935bf 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -6,8 +6,8 @@ Concedi Accesso Rimani Aggiornato Molto bene! - Supporta - Valuta + Supportami + Valuta App Condividi | Ottieni di più dal tuo widget @@ -18,8 +18,8 @@ Concedi l\'accesso alla tua posizione per vedere il meteo. Hai completato la configurazione! Rimani aggiornato. Info - ore - min + " ore" + " min" tra Progetto Unità di Misura @@ -33,4 +33,19 @@ Impostazioni Calendario Impostazioni Meteo Impostazioni Generali + Errore nel caricamento della lista dei calendari + Formato Ora + 12 ore AM/PM + 24 ore + Tutto il giorno + Formato Data + Intervallo Aggiornamento + 30 Minuti + 1 Ora + 3 Ore + 6 Ore + 12 Ore + 24 Ore + Località Meteo + Geolocalizzazione \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..7aad204 --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9f90b50..b3712bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,14 +11,14 @@ View your events and the weather in another widget. | Share - Rate - Support + Rate App + Support Me Good Job! You have completed the configuration.\nWatch out for updates. Stay up to date About h - min + " min" in Project Unit of Measure @@ -34,4 +34,19 @@ Calendar Settings Weather Settings General Settings + Error loading the calendar list + Hour Format + 12 Hour AM/PM + 24 Hour + All Day Event + Date Format + Refresh Period + 30 Minutes + 1 Hour + 3 Hours + 6 Hours + 12 Hours + 24 Hours + Custom Location + Geolocation diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index c5bbc32..7eb17dd 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -9,7 +9,6 @@ @@ -17,7 +16,6 @@ @@ -25,7 +23,6 @@ @android:color/white 18sp center - sans-serif-light 0.6 @@ -70,7 +67,6 @@ @@ -83,12 +79,10 @@ diff --git a/build.gradle b/build.gradle index 14f21f1..0a25535 100644 --- a/build.gradle +++ b/build.gradle @@ -5,10 +5,12 @@ buildscript { repositories { google() jcenter() + maven { url 'https://maven.fabric.io/public' } } dependencies { classpath 'com.android.tools.build:gradle:3.0.0-beta7' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'io.fabric.tools:gradle:1.+' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -20,6 +22,7 @@ allprojects { google() jcenter() maven { url 'https://jitpack.io' } + maven { url 'https://maven.fabric.io/public' } } }