From d2468c96c003a45f112ddceafcb10b597b4d16cb Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 27 Dec 2020 20:08:49 +0100 Subject: [PATCH 01/61] Pump svg files added in icons folder --- icons/combo.svg | 510 ++++++++++++++++++++++++++++++++++++++++ icons/danars.svg | 237 +++++++++++++++++++ icons/insight.svg | 586 ++++++++++++++++++++++++++++++++++++++++++++++ icons/pod.svg | 37 +++ icons/veo.svg | 289 +++++++++++++++++++++++ 5 files changed, 1659 insertions(+) create mode 100644 icons/combo.svg create mode 100644 icons/danars.svg create mode 100644 icons/insight.svg create mode 100644 icons/pod.svg create mode 100644 icons/veo.svg diff --git a/icons/combo.svg b/icons/combo.svg new file mode 100644 index 0000000000..e266c30c64 --- /dev/null +++ b/icons/combo.svg @@ -0,0 +1,510 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/danars.svg b/icons/danars.svg new file mode 100644 index 0000000000..d7164a0ed7 --- /dev/null +++ b/icons/danars.svg @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/insight.svg b/icons/insight.svg new file mode 100644 index 0000000000..0d126ca315 --- /dev/null +++ b/icons/insight.svg @@ -0,0 +1,586 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/pod.svg b/icons/pod.svg new file mode 100644 index 0000000000..b97d0b8b0a --- /dev/null +++ b/icons/pod.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/icons/veo.svg b/icons/veo.svg new file mode 100644 index 0000000000..91e7c4e73d --- /dev/null +++ b/icons/veo.svg @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3fc9447294fe970cefb9259a1ff0c72e133ecb95 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 27 Dec 2020 22:19:00 +0100 Subject: [PATCH 02/61] Improve insight menu icon --- app/src/main/res/drawable/ic_insight_128.xml | 548 ++++++++--------- icons/insight_128.svg | 581 +++++++++++++++++++ 2 files changed, 821 insertions(+), 308 deletions(-) create mode 100644 icons/insight_128.svg diff --git a/app/src/main/res/drawable/ic_insight_128.xml b/app/src/main/res/drawable/ic_insight_128.xml index c9b0614b22..ed2ba096b5 100644 --- a/app/src/main/res/drawable/ic_insight_128.xml +++ b/app/src/main/res/drawable/ic_insight_128.xml @@ -4,419 +4,351 @@ android:viewportWidth="128" android:viewportHeight="128"> - - - - + android:pathData="M121.885,46.425L121.885,46.425c-1.121,-11.256 -7.977,-16.822 -18.048,-17.723c-26.206,-1.134 -52.242,-2.149 -79.498,0.663C14.103,29.846 6.337,36.163 6.337,46.371c-0.031,5.646 -0.513,11.429 -0.524,16.598C5.65,69.07 5.805,75.3 6.392,81.704C6.17,91.992 13.802,98.755 24.338,99.031c25.629,0.668 52.058,1.982 79.165,0.387c9.557,-0.563 17.299,-6.526 18.161,-17.491C122.127,70.064 122.592,58.14 121.885,46.425zM71.655,78.291c0,0.62 -0.504,1.123 -1.123,1.123H19.668c-0.62,0 -1.123,-0.504 -1.123,-1.123V60.823c0,-0.62 0.504,-1.122 1.123,-1.122h50.864c0.62,0 1.123,0.503 1.123,1.122V78.291zM52.938,51.37c-0.409,0 -0.742,-0.333 -0.742,-0.742v-7.414c0,-0.409 0.333,-0.742 0.742,-0.742h39.728c0.409,0 0.741,0.333 0.741,0.742v7.414c0,0.409 -0.332,0.742 -0.741,0.742H52.938zM97.468,77.139c0,3.379 -2.744,6.123 -6.122,6.123h-6.391c-3.379,0 -6.123,-2.744 -6.123,-6.123V65.442c0,-3.379 2.744,-6.123 6.123,-6.123h6.391c3.378,0 6.122,2.744 6.122,6.123V77.139zM110.727,97.49l-1.405,0.459V30.033l1.405,0.501V97.49z" + android:fillColor="#1F1E1C"/> + android:pathData="M52.084,43.752h4.284v6.338h-4.284z" + android:fillColor="#010101"/> + android:pathData="M66.125,42.471h-8.685c-0.632,0 -1.145,0.513 -1.145,1.145v6.595c0,0.633 0.513,1.146 1.145,1.146h8.685V42.471z" + android:fillColor="#FFFFFF"/> + android:pathData="M60.513,42.471h2.147v8.898h-2.147z" + android:fillColor="#010101"/> + android:pathData="M63.967,42.471h2.147v8.898h-2.147z" + android:fillColor="#010101"/> + android:pathData="M66.125,51.37v-8.899l3.293,2.698l0,3.502L66.125,51.37L66.125,51.37z" + android:fillColor="#FFFFFF"/> + android:pathData="M90.547,37.38H26.481c-6.921,0 -12.54,5.619 -12.54,12.541v29.905c0,6.921 5.619,12.54 12.54,12.54h64.066c6.922,0 12.541,-5.619 12.541,-12.54V49.921C103.089,43 97.469,37.38 90.547,37.38zM50.687,41.107h44.229v11.627H50.687V41.107zM71.655,78.291c0,0.62 -0.504,1.123 -1.123,1.123H19.668c-0.62,0 -1.123,-0.504 -1.123,-1.123V60.823c0,-0.62 0.504,-1.122 1.123,-1.122h50.864c0.62,0 1.123,0.503 1.123,1.122V78.291zM97.468,77.139c0,3.379 -2.744,6.123 -6.122,6.123h-6.391c-3.379,0 -6.123,-2.744 -6.123,-6.123V65.442c0,-3.379 2.744,-6.123 6.123,-6.123h6.391c3.378,0 6.122,2.744 6.122,6.123V77.139z" + android:fillColor="#A29A9A"/> + android:pathData="M90.192,37.761H26.768c-6.824,0 -12.364,5.539 -12.364,12.363v29.483c0,6.823 5.54,12.363 12.364,12.363h63.424c6.824,0 12.363,-5.54 12.363,-12.363V50.124C102.555,43.3 97.016,37.761 90.192,37.761zM52.196,43.214c0,-0.409 0.333,-0.742 0.742,-0.742h39.728c0.409,0 0.741,0.333 0.741,0.742v7.414c0,0.409 -0.332,0.742 -0.741,0.742H52.938c-0.409,0 -0.742,-0.333 -0.742,-0.742V43.214zM71.655,78.291c0,0.62 -0.504,1.123 -1.123,1.123H19.668c-0.62,0 -1.123,-0.504 -1.123,-1.123V60.823c0,-0.62 0.504,-1.122 1.123,-1.122h50.864c0.62,0 1.123,0.503 1.123,1.122V78.291zM97.468,77.139c0,3.379 -2.744,6.123 -6.122,6.123h-6.391c-3.379,0 -6.123,-2.744 -6.123,-6.123V65.442c0,-3.379 2.744,-6.123 6.123,-6.123h6.391c3.378,0 6.122,2.744 6.122,6.123V77.139z" + android:fillColor="#010101"/> + android:pathData="M28.551,48.425c0.012,-0.06 0.002,-0.105 -0.029,-0.133c-0.032,-0.028 -0.095,-0.049 -0.191,-0.061c-0.042,-0.008 -0.063,-0.033 -0.063,-0.072c0,-0.008 0.002,-0.019 0.005,-0.029c0.003,-0.01 0.006,-0.024 0.009,-0.038c0.09,0.008 0.178,0.015 0.265,0.02c0.087,0.005 0.168,0.007 0.243,0.007c0.063,0 0.14,-0.002 0.229,-0.007c0.091,-0.005 0.175,-0.011 0.257,-0.02c0.006,0.029 0.009,0.052 0.009,0.067c0,0.042 -0.022,0.064 -0.063,0.068c-0.096,0.011 -0.164,0.033 -0.203,0.062c-0.039,0.03 -0.064,0.075 -0.076,0.136l-0.445,2.313c-0.012,0.06 -0.002,0.104 0.031,0.131c0.033,0.026 0.101,0.047 0.203,0.062c0.039,0.009 0.058,0.032 0.058,0.068c0,0.018 -0.003,0.041 -0.009,0.072c-0.09,-0.008 -0.181,-0.015 -0.274,-0.02c-0.092,-0.005 -0.177,-0.007 -0.252,-0.007c-0.063,0 -0.139,0.002 -0.227,0.007c-0.089,0.005 -0.174,0.011 -0.255,0.02c-0.006,-0.03 -0.008,-0.054 -0.008,-0.072c0,-0.036 0.018,-0.058 0.054,-0.063c0.096,-0.015 0.165,-0.037 0.207,-0.065c0.042,-0.028 0.069,-0.073 0.08,-0.133L28.551,48.425L28.551,48.425z" + android:fillColor="#FFFFFF"/> + android:pathData="M30.886,49.685c0.018,-0.081 0.027,-0.149 0.027,-0.203c0,-0.087 -0.042,-0.13 -0.126,-0.13c-0.044,0 -0.1,0.025 -0.166,0.074c-0.066,0.05 -0.135,0.114 -0.207,0.193c-0.072,0.08 -0.143,0.169 -0.213,0.268c-0.071,0.099 -0.133,0.2 -0.187,0.302c-0.027,0.051 -0.054,0.108 -0.079,0.169c-0.025,0.061 -0.048,0.124 -0.067,0.189c-0.02,0.065 -0.035,0.128 -0.045,0.191c-0.01,0.063 -0.016,0.122 -0.016,0.175c0,0.042 0.005,0.083 0.013,0.122c-0.113,0.012 -0.232,0.035 -0.356,0.068c-0.024,-0.015 -0.036,-0.033 -0.036,-0.055c0,-0.006 0.002,-0.018 0.005,-0.038s0.006,-0.036 0.009,-0.047c0.069,-0.348 0.123,-0.622 0.161,-0.823c0.04,-0.202 0.069,-0.354 0.088,-0.457c0.02,-0.103 0.032,-0.171 0.037,-0.202c0.004,-0.032 0.007,-0.051 0.007,-0.057c0,-0.036 -0.012,-0.054 -0.036,-0.054c-0.012,0 -0.03,0.005 -0.055,0.015l-0.148,0.063c-0.025,0.01 -0.042,0.016 -0.054,0.016c-0.015,0 -0.028,-0.009 -0.039,-0.027c-0.01,-0.018 -0.019,-0.039 -0.025,-0.063c0.054,-0.033 0.118,-0.068 0.191,-0.106c0.074,-0.037 0.144,-0.072 0.213,-0.103c0.069,-0.032 0.129,-0.058 0.18,-0.079s0.084,-0.031 0.099,-0.031c0.021,0 0.039,0.005 0.054,0.015c0.015,0.01 0.023,0.028 0.023,0.052c0,0.009 -0.001,0.021 -0.002,0.034c-0.002,0.013 -0.004,0.027 -0.007,0.042l-0.162,0.784h0.018c0.078,-0.132 0.159,-0.256 0.243,-0.37c0.084,-0.114 0.169,-0.212 0.254,-0.294c0.086,-0.083 0.172,-0.147 0.259,-0.193c0.087,-0.047 0.175,-0.07 0.265,-0.07c0.084,0 0.151,0.021 0.2,0.062c0.05,0.042 0.075,0.111 0.075,0.207c0,0.036 -0.003,0.078 -0.008,0.126c-0.007,0.047 -0.014,0.095 -0.023,0.143l-0.23,1.08c-0.008,0.042 -0.013,0.071 -0.013,0.086c0,0.039 0.018,0.058 0.054,0.058c0.018,0 0.04,-0.006 0.063,-0.016c0.025,-0.01 0.047,-0.022 0.07,-0.036c0.023,-0.013 0.042,-0.025 0.061,-0.036c0.018,-0.01 0.033,-0.016 0.044,-0.016c0.03,0 0.051,0.03 0.063,0.091c-0.054,0.039 -0.109,0.075 -0.166,0.11c-0.058,0.034 -0.114,0.065 -0.169,0.091c-0.056,0.027 -0.108,0.049 -0.156,0.066c-0.048,0.016 -0.087,0.025 -0.117,0.025c-0.033,0 -0.064,-0.007 -0.092,-0.021c-0.028,-0.013 -0.042,-0.045 -0.042,-0.096c0,-0.009 0.001,-0.024 0.005,-0.042c0.003,-0.02 0.006,-0.037 0.008,-0.052L30.886,49.685L30.886,49.685z" + android:fillColor="#FFFFFF"/> + android:pathData="M32.902,49.549c-0.033,-0.003 -0.054,-0.01 -0.063,-0.025c-0.008,-0.013 -0.015,-0.029 -0.018,-0.047c-0.015,-0.09 -0.049,-0.159 -0.104,-0.209c-0.054,-0.049 -0.127,-0.074 -0.221,-0.074c-0.095,0 -0.178,0.023 -0.247,0.07c-0.069,0.046 -0.104,0.113 -0.104,0.2c0,0.059 0.026,0.121 0.079,0.182c0.052,0.061 0.114,0.124 0.187,0.187c0.054,0.048 0.111,0.097 0.171,0.149c0.06,0.051 0.114,0.103 0.162,0.155c0.048,0.053 0.088,0.108 0.119,0.164c0.032,0.058 0.047,0.116 0.047,0.175c0,0.088 -0.019,0.169 -0.058,0.243c-0.039,0.075 -0.091,0.141 -0.159,0.196c-0.068,0.056 -0.147,0.099 -0.239,0.132c-0.091,0.033 -0.188,0.05 -0.29,0.05c-0.105,0 -0.207,-0.009 -0.306,-0.027s-0.192,-0.046 -0.279,-0.085c0.025,-0.091 0.042,-0.174 0.057,-0.25c0.013,-0.076 0.023,-0.163 0.029,-0.259h0.044c0.073,0 0.108,0.025 0.108,0.077c-0.006,0.125 0.024,0.224 0.088,0.292c0.064,0.069 0.154,0.103 0.268,0.103c0.117,0 0.213,-0.03 0.288,-0.091c0.075,-0.062 0.113,-0.142 0.113,-0.241c0,-0.044 -0.011,-0.088 -0.034,-0.13c-0.023,-0.042 -0.052,-0.082 -0.088,-0.119c-0.036,-0.038 -0.076,-0.075 -0.122,-0.113c-0.045,-0.038 -0.091,-0.075 -0.14,-0.114c-0.09,-0.075 -0.172,-0.154 -0.245,-0.237c-0.074,-0.082 -0.11,-0.177 -0.11,-0.286c0,-0.081 0.019,-0.156 0.057,-0.225c0.037,-0.069 0.089,-0.127 0.153,-0.177c0.064,-0.049 0.14,-0.089 0.225,-0.117c0.085,-0.028 0.175,-0.042 0.272,-0.042c0.174,0 0.338,0.041 0.49,0.121c-0.015,0.045 -0.027,0.103 -0.038,0.172c-0.01,0.069 -0.019,0.138 -0.025,0.207L32.902,49.549L32.902,49.549z" + android:fillColor="#FFFFFF"/> + android:pathData="M33.951,48.573c-0.058,0 -0.102,-0.017 -0.135,-0.052c-0.033,-0.034 -0.05,-0.08 -0.05,-0.137c0,-0.081 0.027,-0.154 0.083,-0.219c0.056,-0.064 0.123,-0.096 0.201,-0.096c0.059,0 0.103,0.019 0.128,0.058c0.025,0.039 0.038,0.089 0.038,0.148c0,0.075 -0.025,0.143 -0.076,0.205C34.089,48.542 34.026,48.573 33.951,48.573zM33.721,50.674c-0.003,0.012 -0.006,0.028 -0.008,0.047c-0.003,0.02 -0.005,0.034 -0.005,0.043c0,0.036 0.018,0.054 0.054,0.054c0.022,0 0.043,-0.006 0.065,-0.016c0.023,-0.01 0.045,-0.022 0.068,-0.036c0.023,-0.013 0.042,-0.025 0.06,-0.036c0.019,-0.01 0.033,-0.016 0.045,-0.016c0.03,0 0.051,0.03 0.063,0.091c-0.051,0.039 -0.106,0.075 -0.164,0.11c-0.058,0.034 -0.115,0.065 -0.169,0.091c-0.054,0.027 -0.105,0.049 -0.153,0.066c-0.048,0.016 -0.088,0.025 -0.117,0.025c-0.033,0 -0.065,-0.007 -0.095,-0.021c-0.029,-0.013 -0.044,-0.045 -0.044,-0.096c0,-0.009 0.001,-0.025 0.004,-0.047c0.004,-0.023 0.007,-0.039 0.009,-0.047c0.066,-0.322 0.119,-0.577 0.158,-0.768s0.068,-0.336 0.088,-0.437c0.02,-0.1 0.032,-0.167 0.039,-0.2c0.006,-0.033 0.008,-0.053 0.008,-0.058c0,-0.036 -0.013,-0.054 -0.041,-0.054c-0.012,0 -0.03,0.005 -0.054,0.015c-0.025,0.01 -0.05,0.022 -0.076,0.032c-0.027,0.01 -0.052,0.021 -0.075,0.031c-0.023,0.01 -0.04,0.016 -0.052,0.016c-0.018,0 -0.031,-0.009 -0.041,-0.027c-0.008,-0.018 -0.016,-0.039 -0.023,-0.063c0.055,-0.029 0.117,-0.063 0.19,-0.101c0.072,-0.038 0.141,-0.073 0.209,-0.106c0.067,-0.033 0.127,-0.06 0.18,-0.081c0.052,-0.021 0.088,-0.031 0.106,-0.031c0.051,0 0.076,0.025 0.076,0.076c0,0.021 -0.003,0.043 -0.009,0.067L33.721,50.674L33.721,50.674z" + android:fillColor="#FFFFFF"/> + android:pathData="M35.747,49.274c-0.037,-0.011 -0.078,-0.022 -0.126,-0.029c-0.048,-0.008 -0.093,-0.011 -0.135,-0.011c-0.129,0 -0.241,0.033 -0.338,0.099s-0.176,0.157 -0.241,0.271c-0.065,0.114 -0.113,0.247 -0.144,0.4c-0.031,0.154 -0.047,0.317 -0.047,0.491c0,0.11 0.015,0.191 0.045,0.241c0.029,0.049 0.075,0.075 0.135,0.075c0.054,0 0.112,-0.028 0.175,-0.084c0.063,-0.056 0.126,-0.127 0.191,-0.216c0.064,-0.089 0.125,-0.188 0.184,-0.299c0.058,-0.111 0.11,-0.224 0.156,-0.338c0.045,-0.114 0.08,-0.224 0.106,-0.328C35.734,49.439 35.747,49.35 35.747,49.274L35.747,49.274zM34.328,51.682c0.042,0.091 0.107,0.166 0.194,0.227c0.087,0.061 0.181,0.092 0.283,0.092c0.126,0 0.238,-0.052 0.333,-0.156c0.096,-0.103 0.165,-0.254 0.207,-0.452l0.221,-1.08h-0.018c-0.126,0.264 -0.265,0.46 -0.417,0.589c-0.151,0.129 -0.296,0.193 -0.434,0.193c-0.045,0 -0.091,-0.007 -0.135,-0.021c-0.045,-0.013 -0.084,-0.037 -0.117,-0.072c-0.033,-0.034 -0.06,-0.081 -0.081,-0.14c-0.022,-0.058 -0.032,-0.134 -0.032,-0.227c0,-0.242 0.037,-0.462 0.11,-0.659c0.074,-0.196 0.169,-0.363 0.286,-0.499c0.117,-0.137 0.247,-0.242 0.39,-0.315c0.142,-0.074 0.281,-0.11 0.416,-0.11c0.106,0 0.202,0.004 0.29,0.013c0.089,0.008 0.192,0.025 0.313,0.049l-0.414,2.116c-0.033,0.171 -0.089,0.316 -0.167,0.434c-0.078,0.119 -0.165,0.217 -0.261,0.293c-0.095,0.076 -0.197,0.132 -0.304,0.166c-0.107,0.035 -0.205,0.052 -0.294,0.052c-0.225,0 -0.401,-0.03 -0.527,-0.09c0.022,-0.066 0.038,-0.124 0.05,-0.172s0.023,-0.11 0.031,-0.189L34.328,51.682L34.328,51.682z" + android:fillColor="#FFFFFF"/> + android:pathData="M36.912,48.253c0,-0.015 -0.002,-0.03 -0.007,-0.044c-0.005,-0.015 -0.017,-0.023 -0.038,-0.023c-0.009,0 -0.025,0.002 -0.047,0.007c-0.023,0.005 -0.046,0.008 -0.07,0.013c-0.025,0.005 -0.047,0.008 -0.068,0.011c-0.021,0.003 -0.036,0.005 -0.045,0.005c-0.041,0 -0.063,-0.031 -0.063,-0.094c0.136,-0.036 0.26,-0.073 0.376,-0.11c0.115,-0.038 0.23,-0.079 0.344,-0.124c0.036,0.024 0.054,0.052 0.054,0.085c0,0.012 -0.001,0.025 -0.005,0.039c-0.003,0.013 -0.006,0.025 -0.008,0.034l-0.383,1.931h0.014c0.08,-0.132 0.161,-0.256 0.242,-0.37c0.081,-0.114 0.164,-0.212 0.248,-0.294c0.084,-0.083 0.169,-0.147 0.257,-0.193c0.087,-0.047 0.174,-0.07 0.26,-0.07c0.088,0 0.158,0.021 0.209,0.062c0.053,0.042 0.079,0.111 0.079,0.207c0,0.036 -0.003,0.078 -0.009,0.126c-0.006,0.047 -0.013,0.095 -0.023,0.143l-0.229,1.08c-0.003,0.012 -0.006,0.027 -0.008,0.045c-0.004,0.018 -0.005,0.031 -0.005,0.041c0,0.039 0.018,0.058 0.054,0.058c0.018,0 0.039,-0.006 0.063,-0.016c0.024,-0.01 0.047,-0.022 0.07,-0.036c0.023,-0.013 0.042,-0.025 0.06,-0.036c0.018,-0.01 0.033,-0.016 0.045,-0.016c0.03,0 0.051,0.03 0.063,0.091c-0.055,0.039 -0.109,0.075 -0.167,0.11c-0.057,0.034 -0.113,0.065 -0.169,0.091c-0.056,0.027 -0.107,0.049 -0.153,0.066c-0.046,0.016 -0.085,0.025 -0.115,0.025c-0.033,0 -0.064,-0.007 -0.094,-0.021c-0.03,-0.013 -0.045,-0.045 -0.045,-0.096c0,-0.009 0.002,-0.025 0.005,-0.047c0.003,-0.023 0.007,-0.039 0.009,-0.047l0.252,-1.202c0.018,-0.084 0.027,-0.152 0.027,-0.203c0,-0.087 -0.042,-0.13 -0.126,-0.13c-0.042,0 -0.094,0.022 -0.158,0.067c-0.063,0.045 -0.13,0.106 -0.2,0.182c-0.071,0.076 -0.142,0.166 -0.214,0.268c-0.072,0.102 -0.14,0.208 -0.203,0.32c-0.026,0.051 -0.053,0.108 -0.078,0.169c-0.025,0.061 -0.047,0.125 -0.065,0.191c-0.019,0.066 -0.033,0.13 -0.043,0.193c-0.01,0.063 -0.015,0.12 -0.015,0.171c0,0.042 0.004,0.083 0.013,0.122c-0.114,0.012 -0.233,0.035 -0.356,0.068c-0.027,-0.015 -0.041,-0.033 -0.041,-0.055c0,-0.011 0.002,-0.025 0.005,-0.042c0.003,-0.016 0.006,-0.031 0.008,-0.042l0.437,-2.25c0.018,-0.087 0.031,-0.174 0.041,-0.258C36.908,48.368 36.912,48.301 36.912,48.253L36.912,48.253z" + android:fillColor="#FFFFFF"/> + android:pathData="M39.108,49.032c0.024,-0.114 0.036,-0.206 0.036,-0.274c0,-0.04 -0.005,-0.08 -0.013,-0.122c0.057,-0.009 0.117,-0.018 0.18,-0.027c0.062,-0.008 0.125,-0.023 0.189,-0.041c0.024,0.018 0.036,0.036 0.036,0.055c0,0.006 -0.001,0.018 -0.002,0.036c-0.002,0.018 -0.004,0.033 -0.007,0.044l-0.077,0.406h0.464c-0.009,0.027 -0.018,0.06 -0.027,0.099c-0.008,0.039 -0.016,0.075 -0.023,0.108c-0.075,-0.011 -0.151,-0.021 -0.229,-0.026c-0.078,-0.007 -0.152,-0.01 -0.221,-0.014l-0.247,1.404c-0.009,0.045 -0.013,0.076 -0.013,0.094c0,0.073 0.043,0.108 0.13,0.108c0.045,0 0.086,-0.006 0.124,-0.016c0.038,-0.01 0.072,-0.023 0.102,-0.038c0.026,-0.012 0.05,-0.024 0.069,-0.034c0.02,-0.01 0.036,-0.016 0.048,-0.016c0.033,0 0.052,0.028 0.058,0.086c-0.093,0.072 -0.194,0.129 -0.304,0.171c-0.11,0.042 -0.213,0.063 -0.308,0.063c-0.108,0 -0.185,-0.017 -0.23,-0.052c-0.044,-0.035 -0.067,-0.086 -0.067,-0.156c0,-0.033 0.003,-0.064 0.008,-0.094l0.284,-1.535H38.74c0.006,-0.051 0.015,-0.09 0.029,-0.115c0.013,-0.025 0.037,-0.038 0.07,-0.038h0.257L39.108,49.032L39.108,49.032z" + android:fillColor="#FFFFFF"/> + android:pathData="M22.548,45.016l-0.201,-1.2l-0.649,1.2C21.699,45.016 22.548,45.016 22.548,45.016zM21.138,46.055c-0.025,0.048 -0.037,0.088 -0.037,0.118c0,0.041 0.024,0.072 0.07,0.091s0.118,0.035 0.214,0.049c0.061,0.01 0.092,0.036 0.092,0.077c0,0.017 -0.004,0.042 -0.01,0.076c-0.103,-0.009 -0.198,-0.018 -0.286,-0.023c-0.088,-0.006 -0.179,-0.008 -0.275,-0.008c-0.069,0 -0.14,0.002 -0.213,0.005c-0.075,0.004 -0.156,0.012 -0.245,0.025c-0.003,-0.013 -0.007,-0.027 -0.01,-0.041c-0.003,-0.014 -0.005,-0.025 -0.005,-0.036c0,-0.045 0.029,-0.073 0.088,-0.083c0.178,-0.03 0.293,-0.096 0.344,-0.195l1.648,-3.031c0.02,-0.034 0.046,-0.052 0.076,-0.052c0.01,0 0.021,0.002 0.031,0.006c0.01,0.003 0.019,0.007 0.025,0.01l0.551,3.052c0.01,0.061 0.041,0.108 0.093,0.139c0.051,0.031 0.118,0.053 0.2,0.067c0.045,0.007 0.075,0.017 0.088,0.031c0.014,0.013 0.021,0.03 0.021,0.051c0,0.017 -0.004,0.043 -0.01,0.077c-0.096,-0.007 -0.188,-0.013 -0.275,-0.018c-0.088,-0.006 -0.177,-0.008 -0.27,-0.008c-0.203,0 -0.404,0.01 -0.603,0.03c-0.01,-0.024 -0.015,-0.049 -0.015,-0.076c0,-0.045 0.032,-0.073 0.097,-0.083c0.045,-0.007 0.093,-0.022 0.144,-0.046c0.052,-0.024 0.077,-0.061 0.077,-0.113v-0.031c0,-0.013 -0.002,-0.029 -0.005,-0.046l-0.155,-0.859h-0.988L21.138,46.055L21.138,46.055z" + android:fillColor="#FFFFFF"/> + android:pathData="M25.317,46.498c-0.271,0 -0.502,-0.036 -0.691,-0.108c-0.191,-0.073 -0.346,-0.171 -0.466,-0.296c-0.121,-0.125 -0.207,-0.272 -0.263,-0.438c-0.055,-0.166 -0.082,-0.345 -0.082,-0.538c0,-0.251 0.042,-0.5 0.124,-0.749c0.082,-0.249 0.206,-0.473 0.371,-0.672c0.165,-0.199 0.372,-0.36 0.62,-0.484c0.249,-0.124 0.541,-0.186 0.878,-0.186c0.172,0 0.337,0.014 0.496,0.041c0.16,0.027 0.313,0.065 0.461,0.113c-0.01,0.1 -0.016,0.197 -0.016,0.293c0,0.069 0.003,0.138 0.008,0.206c0.005,0.069 0.01,0.138 0.018,0.207c-0.025,0.017 -0.055,0.025 -0.093,0.025c-0.065,0 -0.099,-0.025 -0.103,-0.077c-0.03,-0.226 -0.115,-0.384 -0.252,-0.473c-0.138,-0.09 -0.321,-0.134 -0.551,-0.134c-0.226,0 -0.429,0.049 -0.607,0.147c-0.178,0.097 -0.33,0.23 -0.456,0.399c-0.124,0.168 -0.22,0.364 -0.286,0.589c-0.065,0.225 -0.097,0.463 -0.097,0.713c0,0.186 0.025,0.353 0.075,0.502c0.05,0.149 0.119,0.276 0.208,0.381c0.089,0.105 0.198,0.186 0.326,0.244c0.129,0.058 0.274,0.088 0.435,0.088c0.234,0 0.418,-0.048 0.554,-0.144c0.136,-0.096 0.253,-0.25 0.353,-0.463c0.024,-0.055 0.065,-0.082 0.124,-0.082c0.021,0 0.042,0.004 0.064,0.012s0.037,0.017 0.043,0.024c-0.051,0.109 -0.096,0.225 -0.136,0.347c-0.04,0.122 -0.08,0.258 -0.121,0.409c-0.075,0.014 -0.157,0.026 -0.242,0.039c-0.086,0.012 -0.172,0.024 -0.257,0.033c-0.086,0.01 -0.166,0.019 -0.241,0.024C25.437,46.495 25.372,46.498 25.317,46.498L25.317,46.498z" + android:fillColor="#FFFFFF"/> + android:pathData="M28.471,46.498c-0.271,0 -0.502,-0.036 -0.691,-0.108c-0.191,-0.073 -0.346,-0.171 -0.466,-0.296c-0.121,-0.125 -0.207,-0.272 -0.263,-0.438c-0.055,-0.166 -0.082,-0.345 -0.082,-0.538c0,-0.251 0.042,-0.5 0.124,-0.749c0.082,-0.249 0.206,-0.473 0.371,-0.672c0.165,-0.199 0.372,-0.36 0.62,-0.484c0.249,-0.124 0.541,-0.186 0.878,-0.186c0.172,0 0.337,0.014 0.496,0.041c0.16,0.027 0.313,0.065 0.461,0.113c-0.01,0.1 -0.016,0.197 -0.016,0.293c0,0.069 0.003,0.138 0.008,0.206c0.005,0.069 0.01,0.138 0.018,0.207c-0.025,0.017 -0.056,0.025 -0.093,0.025c-0.065,0 -0.099,-0.025 -0.103,-0.077c-0.03,-0.226 -0.115,-0.384 -0.252,-0.473c-0.138,-0.09 -0.321,-0.134 -0.551,-0.134c-0.226,0 -0.429,0.049 -0.607,0.147c-0.178,0.097 -0.33,0.23 -0.456,0.399c-0.125,0.168 -0.22,0.364 -0.286,0.589c-0.065,0.225 -0.097,0.463 -0.097,0.713c0,0.186 0.025,0.353 0.075,0.502s0.119,0.276 0.208,0.381c0.089,0.105 0.198,0.186 0.326,0.244c0.129,0.058 0.274,0.088 0.435,0.088c0.234,0 0.418,-0.048 0.554,-0.144c0.136,-0.096 0.253,-0.25 0.353,-0.463c0.024,-0.055 0.065,-0.082 0.124,-0.082c0.021,0 0.042,0.004 0.064,0.012c0.023,0.008 0.037,0.017 0.043,0.024c-0.051,0.109 -0.096,0.225 -0.136,0.347s-0.08,0.258 -0.121,0.409c-0.075,0.014 -0.157,0.026 -0.242,0.039c-0.086,0.012 -0.172,0.024 -0.257,0.033c-0.086,0.01 -0.166,0.019 -0.241,0.024C28.592,46.495 28.527,46.498 28.471,46.498L28.471,46.498z" + android:fillColor="#FFFFFF"/> + android:pathData="M32.944,45.289c-0.03,0.172 -0.085,0.331 -0.162,0.478c-0.076,0.148 -0.174,0.275 -0.293,0.384c-0.118,0.108 -0.257,0.192 -0.414,0.255c-0.158,0.061 -0.336,0.092 -0.535,0.092c-0.196,0 -0.366,-0.031 -0.51,-0.095c-0.143,-0.063 -0.26,-0.149 -0.35,-0.257c-0.089,-0.108 -0.149,-0.236 -0.18,-0.383c-0.03,-0.148 -0.029,-0.307 0.006,-0.479l0.355,-1.837c0.014,-0.072 -0.006,-0.124 -0.058,-0.154c-0.054,-0.031 -0.118,-0.05 -0.193,-0.057c-0.052,-0.008 -0.077,-0.035 -0.077,-0.083c0,-0.024 0.006,-0.055 0.016,-0.092c0.206,0.021 0.394,0.031 0.566,0.031c0.072,0 0.165,-0.003 0.28,-0.008c0.115,-0.006 0.219,-0.013 0.311,-0.024c0.004,0.017 0.007,0.033 0.008,0.046c0.002,0.014 0.003,0.025 0.003,0.036c0,0.021 -0.006,0.039 -0.018,0.055c-0.012,0.015 -0.032,0.025 -0.059,0.028c-0.089,0.013 -0.163,0.037 -0.224,0.069c-0.06,0.033 -0.097,0.082 -0.11,0.147l-0.34,1.755c-0.024,0.13 -0.029,0.257 -0.018,0.38c0.012,0.124 0.046,0.235 0.101,0.332c0.055,0.098 0.131,0.177 0.229,0.237c0.097,0.06 0.22,0.091 0.368,0.091c0.124,0 0.242,-0.018 0.357,-0.054c0.115,-0.037 0.222,-0.094 0.319,-0.175c0.098,-0.08 0.183,-0.186 0.255,-0.317c0.073,-0.13 0.127,-0.291 0.165,-0.483l0.335,-1.755c0.013,-0.069 -0.004,-0.121 -0.052,-0.155c-0.048,-0.034 -0.116,-0.058 -0.206,-0.072c-0.042,-0.004 -0.062,-0.031 -0.062,-0.083c0,-0.01 0.001,-0.022 0.003,-0.036c0.002,-0.013 0.005,-0.029 0.008,-0.046c0.103,0.01 0.188,0.018 0.253,0.024c0.065,0.005 0.132,0.008 0.201,0.008c0.061,0 0.129,-0.002 0.203,-0.006c0.074,-0.003 0.156,-0.01 0.244,-0.02c0.004,0.017 0.008,0.032 0.01,0.046c0.004,0.013 0.006,0.025 0.006,0.036c0,0.044 -0.023,0.07 -0.067,0.077c-0.086,0.013 -0.157,0.038 -0.211,0.072s-0.09,0.082 -0.103,0.144C33.299,43.441 32.944,45.289 32.944,45.289z" + android:fillColor="#FFFFFF"/> + android:pathData="M35.034,45.073c-0.014,0.109 -0.036,0.181 -0.067,0.216c-0.031,0.034 -0.077,0.051 -0.14,0.051h-1.019c0.014,-0.109 0.035,-0.181 0.064,-0.216c0.029,-0.034 0.076,-0.051 0.141,-0.051H35.034L35.034,45.073z" + android:fillColor="#FFFFFF"/> + android:pathData="M37.077,46.498c-0.271,0 -0.502,-0.036 -0.692,-0.108c-0.191,-0.073 -0.345,-0.171 -0.466,-0.296c-0.12,-0.125 -0.207,-0.272 -0.262,-0.438c-0.055,-0.166 -0.082,-0.345 -0.082,-0.538c0,-0.251 0.041,-0.5 0.124,-0.749c0.082,-0.249 0.206,-0.473 0.371,-0.672c0.164,-0.199 0.371,-0.36 0.62,-0.484c0.249,-0.124 0.541,-0.186 0.877,-0.186c0.172,0 0.338,0.014 0.497,0.041s0.313,0.065 0.46,0.113c-0.009,0.1 -0.015,0.197 -0.015,0.293c0,0.069 0.003,0.138 0.008,0.206c0.006,0.069 0.011,0.138 0.018,0.207c-0.024,0.017 -0.055,0.025 -0.092,0.025c-0.065,0 -0.099,-0.025 -0.103,-0.077c-0.031,-0.226 -0.115,-0.384 -0.252,-0.473c-0.138,-0.09 -0.322,-0.134 -0.551,-0.134c-0.226,0 -0.429,0.049 -0.607,0.147c-0.178,0.097 -0.33,0.23 -0.456,0.399c-0.125,0.168 -0.221,0.364 -0.286,0.589c-0.065,0.225 -0.098,0.463 -0.098,0.713c0,0.186 0.025,0.353 0.075,0.502c0.049,0.149 0.119,0.276 0.208,0.381c0.089,0.105 0.198,0.186 0.326,0.244c0.128,0.058 0.274,0.088 0.435,0.088c0.233,0 0.418,-0.048 0.554,-0.144c0.135,-0.096 0.253,-0.25 0.352,-0.463c0.025,-0.055 0.066,-0.082 0.124,-0.082c0.021,0 0.042,0.004 0.065,0.012c0.022,0.008 0.037,0.017 0.043,0.024c-0.052,0.109 -0.097,0.225 -0.137,0.347c-0.039,0.122 -0.079,0.258 -0.121,0.409c-0.075,0.014 -0.156,0.026 -0.241,0.039c-0.086,0.012 -0.172,0.024 -0.257,0.033c-0.086,0.01 -0.167,0.019 -0.242,0.024C37.197,46.495 37.132,46.498 37.077,46.498L37.077,46.498z" + android:fillColor="#FFFFFF"/> + android:pathData="M41.4,43.446c0.013,-0.068 0.002,-0.119 -0.036,-0.152c-0.038,-0.032 -0.11,-0.058 -0.217,-0.075c-0.048,-0.01 -0.072,-0.034 -0.072,-0.072c0,-0.01 0.002,-0.024 0.005,-0.039c0.004,-0.015 0.008,-0.03 0.01,-0.043c0.103,0.007 0.206,0.013 0.307,0.02c0.101,0.008 0.193,0.01 0.275,0.01c0.072,0 0.159,-0.002 0.262,-0.008c0.103,-0.005 0.201,-0.013 0.293,-0.023c0.008,0.027 0.01,0.055 0.01,0.082c0,0.041 -0.022,0.063 -0.067,0.067c-0.103,0.017 -0.179,0.042 -0.229,0.077c-0.049,0.034 -0.081,0.086 -0.095,0.154l-0.504,2.641c-0.014,0.068 0.001,0.118 0.043,0.149c0.043,0.031 0.116,0.055 0.219,0.072c0.044,0.01 0.067,0.036 0.067,0.077c0,0.021 -0.004,0.048 -0.01,0.082c-0.099,-0.009 -0.204,-0.018 -0.311,-0.023c-0.108,-0.006 -0.205,-0.008 -0.29,-0.008c-0.069,0 -0.157,0.002 -0.263,0.008c-0.106,0.005 -0.206,0.013 -0.298,0.023c-0.007,-0.034 -0.01,-0.061 -0.01,-0.082c0,-0.044 0.021,-0.07 0.061,-0.077c0.121,-0.021 0.204,-0.045 0.25,-0.075s0.076,-0.078 0.091,-0.146l0.241,-1.261h-1.462l-0.241,1.261c-0.014,0.068 0,0.118 0.041,0.149c0.042,0.031 0.119,0.055 0.232,0.072c0.044,0.004 0.067,0.029 0.067,0.077c0,0.021 -0.004,0.048 -0.01,0.082c-0.103,-0.009 -0.209,-0.018 -0.319,-0.023c-0.11,-0.006 -0.207,-0.008 -0.293,-0.008c-0.069,0 -0.153,0.002 -0.253,0.008c-0.099,0.005 -0.193,0.013 -0.283,0.023c-0.01,-0.024 -0.015,-0.051 -0.015,-0.082c0,-0.044 0.022,-0.069 0.067,-0.072c0.109,-0.017 0.188,-0.042 0.234,-0.075c0.046,-0.033 0.076,-0.084 0.091,-0.152l0.509,-2.641c0.013,-0.068 0.002,-0.121 -0.034,-0.157c-0.036,-0.036 -0.108,-0.062 -0.219,-0.08c-0.048,-0.003 -0.072,-0.027 -0.072,-0.072c0,-0.025 0.005,-0.05 0.015,-0.077c0.1,0.01 0.198,0.018 0.296,0.024c0.098,0.005 0.19,0.008 0.275,0.008c0.069,0 0.158,-0.003 0.271,-0.008c0.111,-0.006 0.213,-0.013 0.306,-0.024c0.01,0.027 0.016,0.053 0.016,0.077c0,0.041 -0.025,0.065 -0.073,0.072c-0.109,0.018 -0.191,0.044 -0.241,0.08c-0.052,0.036 -0.084,0.089 -0.098,0.157l-0.232,1.179h1.462L41.4,43.446L41.4,43.446z" + android:fillColor="#FFFFFF"/> + android:pathData="M43.202,43.441c0.013,-0.069 -0.006,-0.119 -0.057,-0.149c-0.052,-0.031 -0.119,-0.052 -0.201,-0.062c-0.048,-0.01 -0.073,-0.04 -0.073,-0.088c0,-0.01 0.001,-0.022 0.003,-0.036c0.002,-0.013 0.005,-0.029 0.008,-0.046c0.103,0.01 0.207,0.018 0.314,0.024c0.107,0.005 0.206,0.008 0.299,0.008h0.972c0.147,0 0.251,-0.006 0.308,-0.016c0.058,-0.009 0.107,-0.015 0.144,-0.015c0.044,0 0.073,0.021 0.082,0.062c0.008,0.058 0.016,0.146 0.026,0.265c0.01,0.118 0.03,0.253 0.061,0.404c-0.013,0.007 -0.031,0.014 -0.051,0.024c-0.021,0.008 -0.04,0.012 -0.057,0.012c-0.045,0 -0.075,-0.021 -0.088,-0.061c-0.044,-0.175 -0.11,-0.299 -0.195,-0.371c-0.086,-0.073 -0.215,-0.108 -0.387,-0.108H43.67l-0.257,1.343h0.705c0.075,0 0.13,-0.025 0.165,-0.076c0.034,-0.052 0.065,-0.123 0.092,-0.211c0.007,-0.017 0.016,-0.031 0.028,-0.041c0.011,-0.01 0.031,-0.015 0.058,-0.015c0.031,0 0.064,0.007 0.098,0.021c-0.021,0.082 -0.039,0.157 -0.054,0.224c-0.015,0.067 -0.029,0.135 -0.042,0.204c-0.012,0.068 -0.022,0.141 -0.031,0.216c-0.008,0.075 -0.016,0.161 -0.023,0.257c-0.031,0.009 -0.062,0.015 -0.092,0.015c-0.031,0 -0.053,-0.008 -0.065,-0.025c-0.011,-0.018 -0.016,-0.037 -0.012,-0.057c0.007,-0.079 0,-0.151 -0.021,-0.217c-0.021,-0.065 -0.069,-0.097 -0.144,-0.097h-0.7l-0.241,1.276c-0.01,0.055 -0.003,0.091 0.023,0.11c0.025,0.019 0.068,0.028 0.126,0.028h0.591c0.148,0 0.28,-0.038 0.397,-0.113c0.116,-0.075 0.238,-0.206 0.365,-0.39c0.014,-0.018 0.026,-0.03 0.039,-0.039c0.012,-0.008 0.028,-0.013 0.049,-0.013s0.041,0.005 0.061,0.015c0.021,0.01 0.04,0.025 0.057,0.041c-0.017,0.034 -0.034,0.071 -0.051,0.108c-0.017,0.03 -0.035,0.067 -0.052,0.108c-0.017,0.041 -0.034,0.083 -0.051,0.124c-0.028,0.069 -0.05,0.136 -0.067,0.201c-0.018,0.065 -0.035,0.111 -0.052,0.139c-0.017,0.027 -0.044,0.041 -0.082,0.041c-0.058,0 -0.117,-0.005 -0.175,-0.013c-0.058,-0.008 -0.137,-0.012 -0.237,-0.012h-1.215c-0.072,0 -0.16,0.002 -0.265,0.008c-0.105,0.005 -0.203,0.013 -0.295,0.023c-0.004,-0.017 -0.007,-0.032 -0.008,-0.046c-0.001,-0.013 -0.002,-0.025 -0.002,-0.036c0,-0.017 0.005,-0.034 0.015,-0.051c0.01,-0.018 0.029,-0.028 0.057,-0.031c0.107,-0.017 0.186,-0.043 0.237,-0.077c0.052,-0.034 0.082,-0.081 0.092,-0.139L43.202,43.441L43.202,43.441z" + android:fillColor="#FFFFFF"/> + android:pathData="M46.361,44.727l0.01,-0.072l1.266,-1.148c0.069,-0.058 0.103,-0.111 0.103,-0.159c0,-0.062 -0.061,-0.103 -0.185,-0.124c-0.048,-0.01 -0.072,-0.036 -0.072,-0.077c0,-0.025 0.003,-0.054 0.01,-0.088c0.099,0.01 0.185,0.018 0.257,0.024c0.073,0.005 0.153,0.008 0.242,0.008c0.075,0 0.149,-0.003 0.221,-0.008c0.073,-0.006 0.152,-0.013 0.237,-0.024c0.004,0.017 0.007,0.033 0.008,0.046c0.001,0.014 0.002,0.025 0.002,0.036c0,0.045 -0.022,0.073 -0.067,0.083c-0.078,0.017 -0.146,0.042 -0.203,0.075c-0.057,0.032 -0.109,0.071 -0.158,0.116l-1.266,1.153l0.963,1.549c0.03,0.048 0.073,0.091 0.125,0.126c0.054,0.036 0.118,0.061 0.193,0.075c0.027,0.007 0.044,0.016 0.051,0.025c0.008,0.01 0.01,0.023 0.01,0.037c0,0.024 -0.008,0.053 -0.025,0.087c-0.195,-0.02 -0.358,-0.03 -0.489,-0.03c-0.079,0 -0.142,-0.024 -0.191,-0.07c-0.048,-0.046 -0.102,-0.114 -0.159,-0.203L46.361,44.727L46.361,44.727zM46.053,43.441c0.007,-0.041 0.003,-0.075 -0.01,-0.101c-0.014,-0.025 -0.034,-0.046 -0.059,-0.061c-0.025,-0.015 -0.055,-0.026 -0.088,-0.033c-0.032,-0.008 -0.064,-0.012 -0.095,-0.016c-0.048,-0.007 -0.072,-0.034 -0.072,-0.082c0,-0.01 0.002,-0.024 0.005,-0.039c0.004,-0.015 0.008,-0.032 0.01,-0.049c0.103,0.01 0.205,0.018 0.304,0.024c0.1,0.005 0.192,0.008 0.278,0.008c0.072,0 0.162,-0.003 0.27,-0.008c0.108,-0.006 0.208,-0.013 0.302,-0.024c0.003,0.017 0.006,0.033 0.008,0.046c0.002,0.014 0.002,0.027 0.002,0.041c0,0.042 -0.024,0.067 -0.072,0.077c-0.09,0.013 -0.164,0.036 -0.224,0.067c-0.06,0.03 -0.097,0.08 -0.111,0.149l-0.509,2.646c-0.007,0.041 -0.005,0.075 0.006,0.1c0.01,0.025 0.028,0.047 0.054,0.064s0.056,0.03 0.09,0.039c0.035,0.008 0.071,0.015 0.108,0.018c0.041,0.008 0.061,0.033 0.061,0.077c0,0.01 0,0.023 -0.002,0.036c-0.002,0.014 -0.005,0.029 -0.008,0.046c-0.104,-0.009 -0.206,-0.018 -0.307,-0.023c-0.101,-0.006 -0.195,-0.008 -0.281,-0.008c-0.072,0 -0.161,0.002 -0.27,0.008c-0.108,0.005 -0.208,0.013 -0.301,0.023c-0.004,-0.017 -0.007,-0.032 -0.008,-0.046c-0.002,-0.013 -0.003,-0.025 -0.003,-0.036c0,-0.044 0.021,-0.07 0.061,-0.077c0.093,-0.013 0.171,-0.037 0.235,-0.069c0.063,-0.033 0.102,-0.084 0.115,-0.152L46.053,43.441L46.053,43.441z" + android:fillColor="#FFFFFF"/> + android:pathData="M44.998,82.892c0.738,0 1.338,0.6 1.338,1.338c0,0.738 -0.6,1.337 -1.338,1.337c-0.738,0 -1.338,-0.599 -1.338,-1.337C43.659,83.492 44.259,82.892 44.998,82.892zM44.998,83.098c0.624,0 1.132,0.507 1.132,1.133c0,0.624 -0.507,1.132 -1.132,1.132c-0.625,0 -1.133,-0.507 -1.133,-1.132C43.865,83.605 44.372,83.098 44.998,83.098z" + android:fillColor="#FFFFFF"/> - - - - - - - - - - + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:strokeLineCap="round"/> - + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:strokeLineCap="round"/> + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:strokeLineCap="round"/> + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:strokeLineCap="round"/> + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:strokeLineCap="round"/> + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF" + android:strokeLineCap="round"/> + android:pathData="M44.38,84.066h1.236v0.289h-1.236z" + android:fillColor="#FFFFFF"/> + android:pathData="M45.142,84.828v-1.236h-0.289v1.236H45.142z" + android:fillColor="#FFFFFF"/> + android:pathData="M47.301,86.381c0.056,-0.055 0.056,-0.144 0.001,-0.2l-0.98,-0.995c-0.055,-0.056 -0.144,-0.056 -0.2,-0.001l-0.202,0.198c-0.056,0.055 -0.056,0.144 -0.001,0.2l0.98,0.995c0.055,0.056 0.144,0.057 0.2,0.002L47.301,86.381z" + android:fillColor="#FFFFFF"/> + android:pathData="M91.724,57.653h-7.218c-3.945,0 -7.148,3.203 -7.148,7.148V77.86c0,3.945 3.203,7.147 7.148,7.147h7.218c3.944,0 7.147,-3.202 7.147,-7.147V64.801C98.872,60.855 95.669,57.653 91.724,57.653zM97.468,77.139c0,3.379 -2.744,6.123 -6.122,6.123h-6.391c-3.379,0 -6.123,-2.744 -6.123,-6.123V65.442c0,-3.379 2.744,-6.123 6.123,-6.123h6.391c3.378,0 6.122,2.744 6.122,6.123V77.139z" + android:fillColor="#434040"/> + android:pathData="M91.65,58.009h-6.975c-3.829,0 -6.938,3.109 -6.938,6.938v12.636c0,3.829 3.109,6.938 6.938,6.938h6.975c3.829,0 6.938,-3.109 6.938,-6.938V64.947C98.588,61.118 95.479,58.009 91.65,58.009zM97.468,77.139c0,3.379 -2.744,6.123 -6.122,6.123h-6.391c-3.379,0 -6.123,-2.744 -6.123,-6.123V65.442c0,-3.379 2.744,-6.123 6.123,-6.123h6.391c3.378,0 6.122,2.744 6.122,6.123V77.139z" + android:fillColor="#010101"/> + android:pathData="M91.556,58.862h-6.811c-3.531,0 -6.397,2.866 -6.397,6.397v12.135c0,3.531 2.866,6.397 6.397,6.397h6.811c3.531,0 6.397,-2.866 6.397,-6.397V65.259C97.953,61.728 95.087,58.862 91.556,58.862zM97.468,77.139c0,3.379 -2.744,6.123 -6.122,6.123h-6.391c-3.379,0 -6.123,-2.744 -6.123,-6.123V65.442c0,-3.379 2.744,-6.123 6.123,-6.123h6.391c3.378,0 6.122,2.744 6.122,6.123V77.139z" + android:fillColor="#9D9292"/> + android:pathData="M88.171,62.074l1.886,2.323h-3.773L88.171,62.074z" + android:fillColor="#FFFFFF"/> + android:pathData="M88.339,81.185l-1.885,-2.324h3.772L88.339,81.185z" + android:fillColor="#FFFFFF"/> + android:pathData="M91.955,67.285H84.27c-1.653,0 -2.995,1.342 -2.995,2.995v3.02c0,1.653 1.341,2.995 2.995,2.995h7.685c1.652,0 2.995,-1.342 2.995,-2.995v-3.02C94.949,68.627 93.607,67.285 91.955,67.285zM92.795,73.567c0,1.013 -0.822,1.835 -1.835,1.835h-5.651c-1.014,0 -1.836,-0.822 -1.836,-1.835v-3.672c0,-1.013 0.822,-1.835 1.836,-1.835h5.651c1.013,0 1.835,0.822 1.835,1.835V73.567z" + android:fillColor="#776E6E"/> + android:pathData="M88.188,71.589m-1.441,0a1.441,1.441 0,1 1,2.882 0a1.441,1.441 0,1 1,-2.882 0" + android:fillColor="#FFFFFF"/> + android:pathData="M90.713,74.654h-5.102c-0.845,0 -1.532,-0.687 -1.532,-1.531v-2.811c0,-0.845 0.687,-1.532 1.532,-1.532h5.102c0.845,0 1.532,0.687 1.532,1.532v2.811C92.245,73.968 91.558,74.654 90.713,74.654zM85.612,69.034c-0.705,0 -1.278,0.574 -1.278,1.279v2.811c0,0.704 0.574,1.278 1.278,1.278h5.102c0.705,0 1.279,-0.573 1.279,-1.278v-2.811c0,-0.705 -0.574,-1.279 -1.279,-1.279H85.612z" + android:fillColor="#FFFFFF"/> + android:pathData="M71.03,59.197H19.181c-0.651,0 -1.178,0.528 -1.178,1.179v18.332c0,0.651 0.527,1.179 1.178,1.179H71.03c0.651,0 1.179,-0.528 1.179,-1.179V60.376C72.209,59.726 71.68,59.197 71.03,59.197zM71.655,78.291c0,0.62 -0.504,1.123 -1.123,1.123H19.668c-0.62,0 -1.123,-0.504 -1.123,-1.123V60.823c0,-0.62 0.504,-1.122 1.123,-1.122h50.864c0.62,0 1.123,0.503 1.123,1.122V78.291z" + android:fillColor="#494444"/> + android:pathData="M70.915,76.941c0,-0.166 -0.135,-0.301 -0.301,-0.301H19.452c-0.166,0 -0.301,0.135 -0.301,0.301v1.462c0,0.166 0.135,0.302 0.301,0.302h51.162c0.166,0 0.301,-0.136 0.301,-0.302V76.941z" + android:fillColor="#FFFFFF"/> + android:pathData="M70.502,77.221c0,-0.111 -0.091,-0.202 -0.203,-0.202H19.732c-0.112,0 -0.203,0.091 -0.203,0.202v0.98c0,0.111 0.091,0.202 0.203,0.202H70.3c0.112,0 0.203,-0.091 0.203,-0.202V77.221z" + android:fillColor="#23211F"/> + android:pathData="M19.815,77.257h45.591v0.894h-45.591z" + android:fillColor="#F27E30"/> + android:pathData="M65.098,77.245h5.136v0.905h-5.136z" + android:fillColor="#5D5555"/> + android:pathData="M66.272,76.856l-0.855,0.86l0.266,0.268l0.855,-0.861L66.272,76.856z" + android:fillColor="#A79998"/> + android:pathData="M65.683,77.438l0.855,0.861l-0.266,0.267l-0.855,-0.861L65.683,77.438z" + android:fillColor="#A79998"/> + android:pathData="M71.002,61.438l-1.784,1.013v-2.026L71.002,61.438L71.002,61.438z" + android:fillColor="#6AAE46"/> + android:pathData="M48.727,61.49c0,-0.326 0.031,-0.589 0.093,-0.788c0.062,-0.2 0.155,-0.353 0.278,-0.461c0.123,-0.108 0.277,-0.162 0.464,-0.162c0.138,0 0.258,0.03 0.362,0.09c0.104,0.059 0.19,0.146 0.257,0.258c0.068,0.112 0.121,0.249 0.159,0.411c0.039,0.161 0.058,0.379 0.058,0.653c0,0.324 -0.031,0.586 -0.092,0.785c-0.062,0.199 -0.155,0.354 -0.277,0.462c-0.123,0.108 -0.278,0.163 -0.466,0.163c-0.247,0 -0.441,-0.096 -0.582,-0.287C48.812,62.383 48.727,62.009 48.727,61.49L48.727,61.49zM49.05,61.49c0,0.454 0.049,0.755 0.147,0.905c0.099,0.15 0.221,0.225 0.365,0.225s0.266,-0.075 0.365,-0.226c0.098,-0.151 0.147,-0.452 0.147,-0.904c0,-0.455 -0.049,-0.757 -0.147,-0.906c-0.099,-0.15 -0.222,-0.224 -0.369,-0.224c-0.144,0 -0.259,0.066 -0.346,0.198C49.104,60.725 49.05,61.037 49.05,61.49L49.05,61.49z" + android:fillColor="#FFFFFF"/> + android:pathData="M50.72,62.123l0.315,-0.045c0.036,0.192 0.097,0.331 0.184,0.416c0.087,0.085 0.193,0.127 0.318,0.127c0.148,0 0.273,-0.056 0.374,-0.166c0.103,-0.11 0.154,-0.247 0.154,-0.411c0,-0.156 -0.047,-0.284 -0.141,-0.385c-0.095,-0.101 -0.215,-0.152 -0.36,-0.152c-0.059,0 -0.134,0.012 -0.223,0.038l0.035,-0.298c0.022,0.003 0.038,0.004 0.051,0.004c0.134,0 0.255,-0.038 0.362,-0.113c0.107,-0.075 0.16,-0.191 0.16,-0.348c0,-0.124 -0.039,-0.228 -0.117,-0.309c-0.078,-0.082 -0.179,-0.123 -0.303,-0.123c-0.122,0 -0.224,0.041 -0.306,0.124c-0.081,0.083 -0.134,0.207 -0.158,0.373l-0.314,-0.06c0.038,-0.228 0.125,-0.404 0.262,-0.529c0.136,-0.125 0.306,-0.188 0.508,-0.188c0.14,0 0.269,0.033 0.387,0.097c0.118,0.065 0.207,0.153 0.27,0.265c0.062,0.111 0.093,0.23 0.093,0.357c0,0.119 -0.029,0.227 -0.089,0.325c-0.059,0.098 -0.148,0.176 -0.264,0.234c0.151,0.038 0.269,0.116 0.353,0.235c0.084,0.119 0.126,0.267 0.126,0.445c0,0.241 -0.082,0.446 -0.245,0.614c-0.163,0.168 -0.37,0.252 -0.619,0.252c-0.225,0 -0.412,-0.073 -0.56,-0.217C50.825,62.541 50.74,62.353 50.72,62.123L50.72,62.123z" + android:fillColor="#FFFFFF"/> + android:pathData="M53.659,62.068l0.307,-0.045c0.008,0.211 0.044,0.356 0.109,0.434c0.066,0.078 0.156,0.117 0.272,0.117c0.085,0 0.158,-0.021 0.22,-0.063c0.062,-0.042 0.105,-0.099 0.128,-0.172c0.023,-0.072 0.035,-0.188 0.035,-0.346V60.09h0.339v1.883c0,0.231 -0.025,0.409 -0.077,0.537c-0.052,0.127 -0.134,0.224 -0.246,0.29c-0.113,0.066 -0.245,0.1 -0.396,0.1c-0.225,0 -0.397,-0.07 -0.517,-0.209C53.711,62.551 53.654,62.344 53.659,62.068L53.659,62.068z" + android:fillColor="#FFFFFF"/> + android:pathData="M56.794,62.606c-0.117,0.107 -0.229,0.182 -0.337,0.226c-0.108,0.043 -0.224,0.066 -0.347,0.066c-0.204,0 -0.36,-0.054 -0.47,-0.161c-0.11,-0.108 -0.165,-0.245 -0.165,-0.412c0,-0.098 0.021,-0.188 0.062,-0.269c0.042,-0.081 0.095,-0.145 0.163,-0.194c0.067,-0.049 0.142,-0.087 0.226,-0.111c0.061,-0.018 0.155,-0.035 0.279,-0.051c0.255,-0.033 0.441,-0.072 0.561,-0.117c0.001,-0.046 0.002,-0.076 0.002,-0.089c0,-0.139 -0.029,-0.236 -0.089,-0.292c-0.081,-0.076 -0.2,-0.115 -0.358,-0.115c-0.148,0 -0.257,0.028 -0.328,0.084c-0.071,0.057 -0.123,0.155 -0.157,0.297l-0.307,-0.045c0.027,-0.142 0.074,-0.257 0.138,-0.344c0.064,-0.087 0.157,-0.155 0.278,-0.202c0.121,-0.046 0.261,-0.07 0.422,-0.07c0.158,0 0.287,0.02 0.386,0.059c0.099,0.041 0.173,0.091 0.219,0.152c0.047,0.061 0.079,0.139 0.098,0.231c0.01,0.058 0.016,0.162 0.016,0.313v0.452c0,0.316 0.007,0.515 0.02,0.599c0.013,0.084 0.04,0.163 0.079,0.241h-0.328C56.824,62.782 56.803,62.7 56.794,62.606L56.794,62.606zM56.767,61.849c-0.114,0.05 -0.286,0.092 -0.514,0.127c-0.129,0.021 -0.221,0.043 -0.274,0.068c-0.054,0.025 -0.095,0.062 -0.124,0.11c-0.029,0.049 -0.044,0.103 -0.044,0.161c0,0.091 0.032,0.166 0.095,0.226c0.064,0.06 0.157,0.091 0.279,0.091c0.121,0 0.229,-0.028 0.324,-0.086s0.163,-0.136 0.207,-0.235c0.034,-0.076 0.051,-0.19 0.051,-0.339L56.767,61.849L56.767,61.849z" + android:fillColor="#FFFFFF"/> + android:pathData="M57.574,62.853v-2.001h0.283v0.284c0.137,-0.22 0.334,-0.329 0.591,-0.329c0.111,0 0.214,0.022 0.308,0.064c0.093,0.043 0.164,0.101 0.21,0.171c0.047,0.071 0.079,0.155 0.098,0.251c0.011,0.063 0.018,0.173 0.018,0.33v1.231h-0.315v-1.218c0,-0.139 -0.012,-0.241 -0.037,-0.31c-0.025,-0.069 -0.068,-0.123 -0.13,-0.164c-0.062,-0.041 -0.136,-0.061 -0.22,-0.061c-0.134,0 -0.25,0.046 -0.347,0.138c-0.097,0.091 -0.146,0.266 -0.146,0.523v1.093H57.574L57.574,62.853z" + android:fillColor="#FFFFFF"/> + android:pathData="M62.126,62.527v0.326h-1.694c-0.003,-0.082 0.009,-0.16 0.037,-0.236c0.042,-0.125 0.111,-0.247 0.207,-0.368c0.095,-0.121 0.232,-0.26 0.412,-0.418c0.278,-0.246 0.467,-0.441 0.565,-0.586c0.097,-0.143 0.146,-0.28 0.146,-0.407c0,-0.135 -0.044,-0.248 -0.134,-0.34c-0.089,-0.092 -0.205,-0.139 -0.348,-0.139c-0.152,0 -0.274,0.049 -0.364,0.147c-0.091,0.098 -0.137,0.234 -0.138,0.407l-0.324,-0.036c0.022,-0.259 0.105,-0.457 0.25,-0.594c0.144,-0.137 0.339,-0.205 0.582,-0.205c0.246,0 0.44,0.074 0.584,0.221c0.143,0.147 0.215,0.329 0.215,0.547c0,0.11 -0.021,0.219 -0.063,0.325c-0.042,0.107 -0.111,0.22 -0.208,0.338c-0.097,0.118 -0.259,0.28 -0.485,0.486c-0.19,0.172 -0.31,0.288 -0.364,0.348c-0.054,0.061 -0.098,0.123 -0.133,0.184L62.126,62.527L62.126,62.527z" + android:fillColor="#FFFFFF"/> + android:pathData="M62.464,61.49c0,-0.326 0.031,-0.589 0.093,-0.788c0.062,-0.2 0.155,-0.353 0.278,-0.461c0.123,-0.108 0.277,-0.162 0.464,-0.162c0.138,0 0.257,0.03 0.361,0.09c0.104,0.059 0.19,0.146 0.257,0.258s0.121,0.249 0.159,0.411c0.038,0.161 0.058,0.379 0.058,0.653c0,0.324 -0.031,0.586 -0.092,0.785c-0.062,0.199 -0.155,0.354 -0.277,0.462C63.642,62.846 63.487,62.9 63.3,62.9c-0.247,0 -0.441,-0.096 -0.583,-0.287C62.548,62.383 62.464,62.009 62.464,61.49L62.464,61.49zM62.787,61.49c0,0.454 0.049,0.755 0.147,0.905c0.099,0.15 0.22,0.225 0.365,0.225c0.144,0 0.266,-0.075 0.364,-0.226c0.099,-0.151 0.148,-0.452 0.148,-0.904c0,-0.455 -0.049,-0.757 -0.148,-0.906c-0.098,-0.15 -0.221,-0.224 -0.368,-0.224c-0.144,0 -0.26,0.066 -0.346,0.198C62.841,60.725 62.787,61.037 62.787,61.49L62.787,61.49z" + android:fillColor="#FFFFFF"/> + android:pathData="M66.109,62.527v0.326h-1.695c-0.002,-0.082 0.01,-0.16 0.037,-0.236c0.043,-0.125 0.112,-0.247 0.207,-0.368c0.095,-0.121 0.232,-0.26 0.412,-0.418c0.278,-0.246 0.467,-0.441 0.564,-0.586c0.098,-0.143 0.147,-0.28 0.147,-0.407c0,-0.135 -0.044,-0.248 -0.134,-0.34c-0.089,-0.092 -0.206,-0.139 -0.349,-0.139c-0.151,0 -0.273,0.049 -0.363,0.147c-0.091,0.098 -0.137,0.234 -0.139,0.407l-0.324,-0.036c0.023,-0.259 0.106,-0.457 0.251,-0.594c0.144,-0.137 0.339,-0.205 0.582,-0.205c0.246,0 0.44,0.074 0.584,0.221c0.143,0.147 0.215,0.329 0.215,0.547c0,0.11 -0.021,0.219 -0.063,0.325c-0.041,0.107 -0.111,0.22 -0.208,0.338c-0.097,0.118 -0.259,0.28 -0.486,0.486c-0.189,0.172 -0.309,0.288 -0.363,0.348c-0.054,0.061 -0.098,0.123 -0.133,0.184L66.109,62.527L66.109,62.527z" + android:fillColor="#FFFFFF"/> + android:pathData="M66.446,61.49c0,-0.326 0.032,-0.589 0.094,-0.788c0.062,-0.2 0.155,-0.353 0.277,-0.461c0.124,-0.108 0.278,-0.162 0.465,-0.162c0.137,0 0.257,0.03 0.361,0.09c0.104,0.059 0.19,0.146 0.257,0.258c0.067,0.112 0.121,0.249 0.158,0.411c0.039,0.161 0.058,0.379 0.058,0.653c0,0.324 -0.031,0.586 -0.093,0.785c-0.061,0.199 -0.154,0.354 -0.276,0.462c-0.124,0.108 -0.279,0.163 -0.466,0.163c-0.247,0 -0.441,-0.096 -0.583,-0.287C66.531,62.383 66.446,62.009 66.446,61.49L66.446,61.49zM66.769,61.49c0,0.454 0.05,0.755 0.148,0.905s0.22,0.225 0.365,0.225c0.144,0 0.266,-0.075 0.364,-0.226c0.098,-0.151 0.148,-0.452 0.148,-0.904c0,-0.455 -0.05,-0.757 -0.148,-0.906c-0.098,-0.15 -0.221,-0.224 -0.368,-0.224c-0.144,0 -0.26,0.066 -0.346,0.198C66.824,60.725 66.769,61.037 66.769,61.49L66.769,61.49z" + android:fillColor="#FFFFFF"/> + android:pathData="M19.776,62.83l-0.343,0.001v-2.066c-0.083,0.075 -0.191,0.149 -0.325,0.224c-0.134,0.075 -0.255,0.131 -0.362,0.169v-0.313c0.192,-0.087 0.36,-0.191 0.505,-0.312c0.143,-0.122 0.245,-0.24 0.305,-0.354l0.222,-0.001V62.83z" + android:fillColor="#FFFFFF"/> + android:pathData="M20.655,61.524c0,-0.312 0.034,-0.564 0.102,-0.755c0.068,-0.191 0.169,-0.338 0.304,-0.441c0.134,-0.104 0.303,-0.157 0.506,-0.157c0.15,-0.001 0.282,0.027 0.395,0.084s0.207,0.139 0.28,0.245c0.074,0.108 0.132,0.238 0.174,0.392c0.042,0.154 0.063,0.362 0.063,0.623c0,0.31 -0.034,0.56 -0.101,0.751c-0.068,0.191 -0.169,0.338 -0.303,0.442c-0.134,0.105 -0.304,0.157 -0.508,0.158c-0.27,0.001 -0.482,-0.09 -0.636,-0.272C20.748,62.377 20.656,62.019 20.655,61.524L20.655,61.524zM21.008,61.522c0,0.434 0.054,0.722 0.161,0.865c0.108,0.143 0.241,0.214 0.398,0.214c0.158,-0.001 0.29,-0.074 0.398,-0.218c0.108,-0.144 0.161,-0.433 0.161,-0.865c0,-0.435 -0.054,-0.723 -0.161,-0.866c-0.108,-0.142 -0.241,-0.213 -0.402,-0.213c-0.158,0.001 -0.284,0.064 -0.378,0.191C21.068,60.791 21.008,61.089 21.008,61.522z" + android:fillColor="#FFFFFF"/> + android:pathData="M23.02,61.273v-0.369l0.39,-0.002v0.37L23.02,61.273zM23.02,62.817v-0.37l0.39,-0.001v0.369L23.02,62.817z" + android:fillColor="#FFFFFF"/> + android:pathData="M25.719,62.495v0.312l-1.849,0.007c-0.003,-0.078 0.01,-0.153 0.04,-0.225c0.047,-0.119 0.123,-0.236 0.226,-0.352c0.104,-0.116 0.254,-0.249 0.45,-0.402c0.304,-0.236 0.509,-0.423 0.616,-0.561c0.107,-0.138 0.16,-0.268 0.16,-0.39c0,-0.128 -0.049,-0.237 -0.146,-0.324c-0.097,-0.088 -0.224,-0.132 -0.38,-0.131c-0.166,0.001 -0.298,0.048 -0.397,0.142c-0.099,0.093 -0.15,0.224 -0.151,0.39l-0.353,-0.033c0.024,-0.249 0.115,-0.439 0.273,-0.57c0.158,-0.131 0.37,-0.196 0.636,-0.198c0.268,-0.001 0.481,0.069 0.637,0.208c0.157,0.141 0.235,0.314 0.235,0.522c0,0.106 -0.023,0.209 -0.068,0.312c-0.046,0.102 -0.123,0.209 -0.228,0.323c-0.107,0.114 -0.283,0.27 -0.53,0.467c-0.206,0.164 -0.338,0.275 -0.397,0.334c-0.058,0.058 -0.107,0.117 -0.144,0.176C24.348,62.5 25.719,62.495 25.719,62.495z" + android:fillColor="#FFFFFF"/> + android:pathData="M27.382,62.8l-0.344,0.001v-2.066c-0.082,0.075 -0.191,0.15 -0.325,0.224c-0.134,0.075 -0.255,0.132 -0.361,0.169v-0.313c0.192,-0.086 0.36,-0.19 0.504,-0.311c0.144,-0.122 0.246,-0.241 0.306,-0.355l0.222,-0.001C27.382,60.149 27.382,62.8 27.382,62.8z" + android:fillColor="#FFFFFF"/> + android:pathData="M45.114,61.045h0.299v0.805h-0.299z" + android:fillColor="#999C97"/> + android:pathData="M45.091,60.553v1.918h-3.389v-1.918H45.091zM44.614,60.934h-2.376v1.104h2.376V60.934z" + android:fillColor="#999C97"/> + android:pathData="M34.788,62.554h0.934v0.415h-0.934z" + android:fillColor="#FFFFFF"/> + android:pathData="M36.624,61.934l-1.19,-0.606l-0.173,0.324l1.19,0.607L36.624,61.934L36.624,61.934z" + android:fillColor="#FFFFFF"/> + android:pathData="M35.255,61.651l-1.19,0.607l-0.173,-0.324l1.189,-0.606L35.255,61.651L35.255,61.651z" + android:fillColor="#FFFFFF"/> + android:pathData="M35.051,60.423h0.421v2.547h-0.421z" + android:fillColor="#FFFFFF"/> + android:pathData="M35.472,60.246c0,-0.058 -0.047,-0.106 -0.105,-0.106h-0.21c-0.058,0 -0.106,0.047 -0.106,0.106v2.036c0,0.058 0.047,0.106 0.106,0.106h0.21c0.058,0 0.105,-0.047 0.105,-0.106V60.246z" + android:fillColor="#FFFFFF"/> + android:pathData="M37.873,65.857h0.441v1.902c0,0.331 -0.038,0.593 -0.114,0.788c-0.075,0.194 -0.212,0.353 -0.41,0.474c-0.197,0.123 -0.456,0.183 -0.778,0.183c-0.312,0 -0.567,-0.053 -0.766,-0.159c-0.198,-0.106 -0.34,-0.26 -0.424,-0.461c-0.085,-0.202 -0.127,-0.476 -0.127,-0.825v-1.902h0.44v1.9c0,0.287 0.027,0.497 0.081,0.633c0.054,0.135 0.146,0.24 0.277,0.313c0.13,0.074 0.29,0.11 0.48,0.11c0.324,0 0.556,-0.073 0.693,-0.218c0.138,-0.145 0.207,-0.424 0.207,-0.838L37.873,65.857L37.873,65.857z" + android:fillColor="#FFFFFF"/> + android:pathData="M38.689,69.205l0.966,-3.405h0.327l-0.963,3.405H38.689z" + android:fillColor="#FFFFFF"/> + android:pathData="M40.288,69.15v-3.293h0.409v1.181c0.191,-0.218 0.432,-0.327 0.722,-0.327c0.179,0 0.335,0.035 0.466,0.105c0.132,0.069 0.226,0.165 0.283,0.289c0.057,0.123 0.086,0.301 0.086,0.534v1.512h-0.409v-1.512c0,-0.202 -0.044,-0.349 -0.133,-0.441c-0.089,-0.091 -0.214,-0.138 -0.376,-0.138c-0.121,0 -0.235,0.031 -0.341,0.093c-0.108,0.062 -0.183,0.146 -0.229,0.253c-0.045,0.106 -0.068,0.253 -0.068,0.44v1.305H40.288L40.288,69.15z" + android:fillColor="#FFFFFF"/> + android:pathData="M43.916,69.15v-3.07h1.031c0.21,0 0.378,0.031 0.506,0.093c0.126,0.061 0.226,0.158 0.298,0.287c0.072,0.129 0.108,0.264 0.108,0.405c0,0.132 -0.031,0.256 -0.095,0.371c-0.064,0.116 -0.16,0.209 -0.289,0.281c0.166,0.055 0.294,0.147 0.383,0.278c0.09,0.131 0.134,0.287 0.134,0.465c0,0.144 -0.026,0.277 -0.081,0.401c-0.055,0.124 -0.122,0.219 -0.202,0.286c-0.08,0.067 -0.18,0.118 -0.301,0.152c-0.121,0.035 -0.268,0.052 -0.443,0.052H43.916L43.916,69.15zM44.279,67.369h0.595c0.161,0 0.276,-0.011 0.346,-0.035c0.092,-0.031 0.162,-0.082 0.209,-0.153c0.047,-0.072 0.071,-0.161 0.071,-0.269c0,-0.102 -0.023,-0.191 -0.066,-0.269c-0.043,-0.077 -0.107,-0.13 -0.188,-0.159c-0.081,-0.028 -0.221,-0.042 -0.418,-0.042h-0.55V67.369L44.279,67.369zM44.279,68.787h0.685c0.118,0 0.2,-0.006 0.247,-0.015c0.084,-0.017 0.154,-0.044 0.21,-0.084c0.057,-0.039 0.103,-0.095 0.139,-0.171c0.037,-0.075 0.055,-0.16 0.055,-0.258c0,-0.114 -0.026,-0.214 -0.079,-0.298c-0.052,-0.085 -0.124,-0.144 -0.218,-0.178s-0.227,-0.051 -0.403,-0.051h-0.636L44.279,68.787L44.279,68.787z" + android:fillColor="#FFFFFF"/> + android:pathData="M46.497,69.15v-3.07h1.22c0.244,0 0.431,0.027 0.558,0.082c0.127,0.056 0.229,0.153 0.306,0.292c0.076,0.14 0.114,0.294 0.114,0.463c0,0.218 -0.063,0.401 -0.189,0.551c-0.126,0.149 -0.322,0.244 -0.586,0.285c0.096,0.052 0.17,0.103 0.22,0.153c0.107,0.108 0.207,0.245 0.302,0.408l0.478,0.836h-0.457l-0.364,-0.639c-0.107,-0.185 -0.193,-0.325 -0.262,-0.423c-0.069,-0.098 -0.13,-0.166 -0.185,-0.206c-0.055,-0.039 -0.109,-0.066 -0.166,-0.081c-0.041,-0.01 -0.108,-0.015 -0.203,-0.015h-0.422v1.364H46.497zM46.861,67.434h0.782c0.166,0 0.296,-0.019 0.39,-0.058c0.093,-0.038 0.165,-0.1 0.213,-0.184c0.049,-0.085 0.074,-0.176 0.074,-0.275c0,-0.145 -0.047,-0.265 -0.141,-0.358c-0.094,-0.093 -0.243,-0.141 -0.448,-0.141h-0.87V67.434L46.861,67.434z" + android:fillColor="#FFFFFF"/> + android:pathData="M49.091,67.849h1.037v0.379h-1.037z" + android:fillColor="#FFFFFF"/> + android:pathData="M50.544,69.15v-3.07h1.037c0.183,0 0.322,0.009 0.418,0.029c0.136,0.025 0.249,0.073 0.34,0.143c0.091,0.071 0.165,0.169 0.221,0.296c0.056,0.127 0.083,0.267 0.083,0.419c0,0.261 -0.074,0.482 -0.223,0.663c-0.149,0.181 -0.418,0.271 -0.806,0.271h-0.705v1.249L50.544,69.15L50.544,69.15zM50.907,67.539h0.711c0.235,0 0.402,-0.048 0.501,-0.146c0.098,-0.098 0.148,-0.236 0.148,-0.413c0,-0.128 -0.029,-0.238 -0.088,-0.329c-0.058,-0.091 -0.134,-0.152 -0.229,-0.181c-0.061,-0.019 -0.174,-0.027 -0.34,-0.027h-0.704L50.907,67.539L50.907,67.539z" + android:fillColor="#FFFFFF"/> + android:pathData="M53.059,69.15v-2.224h0.304v0.337c0.077,-0.158 0.149,-0.261 0.215,-0.312c0.065,-0.05 0.138,-0.075 0.216,-0.075c0.114,0 0.229,0.041 0.347,0.122l-0.116,0.35c-0.083,-0.055 -0.165,-0.082 -0.248,-0.082c-0.074,0 -0.14,0.025 -0.198,0.075c-0.059,0.05 -0.101,0.119 -0.126,0.207c-0.037,0.134 -0.056,0.281 -0.056,0.44v1.165L53.059,69.15L53.059,69.15z" + android:fillColor="#FFFFFF"/> + android:pathData="M54.215,68.038c0,-0.412 0.103,-0.717 0.308,-0.916c0.171,-0.164 0.379,-0.247 0.626,-0.247c0.274,0 0.497,0.101 0.671,0.301c0.174,0.2 0.261,0.477 0.261,0.83c0,0.287 -0.039,0.512 -0.116,0.676c-0.076,0.163 -0.189,0.291 -0.335,0.382c-0.147,0.091 -0.307,0.136 -0.481,0.136c-0.279,0 -0.505,-0.1 -0.676,-0.299C54.302,68.701 54.215,68.413 54.215,68.038L54.215,68.038zM54.562,68.038c0,0.285 0.056,0.498 0.167,0.639c0.111,0.141 0.252,0.212 0.421,0.212c0.167,0 0.307,-0.071 0.418,-0.213c0.111,-0.142 0.167,-0.359 0.167,-0.652c0,-0.274 -0.056,-0.483 -0.168,-0.624c-0.112,-0.142 -0.251,-0.213 -0.417,-0.213c-0.169,0 -0.309,0.071 -0.421,0.212C54.618,67.54 54.562,67.753 54.562,68.038L54.562,68.038z" + android:fillColor="#FFFFFF"/> + android:pathData="M56.567,69.15v-1.933h-0.301v-0.29h0.301V66.71c0,-0.221 0.042,-0.39 0.127,-0.506c0.085,-0.118 0.219,-0.176 0.403,-0.176c0.124,0 0.239,0.016 0.343,0.048l-0.053,0.319c-0.066,-0.013 -0.126,-0.019 -0.181,-0.019c-0.117,0 -0.196,0.025 -0.239,0.077c-0.042,0.052 -0.064,0.161 -0.064,0.329v0.144h0.387v0.29h-0.387v1.933L56.567,69.15L56.567,69.15zM57.545,66.513V66.08h0.338v0.433H57.545zM57.545,69.15v-2.224h0.338v2.224H57.545z" + android:fillColor="#FFFFFF"/> + android:pathData="M58.389,66.08h0.338v3.07h-0.338z" + android:fillColor="#FFFFFF"/> + android:pathData="M61.494,69.15h-0.337v-2.402c-0.082,0.087 -0.189,0.174 -0.32,0.259c-0.132,0.087 -0.251,0.152 -0.356,0.195v-0.365c0.189,-0.099 0.354,-0.219 0.495,-0.359c0.141,-0.141 0.241,-0.278 0.3,-0.411h0.217L61.494,69.15L61.494,69.15z" + android:fillColor="#FFFFFF"/> + android:pathData="M22.114,66.613h0.658v2.261h-0.658z" + android:fillColor="#FFFFFF"/> + android:pathData="M21.347,66.573h1.426v0.658h-1.426z" + android:fillColor="#FFFFFF"/> + android:pathData="M21.358,65.27h0.658v1.633h-0.658z" + android:fillColor="#FFFFFF"/> + android:pathData="M19.295,66.995h0.658v1.85h-0.658z" + android:fillColor="#FFFFFF"/> + android:pathData="M19.919,65.563h0.642v2.019h-0.642z" + android:fillColor="#FFFFFF"/> + android:pathData="M19.919,65.27h1.755v0.585h-1.755z" + android:fillColor="#FFFFFF"/> + android:pathData="M25.83,69.074h-0.508v-3.308c-0.122,0.12 -0.282,0.239 -0.48,0.358c-0.199,0.119 -0.377,0.208 -0.535,0.268v-0.502c0.284,-0.137 0.532,-0.302 0.744,-0.496c0.213,-0.194 0.363,-0.383 0.452,-0.565h0.327V69.074z" + android:fillColor="#FFFFFF"/> + android:pathData="M27.414,68.484h0.578v0.591h-0.578z" + android:fillColor="#FFFFFF"/> + android:pathData="M28.737,67.958l0.507,-0.069c0.058,0.294 0.158,0.506 0.298,0.636c0.14,0.129 0.31,0.194 0.511,0.194c0.24,0 0.44,-0.084 0.606,-0.254c0.164,-0.169 0.246,-0.378 0.246,-0.628c0,-0.239 -0.075,-0.436 -0.228,-0.59c-0.152,-0.155 -0.346,-0.232 -0.581,-0.232c-0.095,0 -0.215,0.02 -0.358,0.058l0.057,-0.456c0.034,0.004 0.061,0.006 0.082,0.006c0.216,0 0.411,-0.058 0.584,-0.173s0.259,-0.293 0.259,-0.534c0,-0.19 -0.063,-0.348 -0.189,-0.473c-0.126,-0.125 -0.289,-0.188 -0.489,-0.188c-0.197,0 -0.361,0.064 -0.493,0.191c-0.132,0.127 -0.216,0.317 -0.254,0.571l-0.507,-0.091c0.061,-0.348 0.203,-0.618 0.423,-0.809c0.22,-0.191 0.494,-0.287 0.821,-0.287c0.226,0 0.434,0.049 0.623,0.148c0.191,0.099 0.336,0.234 0.436,0.406c0.101,0.171 0.151,0.353 0.151,0.545c0,0.182 -0.048,0.349 -0.143,0.499c-0.096,0.15 -0.238,0.269 -0.426,0.357c0.244,0.058 0.435,0.177 0.57,0.358c0.136,0.182 0.204,0.409 0.204,0.682c0,0.37 -0.132,0.682 -0.395,0.939c-0.263,0.257 -0.596,0.385 -0.999,0.385c-0.362,0 -0.664,-0.11 -0.904,-0.332C28.908,68.597 28.771,68.31 28.737,67.958z" + android:fillColor="#FFFFFF"/> + android:pathData="M31.947,67.967l0.533,-0.046c0.04,0.266 0.131,0.465 0.275,0.599c0.143,0.133 0.317,0.2 0.52,0.2c0.245,0 0.452,-0.094 0.621,-0.282c0.17,-0.189 0.254,-0.439 0.254,-0.75c0,-0.296 -0.081,-0.53 -0.243,-0.701c-0.163,-0.172 -0.376,-0.257 -0.639,-0.257c-0.163,0 -0.311,0.038 -0.442,0.113c-0.132,0.076 -0.235,0.174 -0.31,0.296l-0.476,-0.064l0.4,-2.171h2.056v0.496h-1.65l-0.223,1.137c0.248,-0.177 0.508,-0.266 0.781,-0.266c0.361,0 0.666,0.128 0.914,0.384c0.248,0.256 0.373,0.585 0.373,0.987c0,0.382 -0.109,0.713 -0.327,0.991c-0.265,0.342 -0.627,0.514 -1.087,0.514c-0.375,0 -0.683,-0.108 -0.921,-0.324C32.117,68.608 31.981,68.322 31.947,67.967L31.947,67.967z" + android:fillColor="#FFFFFF"/> + android:pathData="M19.26,72.266h2.782v0.579h-2.782z" + android:fillColor="#F27E30"/> + android:pathData="M22.007,75.201h0.625v0.576h-0.625z" + android:fillColor="#F27E30"/> + android:pathData="M21.447,72.845h0.595v2.934h-0.595z" + android:fillColor="#F27E30"/> + android:pathData="M19.26,72.845h0.576v2.934h-0.576z" + android:fillColor="#F27E30"/> + android:pathData="M26.696,75.506v0.488H24.06c-0.004,-0.123 0.015,-0.24 0.057,-0.353c0.067,-0.186 0.174,-0.369 0.323,-0.549c0.148,-0.181 0.361,-0.39 0.641,-0.626c0.433,-0.369 0.726,-0.66 0.878,-0.875c0.153,-0.215 0.229,-0.419 0.229,-0.61c0,-0.202 -0.07,-0.371 -0.208,-0.509c-0.139,-0.138 -0.32,-0.207 -0.542,-0.207c-0.237,0 -0.425,0.074 -0.567,0.221c-0.141,0.146 -0.213,0.349 -0.215,0.608l-0.503,-0.054c0.034,-0.389 0.164,-0.685 0.389,-0.889c0.225,-0.204 0.527,-0.306 0.906,-0.306c0.383,0 0.686,0.11 0.909,0.33c0.223,0.22 0.335,0.492 0.335,0.818c0,0.165 -0.033,0.327 -0.098,0.488c-0.066,0.159 -0.174,0.327 -0.325,0.505c-0.152,0.176 -0.404,0.419 -0.755,0.727c-0.293,0.256 -0.482,0.429 -0.566,0.52c-0.083,0.091 -0.152,0.183 -0.207,0.275L26.696,75.506L26.696,75.506z" + android:fillColor="#FFFFFF"/> + android:pathData="M27.497,75.415h0.557v0.578h-0.557z" + android:fillColor="#FFFFFF"/> + android:pathData="M28.773,74.902l0.49,-0.068c0.057,0.288 0.152,0.495 0.287,0.622c0.136,0.126 0.3,0.19 0.494,0.19c0.23,0 0.425,-0.082 0.584,-0.248c0.158,-0.165 0.238,-0.37 0.238,-0.614c0,-0.233 -0.074,-0.425 -0.22,-0.577c-0.147,-0.151 -0.334,-0.226 -0.561,-0.226c-0.092,0 -0.207,0.019 -0.345,0.057l0.055,-0.446c0.032,0.004 0.058,0.006 0.078,0.006c0.208,0 0.397,-0.057 0.564,-0.169c0.166,-0.113 0.25,-0.287 0.25,-0.522c0,-0.186 -0.06,-0.34 -0.182,-0.462c-0.122,-0.123 -0.279,-0.184 -0.471,-0.184c-0.191,0 -0.35,0.062 -0.476,0.187c-0.127,0.124 -0.209,0.31 -0.245,0.558l-0.489,-0.091c0.059,-0.34 0.195,-0.604 0.407,-0.791c0.212,-0.187 0.476,-0.28 0.792,-0.28c0.218,0 0.418,0.048 0.602,0.145c0.183,0.097 0.323,0.229 0.42,0.396c0.097,0.167 0.146,0.345 0.146,0.533c0,0.178 -0.046,0.341 -0.139,0.488c-0.093,0.146 -0.23,0.263 -0.411,0.35c0.236,0.056 0.419,0.173 0.55,0.351c0.13,0.177 0.195,0.4 0.195,0.667c0,0.36 -0.126,0.667 -0.38,0.918c-0.255,0.251 -0.575,0.376 -0.964,0.376c-0.35,0 -0.64,-0.108 -0.872,-0.324C28.937,75.526 28.805,75.246 28.773,74.902L28.773,74.902z" + android:fillColor="#FFFFFF"/> + android:pathData="M31.87,74.91l0.514,-0.045c0.039,0.259 0.126,0.455 0.266,0.586c0.139,0.13 0.306,0.195 0.502,0.195c0.236,0 0.436,-0.091 0.599,-0.276c0.163,-0.184 0.244,-0.428 0.244,-0.733c0,-0.29 -0.078,-0.518 -0.235,-0.685c-0.158,-0.167 -0.362,-0.251 -0.617,-0.251c-0.158,0 -0.3,0.037 -0.427,0.111c-0.126,0.075 -0.226,0.171 -0.299,0.289l-0.46,-0.061l0.387,-2.123h1.983v0.485h-1.592l-0.214,1.111c0.239,-0.174 0.49,-0.259 0.754,-0.259c0.348,0 0.642,0.125 0.882,0.374c0.239,0.25 0.358,0.572 0.358,0.964c0,0.374 -0.105,0.698 -0.315,0.971c-0.257,0.334 -0.606,0.502 -1.048,0.502c-0.363,0 -0.659,-0.106 -0.888,-0.316C32.034,75.538 31.903,75.258 31.87,74.91L31.87,74.91z" + android:fillColor="#FFFFFF"/> + android:pathData="M37.785,71.86h0.528v2.388c0,0.415 -0.045,0.745 -0.136,0.989c-0.091,0.244 -0.255,0.443 -0.491,0.596c-0.237,0.154 -0.547,0.23 -0.932,0.23c-0.373,0 -0.679,-0.067 -0.917,-0.2c-0.238,-0.134 -0.407,-0.327 -0.509,-0.58s-0.153,-0.598 -0.153,-1.036V71.86h0.528v2.385c0,0.358 0.032,0.623 0.097,0.793c0.064,0.171 0.174,0.302 0.332,0.393c0.157,0.092 0.348,0.139 0.575,0.139c0.388,0 0.665,-0.091 0.83,-0.274c0.165,-0.183 0.247,-0.533 0.247,-1.052L37.785,71.86L37.785,71.86z" + android:fillColor="#FFFFFF"/> + + + + + + diff --git a/icons/insight_128.svg b/icons/insight_128.svg new file mode 100644 index 0000000000..1613d7aa1c --- /dev/null +++ b/icons/insight_128.svg @@ -0,0 +1,581 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 30689c38aa8b06423ea9f4e02f4edfaa136d8045 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Wed, 13 Jan 2021 00:23:35 +0100 Subject: [PATCH 03/61] vibrate less on bolus --- .../androidaps/data/ListenerService.java | 99 +++++++++---------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java b/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java index db9204f1ec..2f048af9a7 100644 --- a/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java +++ b/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java @@ -115,7 +115,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp } - @Override protected Void doInBackground(Void... params) { // Log.d(TAG, logPrefix + "DataRequester: doInBack: " + params); @@ -158,8 +157,8 @@ public class ListenerService extends WearableListenerService implements GoogleAp } Log.d(TAG, "doInBackground connected. CapabilityApi.GetCapabilityResult mPhoneNodeID=" - + (phoneNode != null ? phoneNode.getId() : "") + " count=" + count + " localnode=" - + localnode);// KS + + (phoneNode != null ? phoneNode.getId() : "") + " count=" + count + " localnode=" + + localnode);// KS if (count > 0) { @@ -168,11 +167,11 @@ public class ListenerService extends WearableListenerService implements GoogleAp // Log.d(TAG, "doInBackground path: " + path); switch (path) { - // simple send as is payloads + // simple send as is payloads case WEARABLE_RESEND_PATH: Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), - WEARABLE_RESEND_PATH, null); + WEARABLE_RESEND_PATH, null); break; case WEARABLE_DATA_PATH: case WEARABLE_CANCELBOLUS_PATH: @@ -207,7 +206,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp } } else { Log.d(TAG, logPrefix + "Not connected for sending: api " - + ((googleApiClient == null) ? "is NULL!" : "not null")); + + ((googleApiClient == null) ? "is NULL!" : "not null")); if (googleApiClient != null) { googleApiClient.connect(); } else { @@ -227,12 +226,12 @@ public class ListenerService extends WearableListenerService implements GoogleAp public CapabilityInfo getCapabilities() { CapabilityApi.GetCapabilityResult capabilityResult = Wearable.CapabilityApi.getCapability(googleApiClient, - CAPABILITY_PHONE_APP, CapabilityApi.FILTER_REACHABLE).await(GET_CAPABILITIES_TIMEOUT_MS, - TimeUnit.MILLISECONDS); + CAPABILITY_PHONE_APP, CapabilityApi.FILTER_REACHABLE).await(GET_CAPABILITIES_TIMEOUT_MS, + TimeUnit.MILLISECONDS); if (!capabilityResult.getStatus().isSuccess()) { Log.e(TAG, logPrefix + "doInBackground Failed to get capabilities, status: " - + capabilityResult.getStatus().getStatusMessage()); + + capabilityResult.getStatus().getStatusMessage()); return null; } @@ -364,7 +363,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp } Log.d(TAG, logPrefix + "sendData: execute lastRequest:" + WearUtil.dateTimeText(lastRequest)); - mDataRequester = (DataRequester)new DataRequester(this, path, payload).execute(); + mDataRequester = (DataRequester) new DataRequester(this, path, payload).execute(); // executeTask(mDataRequester); // if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { @@ -402,7 +401,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp } - private void forceGoogleApiConnect() { if (googleApiClient == null || (!googleApiClient.isConnected() && !googleApiClient.isConnecting())) { try { @@ -424,7 +422,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp if (intent != null && ACTION_RESEND.equals(intent.getAction())) { googleApiConnect(); requestData(); - } else if(intent != null && ACTION_CANCELBOLUS.equals(intent.getAction())){ + } else if (intent != null && ACTION_CANCELBOLUS.equals(intent.getAction())) { googleApiConnect(); //dismiss notification @@ -436,7 +434,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp cancelBolus(); - } else if(intent != null && ACTION_CONFIRMATION.equals(intent.getAction())){ + } else if (intent != null && ACTION_CONFIRMATION.equals(intent.getAction())) { googleApiConnect(); //dismiss notification @@ -447,7 +445,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp String actionstring = intent.getStringExtra("actionstring"); sendConfirmActionstring(actionstring); - } else if(intent != null && ACTION_CONFIRMCHANGE.equals(intent.getAction())){ + } else if (intent != null && ACTION_CONFIRMCHANGE.equals(intent.getAction())) { googleApiConnect(); //dismiss notification @@ -458,7 +456,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp String actionstring = intent.getStringExtra("actionstring"); sendConfirmActionstring(actionstring); - } else if(intent != null && ACTION_INITIATE_ACTION.equals(intent.getAction())){ + } else if (intent != null && ACTION_INITIATE_ACTION.equals(intent.getAction())) { googleApiConnect(); String actionstring = intent.getStringExtra("actionstring"); @@ -497,7 +495,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp String message = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("message"); String actionstring = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("actionstring"); - if("opencpp".equals(title) && actionstring.startsWith("opencpp")){ + if ("opencpp".equals(title) && actionstring.startsWith("opencpp")) { String[] act = actionstring.split("\\s+"); Intent intent = new Intent(this, CPPActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -518,16 +516,16 @@ public class ListenerService extends WearableListenerService implements GoogleAp messageIntent.putExtra("status", dataMap.toBundle()); Persistence.storeDataMap(RawDisplayData.STATUS_PERSISTENCE_KEY, dataMap); LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent); - } else if (path.equals(BASAL_DATA_PATH)){ + } else if (path.equals(BASAL_DATA_PATH)) { dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap(); Intent messageIntent = new Intent(); messageIntent.setAction(Intent.ACTION_SEND); messageIntent.putExtra("basals", dataMap.toBundle()); Persistence.storeDataMap(RawDisplayData.BASALS_PERSISTENCE_KEY, dataMap); LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent); - } else if (path.equals(NEW_PREFERENCES_PATH)){ + } else if (path.equals(NEW_PREFERENCES_PATH)) { dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap(); - if(dataMap.containsKey("wearcontrol")) { + if (dataMap.containsKey("wearcontrol")) { boolean wearcontrol = dataMap.getBoolean("wearcontrol", false); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = sharedPreferences.edit(); @@ -555,20 +553,20 @@ public class ListenerService extends WearableListenerService implements GoogleAp } private void notifyChangeRequest(String title, String message, String actionstring) { - // Create the NotificationChannel, but only on API 26+ because - // the NotificationChannel class is new and not in the support library - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - CharSequence name = "AAPS Open Loop"; - String description = "Open Loop request notiffication";//getString(R.string.channel_description); - NotificationChannel channel = new NotificationChannel(AAPS_NOTIFY_CHANNEL_ID_OPENLOOP, name, NotificationManager.IMPORTANCE_HIGH); - channel.setDescription(description); - channel.enableVibration(true); + // Create the NotificationChannel, but only on API 26+ because + // the NotificationChannel class is new and not in the support library + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + CharSequence name = "AAPS Open Loop"; + String description = "Open Loop request notiffication";//getString(R.string.channel_description); + NotificationChannel channel = new NotificationChannel(AAPS_NOTIFY_CHANNEL_ID_OPENLOOP, name, NotificationManager.IMPORTANCE_HIGH); + channel.setDescription(description); + channel.enableVibration(true); - // Register the channel with the system; you can't change the importance - // or other notification behaviors after this - NotificationManager notificationManager = getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(channel); - } + // Register the channel with the system; you can't change the importance + // or other notification behaviors after this + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + } NotificationCompat.Builder builder = new NotificationCompat.Builder(this, AAPS_NOTIFY_CHANNEL_ID_OPENLOOP); @@ -607,12 +605,22 @@ public class ListenerService extends WearableListenerService implements GoogleAp private void showBolusProgress(int progresspercent, String progresstatus) { + long[] vibratePattern; + boolean vibrate = PreferenceManager + .getDefaultSharedPreferences(this).getBoolean("vibrateOnBolus", true); + if (vibrate) { + vibratePattern = new long[]{0, 50, 1000}; + } else { + vibratePattern = new long[]{0, 1, 1000}; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "AAPS Bolus Progress"; String description = "Bolus progress and cancel"; NotificationChannel channel = new NotificationChannel(AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS, name, NotificationManager.IMPORTANCE_HIGH); channel.setDescription(description); channel.enableVibration(true); + channel.setVibrationPattern(vibratePattern); // Register the channel with the system; you can't change the importance // or other notification behaviors after this @@ -624,16 +632,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp cancelIntent.setAction(ACTION_CANCELBOLUS); PendingIntent cancelPendingIntent = PendingIntent.getService(this, 0, cancelIntent, 0); - long[] vibratePattern; - boolean vibreate = PreferenceManager - .getDefaultSharedPreferences(this).getBoolean("vibrateOnBolus", true); - if(vibreate){ - vibratePattern = new long[]{0, 50, 1000}; - } else { - vibratePattern = new long[]{0, 1, 1000}; - } - - // TODO: proper channel. Does cancel work? NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS) .setSmallIcon(R.drawable.ic_icon) @@ -652,7 +650,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp notificationManager.cancel(CONFIRM_NOTIF_ID); // multiple watch setup - if (progresspercent == 100){ + if (progresspercent == 100) { scheduleDismissBolusprogress(5); } } @@ -675,18 +673,17 @@ public class ListenerService extends WearableListenerService implements GoogleAp } - - private class DismissThread extends Thread{ + private class DismissThread extends Thread { private final int notificationID; private final int seconds; private boolean valid = true; - DismissThread(int notificationID, int seconds){ + DismissThread(int notificationID, int seconds) { this.notificationID = notificationID; this.seconds = seconds; } - public synchronized void invalidate(){ + public synchronized void invalidate() { valid = false; } @@ -694,7 +691,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp public void run() { SystemClock.sleep(seconds * 1000); synchronized (this) { - if(valid) { + if (valid) { NotificationManagerCompat notificationManager = NotificationManagerCompat.from(ListenerService.this); notificationManager.cancel(notificationID); @@ -738,7 +735,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp public void onCapabilityChanged(CapabilityInfo capabilityInfo) { updatePhoneSyncBgsCapability(capabilityInfo); Log.d(TAG, logPrefix + "onConnected onCapabilityChanged mPhoneNodeID:" + mPhoneNodeId - + ", Capability: " + capabilityInfo); + + ", Capability: " + capabilityInfo); } }; @@ -768,7 +765,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp public void onResult(NodeApi.GetLocalNodeResult getLocalNodeResult) { if (!getLocalNodeResult.getStatus().isSuccess()) { Log.e(TAG, "ERROR: failed to getLocalNode Status=" - + getLocalNodeResult.getStatus().getStatusMessage()); + + getLocalNodeResult.getStatus().getStatusMessage()); } else { Log.d(TAG, "getLocalNode Status=: " + getLocalNodeResult.getStatus().getStatusMessage()); Node getnode = getLocalNodeResult.getNode(); @@ -791,5 +788,5 @@ public class ListenerService extends WearableListenerService implements GoogleAp Wearable.MessageApi.removeListener(googleApiClient, this); Wearable.ChannelApi.removeListener(googleApiClient, this); } - } + } } From c72ada9559bbb2b23ef3b2a5250bdc739d1bcb81 Mon Sep 17 00:00:00 2001 From: Andrew Warrington Date: Wed, 13 Jan 2021 10:26:27 +0000 Subject: [PATCH 04/61] Updated SVG text size in Cockpit following testing on new watch models. Text size reduced slightly as it was too large to fit when glucose in mmol/L was higher than 10. --- wear/src/main/res/layout/rect_cockpit.xml | 2 +- wear/src/main/res/layout/round_cockpit.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wear/src/main/res/layout/rect_cockpit.xml b/wear/src/main/res/layout/rect_cockpit.xml index 88bda0917c..cf26712258 100644 --- a/wear/src/main/res/layout/rect_cockpit.xml +++ b/wear/src/main/res/layout/rect_cockpit.xml @@ -175,7 +175,7 @@ android:layout_weight="1" android:text="---" android:textColor="@color/primary_text_dark" - android:textSize="26sp" /> + android:textSize="30sp" /> diff --git a/wear/src/main/res/layout/round_cockpit.xml b/wear/src/main/res/layout/round_cockpit.xml index b2892c20db..afdecf8a43 100644 --- a/wear/src/main/res/layout/round_cockpit.xml +++ b/wear/src/main/res/layout/round_cockpit.xml @@ -175,7 +175,7 @@ android:layout_weight="1" android:text="---" android:textColor="@color/primary_text_dark" - android:textSize="34sp" /> + android:textSize="30sp" /> From 91bac97dca21c94d24cc28979f6ce9a1a547980c Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 14 Jan 2021 10:17:04 +0100 Subject: [PATCH 05/61] New Crowdin updates (#225) * New translations strings.xml (Italian) * New translations strings.xml (Hebrew) * New translations strings.xml (Italian) * New translations strings.xml (Slovak) * New translations strings.xml (Slovak) * New translations strings.xml (Slovak) * New translations strings.xml (Slovak) * New translations strings.xml (Hebrew) * New translations strings.xml (Swedish) * New translations exam.xml (Swedish) * New translations strings.xml (Russian) * New translations strings.xml (Russian) * New translations strings.xml (Russian) * New translations exam.xml (Russian) * New translations strings.xml (Russian) --- app/src/main/res/values-it-rIT/strings.xml | 4 ++ app/src/main/res/values-iw-rIL/strings.xml | 13 +++++ app/src/main/res/values-ru-rRU/exam.xml | 58 +++++++++++++++++++ app/src/main/res/values-ru-rRU/strings.xml | 12 ++++ app/src/main/res/values-sk-rSK/strings.xml | 20 +++++++ app/src/main/res/values-sv-rSE/exam.xml | 2 +- app/src/main/res/values-sv-rSE/strings.xml | 17 +++++- .../src/main/res/values-ru-rRU/strings.xml | 2 + .../src/main/res/values-sk-rSK/strings.xml | 2 + .../src/main/res/values-ru-rRU/strings.xml | 11 ++++ .../src/main/res/values-sk-rSK/strings.xml | 11 ++++ wear/src/main/res/values-ru-rRU/strings.xml | 1 + wear/src/main/res/values-sk-rSK/strings.xml | 1 + 13 files changed, 152 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index 6ef1608520..634fddf596 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -285,6 +285,8 @@ Pasto Corr Azioni + Solo upload su NS (PERICOLOSO DISABILITARE) + Solo upload su NS (no sincronizzazione). Non ha effetto su SGV a meno che non sia selezionata una fonte locale come xDrip+. Non ha effetto sui profili mentre vengono usati i profili NS.\n!!! ATTENZIONE !!! Disabilitare questa opzione potrebbe causare malfunzionamenti e sovra-dosaggio di insulina se uno dei tuoi strumenti (AAPS, NS, xDrip+) è configurato in modo errato. Guarda attentamente se i dati visualizzati da AAPS corrispondono allo stato del micro! Micro non inizializzato! Carica/Riempi Assicurati che la quantità corrisponda alla specifica del tuo set di infusione! @@ -459,6 +461,7 @@ Autorizzazione SMS mancante Autorizzazione stato telefono mancante Stato xDrip+ (smartwatch) + Statusline xDrip+ (smartwatch) xds Mostra BGI Aggiungi BGI alla statusline @@ -501,6 +504,7 @@ Annulla Non tutti i profili caricati! Valori non memorizzati! + Abilita trasmissioni ad altre app (come xDrip+). Non abilitare se hai installato più di un\'istanza di AAPS o NSClient! Abilita le trasmissioni locali. Durata [min] OpenAPS SMB diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw-rIL/strings.xml index 682f804214..4a56f05279 100644 --- a/app/src/main/res/values-iw-rIL/strings.xml +++ b/app/src/main/res/values-iw-rIL/strings.xml @@ -42,6 +42,7 @@ קבלת ערכי סוכר בדם מ-Glimp. קבלת ערכי סוכר בדם מ-600SeriesAndroidUploader. הורדת ערכי סוכר בדם מ-Nightscout + קבלת ערכי סוכר מ-xDrip. שמירת כל הטיפולים שנעשו ניטור ושליטה ב-AndroidAPS באמצעות שעון WearOS. הצג מידע אודות הלולאה במסך Xdrip בשעון החכם. @@ -118,6 +119,7 @@ שנה קלט! מקור ערכי הסוכר מהו מקור הנתונים של AndroidAPS? + xDrip+ מצב APS לולאה סגורה לולאה פתוחה @@ -283,6 +285,8 @@ ארוחה תיקון פעולות + (מסוכן להשבית) העלאה בלבד לנייטסקאוט + העלאה בלבד של נתונים לנייטסקאוט. לא מתאים לשימוש אלא אם מקור נתוני הסוכר הוא מקומי כדוגמת xDrip. לא מתאים לשימוש בפרופילים מקוונים מנייטסקאוט.\n!!! אזהרה !!! ביטול אפשרות זו עלולה לגרום לתקלות ולמינון יתר של אינסולין אם אחד או יותר מרכיבי המערכת (AAPS, xDrip, נייטסקאוט) אינו מוגדר כהלכה. וודאו היטב שהנתונים המוצגים ב-AAPS תואמים את מצב המשאבה! משאבה לא הופעלה! תיחול\\מילוי נא ודאו שהכמות מתאימה למפרט ערכת העירוי שלכם! @@ -337,6 +341,7 @@ SMS קצר את כותרות הלשוניות התבסס על הפרש ממוצע קצר במקום הפרש פשוט\\רגיל + לשימוש כאשר נתונים ממקור לא מפוקח כמו xDrip אינם יציבים. פרופיל ערך ברירת מחדל: 3 מנגנון הגנה עיקרי של OpenAPS. מגביל את המינון הבזאלי לעד פי 3 מהמינון הבזאלי הגבוה ביותר שהוגדר. ברוב המקרים אין צורך לשנות ערך זה, אך יש לזכור שזו המשמעות של “3x max daily; 4x current” בדיון על מנגנוני הגנה. ערך ברירת מחדל: 4 זהו החצי השני של מנגנון הגנה עיקרי של OpenAPS, והחצי השני של \"3x max daily; 4x current\" במנגנוני ההגנה. המשמעות היא שהמינון הבזאלי, ללא קשר למקסימום שנקבע במשאבה, אינו יכול להיות גבוה יותר ממספר זה כפול הקצב הבזאלי הנוכחי. מיועד למנוע כניסה לתחומים מסוכנים ע\"י קביעת קצב בזאלי גבוה לפני הבנה של פעולת האלגוריתם. שוב: ברירת המחדל היא x4, רוב המשתמשים לעולם אינם צריכים לשנות ערך זה ואם הם מרגישים שמנגנון הגנה זה מפריע להם, הפתרון הוא בשינוי של הגדרות אחרות. @@ -350,6 +355,9 @@ מספר טלפון ל SMS לא תקין כיול xDrip+ אינו מותקן + כיול נשלח ל-xDrip+ + הכיול נשלח. יש לאשר את קבלת כיולים ב-xDrip+. + xDrip אינו מקבל כיולים משאבה מושהית מבצע הגדרות משאבה וירטואלית @@ -452,6 +460,8 @@ אודות הרשאות SMS חסרות הרשאת סטטוס הטלפון חסרה + מצב xDrip (שעון) + שורת מצב xDrip (שעון) xDS הצג השפעת רמת הסוכר הוסף השפעת הסוכר לשורת הסטטוס @@ -494,6 +504,7 @@ ביטול לא כל הפרופילים נטענו! הערכים לא נשמרו + אפשר הפצה לאפליקציות אחרות (כגון xDrip). אין להפעיל אם מותקן לכם יותר ממופע אחד של AAPS או NSClient! אפשר שידורים מקומיים. משך [min] OpenAPS SMB @@ -1164,6 +1175,7 @@ תרמו את נתוניכם למדע OH התנתקתם מ-Open Humans + לחצו כאן כדי להתחבר מחדש אם זה לא היה בכוונה. אפשר העלאה רק אם מחובר ל-WiFi אפשר העלאה רק בזמן טעינת הסוללה מצב עובד: %s @@ -1185,4 +1197,5 @@ זמן לאכול!\nהפעילו את אשף הבולוסים וחשבו בולוס חדש. זמן לאכול העלאת רשומות קריסה מושבתת! + גרף diff --git a/app/src/main/res/values-ru-rRU/exam.xml b/app/src/main/res/values-ru-rRU/exam.xml index b4073414aa..55d82a1d17 100644 --- a/app/src/main/res/values-ru-rRU/exam.xml +++ b/app/src/main/res/values-ru-rRU/exam.xml @@ -127,11 +127,40 @@ Context | Edit Context https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html Ошибки записи углеводов Что нужно делать, если сделан неправильный ввод углеводов? + Удалить неверную запись в Журнале терапии и заново ввести правильное значение углеводов. + Ввести инсулин через меню для заполнения канюли. + Ничего не делать – AndroidAPS сам внесет необходимые изменения. + Ввести инсулин через кнопку Инсулин (болюс) на вкладке Начало. + Ошибки подачи/поступления инсулина + Что делать, если вы получили меньше инсулина, чем указано в истории помпы, например, из-за окклюзии, проблем с канюлей или из-за того, что вы забыли подключить помпу обратно после душа? + Удалить данные об инсулине в Портале терапии Nightscout, чтобы удалить их из истории помпы. + Сравнить значения в AndroidAPS и истории помпы. + Рассчитать и ввести «пропущенный» вами инсулин шприцем/ручкой или через кнопку заполнения канюли. + Ничего не делать и позволить AndroidAPS исправить возможный высокий уровень ГК. + Активный инсулин (IOB) + Отметьте все правильные ответы. + На величину IOB влияют устанавливаемые ВБС. + Высокая ВБС не будет применяться, если уровень сахара в крови ниже целевого. + Отрицательный IOB в течение длительного периода при отсутствии физнагрузки указывает на то, что ваш профиль завышен и требуется снизить кол-во инсулина в настройках. + Положительный IOB в течение длительного периода предполагает инсулинорезистентность или не отмеченный прием пищи. + Запись углеводов и болюсов Для оценки и записи потребляемых углеводов следует использовать только граммы. + Употребленные углеводы можно записывать с помощью соответствующей системы обмена (например, DAFNE «CHO» или европейские «хлебные единицы»). AndroidAPS использует динамическую модель для оценки \"распада\" и расчета COB. Если уровень глюкозы в крови находится вне допустимых значений (слишком низкое или слишком высокое), то калькулятор болюса может быть использован для внесения предложений по коррекции соотношения инсулин/углеводы. https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/FAQ.html#insulin-to-carb-ratio-ic-g-u + Растянутые углеводы + Для чего можно использовать e-carbs (растянутые углеводы)? + Запланировать углеводы в будущем, возможно, распределить в течение определенного времени (по аналогии с растянутым болюсом на определенный интервал времени). + Для указания «бесплатных» углеводов при физнагрузке, чтобы скрыть их от AndroidAPS. + Растянутые углеводы (отмеченные в будущем) могут помочь AAPS в работе с пищей с высоким содержанием жиров/белков. + Для указания «лечебных» углеводов, при поднятии низкого уровня ГК. https://androidaps.readthedocs.io/en/latest/EN/Usage/Extended-Carbs.html + Удаленный мониторинг + Как можно удаленно отслеживать AndroidAPS (например, вашего ребенка)? + Приложение NS Client, приложение Nightscout и сайт Nightscout позволяют удаленно отслеживать AndroidAPS. + Прочие приложения (например, Dexcom follow, xDrip в режиме фолловера) позволяют удаленно отслеживать некоторые параметры (например, уровень ГК/значения сенсоров), но используют другие алгоритмы, поэтому могут отображать неточные значения IOB или COB. + Для удаленного отслеживания AndroidAPS оба устройства должны иметь доступ в Интернет (напр.,Wi-Fi или мобильной/сотовой сети). NS Client в режиме удаленки предоставляет как отслеживание, так и полное управление AndroidAPS. https://androidaps.readthedocs.io/en/latest/EN/Children/Children.html Фактор Чувствительности к Инсулину (ISF) @@ -142,18 +171,47 @@ Context | Edit Context Изменение значения ISF в профиле достаточно для применения изменений. https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/FAQ.html#insulin-sensitivity-factor-isf-mmol-l-u-or-mg-dl-u https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html + Вы можете использовать больше одного значения для коэффициента I:C в своем профиле. + Если вы изменяете ISF в своем профиле, вам всегда следует изменять соотношение I:C. + Углеводный коэффициент (соотношение I:C) + Более высокий I:C приводит к уменьшению количества инсулина, вводимого на данное число углеводов. + Более низкий I:C приводит к уменьшению количества инсулина, вводимого на данное число углеводов. Если у вас 0 активных углеводов COB, изменение соотношения инсулин-углеводы IC приведет к иному количеству инсулина на коррекцию данной ГК. Соотношение инсулин-углеводы IC изменится если принимать ХЕ за 10 или 12г. Смысл соотношения инсулин-углеводы IC таков: сколько хлебных единиц покрываются одной ед. инсулина. https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/FAQ.html#carbohydrate-to-insulin-ratio-cr-g-u Cмена профиля + При установке 90% при переключении профиля, какие утверждения верны? + Базальная скорость снизится на 10%. + ISF повысится на 10%. + Значение I:C снизится на 10%. + Коэффициенты ISF и I:C останутся без изменений. https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html?highlight=profile%20switch#profile-switch + Переключение профиля + При установке 120% при переключении профиля, какие утверждения верны? + Целевой уровень ГК будет на 20% выше. + Базальная скорость будет на 20% выше. + Целевой уровень ГК не изменится. + ISF будет на 20% выше. + Переключение профиля + Если вы проснулись на 2 часа раньше обычного, как необходимо уведомить AndroidAPS об изменении своего режима? Выполнить переключение профиля со сдвигом времени 2 Выполнить переключение профиля со сдвигом времени -2 + Установить временную цель \"Eating Soon\" (Ожидаемый прием пищи). + Задать профиль выше 100% https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html?highlight=profile%20switch#timeshift + Изменения в профилях + Базальные скорости, ISF, соотношение I:C и т.д. должны быть установлены в профилях. + Для активации изменений в профиле Nightscout требуется, чтобы телефон с AndroidAPS был подключен к Интернету. + Сохранения новых значений в профиле достаточно, чтобы все сделанные изменения вступили в силу. + Можно настроить несколько профилей и выбирать их в связи с меняющимися обстоятельствами (например, гормональные изменения, посменная работа, образ жизни в будние/выходные дни). https://androidaps.readthedocs.io/en/latest/EN/Module/module.html#good-individual-dosage-algorithm-for-your-diabetes-therapy + Помощь с базальной скоростью Куда обращаться за помощью по скорости базала и т. д. Ваши эндокринологи Google Facebook + Прочие препараты. Прочтите высказывание ниже, а затем отметьте галочку, чтобы принять условия. + AndroidAPS понижает базальную скорость или приостанавливает ввод инсулина для повышения уровня ГК. Препараты из класса ингибиторов SGLT2 (глифлозины) могут предотвращать повышение уровня ГК и, следовательно, вызывать опасную нехватку инсулина, приводящую к ДКА. +\nОбщими торговыми наименованиями являются: Invokana®, Forxiga®, Jardiance®, Steglatro®, Suglat®, Apleway®, Deberza®, Synjardy®, Vokanamet®, Xigduo®.\n\nЯ подтверждаю, что не буду принимать такие препараты, при использовании AndroidAPS или отключу цикл перед их применением. diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index a780b8c04d..dce3fbe795 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -42,6 +42,7 @@ Получать данные гликемии от Glimp. Получать данные гликемии от 600SeriesAndroidUploader. Получать данные гликемии с сайта Nightscout + Получать данные гликемии от xDrip+. Сохраняет все выполненные назначения Мониторить и контролировать AndroidAPS при помощи часов WearOS. Показать информацию о работе алгоритма ИПЖ на экране смарт-часов xDrip+. @@ -118,6 +119,7 @@ измените введенные данные источник СК Откуда должен получать данные AndroidAPS? + xDrip + режим APS Замкнутый цикл открытый цикл @@ -283,6 +285,8 @@ болюс на еду коррекция действия + (ОТКЛЮЧЕНИЕ ОПАСНО) Только загрузка в NS + Только загрузка в NS (синхронизация отключена). Не влияет на данные мониторинга если не выбран локальный источник, такой как xDrip. Профили, иные чем профиль NS не действуют.\n!!! ПРЕДУПРЕЖДЕНИЕ !!! Отключение этой опции может привести к сбою и передозировке инсулина, если какой-либо из компонентов (AAPS, NS, xDrip) настроен неправильно. Внимательно следите за тем, чтобы данные соответствовали состоянию помпы! помпа не инициализирована прайм/заполнение убедитесь что количество соответствует характеристикам вашей инфузионной системы @@ -337,6 +341,7 @@ SMS сокращенные имена табул всегда используйте укороченное среднее приращение вместо простого + Полезно когда данные из нефильтрованных источников вроде xDrip+ начинают \"шуметь\". профиль значение по умолчанию:3 Это ключевой ограничитель безопасности OpenAPS. Он ограничивает величину вашего базала максимум до 3x максимума. Вам вероятно не понадобится менять эту величину но вам следует понимать, что она входит в формулу дуэта \"максимум 3x ежедневное; 4x текущее\" значение по умолчанию: 4 . Это вторая половина обеспечения безопасности OpenAPS из дуэта \"максимум 3x ежедневное; 4x текущее\" Означает что ваша база независимо от установок помпы не может быть выше чем это число умноженное на текущее значение базала. Ограничение для того, чтобы предотвратить вторжение в опасную зону из-за высокого уровня установленных значений базы без понимания алгоритма работы приложения. Большинству людей никогда не потребуется изменять это значение, скорее всего нужно поменять другие настройки если вы чувствуете, что вам мешает это ограничение. @@ -350,6 +355,9 @@ неверный номер телефона для смс калибровка xdrip+ не установлен + Калибровка отправлена на xDrip+ + Калибровка отправлена. В xDrip+ должен быть включена возможность приема. + xDrip + не получает калибровки Работа помпы остановлена выполнение настройки вирт помпы @@ -452,6 +460,8 @@ о приложении отсутствует смс подтверждение Отсутствует разрешение телефона + Cтрока состояния xDrip (часы) + Cтрока состояния xDrip (часы) Статус xDrip показать BGI добавить BGI в строку состояния @@ -494,6 +504,7 @@ отмена не все профили загружены! Данные не сохранены! + Включить трансляцию для других приложений (например, xDrip). Не включайте, если установлено несколько экземпляров приложений AAPS или NSClient! Активировать локальную передачу Длительность (мин) Супер микро болюс OpenAPS @@ -1188,4 +1199,5 @@ Context | Edit Context Пора есть!\nЗапустите помощник болюса снова для подсчета. Пора есть Загрузка журналов сбоя на сервер отключена! + График diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index b774e1a8ea..46bf046e89 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -42,6 +42,7 @@ Získavať hodnoty glykémií z aplikácie Glimp. Získavať hodnoty glykémií z 600SeriesAndroidUploader. Získavať hodnoty glykémií z Nightscoutu + Prijímať hodnoty glykémií z xDrip+. Ukladá všetky ošetrenia do databázy Zobrazovanie stavu a riadenie AndroidAPS z hodiniek s WearOS. Zobraz informácie o uzavretom okruhu na xDrip+ watchface. @@ -118,6 +119,7 @@ Zmeňte zadanie! Zdroj glykémie Odkiaľ má AndroidAPS získavať glykémie? + xDrip+ APS mód Uzavretý okruh Otvorený okruh @@ -283,6 +285,8 @@ Bolus Korekcia Akcie + (DEAKTIVOVANIE NEBEZPEČNÉ) Iba odosielanie do NS + Iba odosielanie do NS. Neplatí pre glykémie, pokiaľ je NS zvolený, ako zdroj glykémií. Neplatí pre profily, pokiaľ je zvolený NS Profil.\n!!! VAROVANIE!!! Vypnutie tejto možnosti môže spôsobiť nesprávne fungovanie a predávkovanie inzulínom, pokiaľ je niektorý z vašich komponentov (AAPS, NS, xDrip+) nesprávne nastavený. Starostlivo sledujte, či dáta zobrazené v AAPS, zodpovedajú aktuálnemu stavu na pumpe! Pumpa nie je inicializovaná! Plnenie/doplňovanie Prosím uistite sa, že hodnota zodpovedá špecifikácií Vášho setu! @@ -337,6 +341,7 @@ SMS Krátke názvy modulov Vždy používať krátkodobý priemerný rozdiel glykémií, namiesto rozdielu posledných dvoch hodnôt + Zmysluplné, pokiaľ dáta z xDrip+ obsahujú veľký šum. Profil Štandardná hodnota: 3 Toto je kľúčová hodnota zabezpečenia. Hovorí, že maximálny nastaviteľný bazál je trojnásobkom maximálneho denného bazálu. Spravidla to zrejme nebudete musieť meniť, prípadne si prečítate o téme \"3x max denný; 4x aktuálny\". Štandardná hodnota: 4 Toto je druhá kľúčová hodnota. Hovorí, že maximálna hodnota dočasného bazálu nikdy nebude väčšia, ako štvornásobok aktuálneho bazálu. Je to preto, aby se ľudia nedostali do nebezpečných hodnôt skôr, ako pochopia ako OpenAPS pracuje. Znovu, štandardná hodnota je 4 a väčšina ľudí ju nikdy nebude musieť meniť. Pokiaľ nestačí, obvykle je problém niekde inde. @@ -350,6 +355,9 @@ Chybné telefónne číslo Kalibrácia xDrip+ nie je nainštalovaný + Kalibrácia odoslaná do xDrip+ + Kalibrácia odoslaná. Príjem kalibrácií musí byť povolený v xDrip+. + xDrip+ neprijíma kalibrácie Pumpa pozastavená Vykonávam Nastavenie virtuálnej pumpy @@ -435,8 +443,12 @@ Prah kritického veku senzora [h] Prah upozornenia na úroveň batérie senzora [%] Prah kritickej úrovne batérie senzora [%] + Prah upozornenia na vek batérie v pumpe [h] + Prah kritického veku batérie v pumpe [h] Prah upozornenia na úroveň hladiny zásobníka [JI] Prah kritickej úrovne hladiny zásobníka [JI] + Prah upozornenia na úroveň batérie v pumpe [%] + Prah kritickej úrovne batérie v pumpe [%] PRED IOB COB @@ -448,6 +460,8 @@ O aplikácii Chýbajúce povolenie SMS príkazov Chýba oprávnenia pre zisťovanie stavu telefónu + Stav z xDrip+ (hodinky) + Stavový riadok xDrip+ (hodinky) XDS Zobrazovať BGI Pridať BGI do stavového riadku @@ -490,6 +504,7 @@ Zrušiť Nenačítané všetky profily! Hodnoty nie sú uložené! + Povoliť vysielanie do iných aplikácií (napr. xDrip+). Nepovoľujte, pokiaľ máte nainštalovanú viac ako jednu AAPS, alebo NSClient inštanciu! Povoliť lokálne vysielanie. Trvanie [min] OpenAPS SMB @@ -1160,6 +1175,7 @@ Darujte svoje údaje vede OH Boli ste odhlásený z Open Humans + Kliknite sem, ak sa chcete prihlásiť znova, v prípade, že sa to stalo nedopatrením. Odoslať iba ak ste pripojený k Wi-Fi Odoslať iba pri nabíjaní Stav procesu: %s @@ -1171,11 +1187,15 @@ Nepotláčať moju aplikáciu? Alarm Odoslať SMS, pokiaľ pumpa nie je dostupná + Nahlásiť nedostupnú pumpu Spustiť výstrahu, keď je čas na jedlo Spustiť výstrahu za %1$d min Bolusový poradca Máte vysokú glykémiu. Namiesto jedla doporučujeme počkať na lepšiu glykémiu a pripomenúť, keď bude čas na jedlo. Prajete si poslať korekčný bolus a pripomenúť, keď bude čas na jedlo? V tomto prípade nebudú zapísané žiadne sacharidy, a neskôr musíte opäť spustiť kalkulačku, akonáhle vám to pripomenieme. Povoliť bolusového poradcu + Pri vysokej glykémii spustiť pripomienku namiesto výsledku z kalkulačky, aby ste začali jesť neskôr (tzv. \"prebolus\") Čas na jedlo!\nSpustite Bolusovú kalkulačku a urobte výpočet znova. Čas na jedlo + Odosielanie protokolov o zlyhaní je zakázané! + Graf diff --git a/app/src/main/res/values-sv-rSE/exam.xml b/app/src/main/res/values-sv-rSE/exam.xml index 94659df495..25898c36e8 100644 --- a/app/src/main/res/values-sv-rSE/exam.xml +++ b/app/src/main/res/values-sv-rSE/exam.xml @@ -157,7 +157,7 @@ Fjärrövervakning Hur kan du övervaka AndroidAPS (till exempel för ditt barn) på distans? NS Client-appen, Nightscout-app och webbsidan för Nightscout tillåter att du följer AndroidAPS på distans. - Andra appar (t.ex. Dexcom Follow, xDrip i följarläge) gör att du kan följa vissa parametrar (t.ex. BG-värden) men använder andra algoritmer så IOB och COB kanske inte överenstämmer. + Andra appar (t.ex. Dexcom Follow, xDrip+ i följarläge) gör att du kan följa vissa parametrar (t.ex. BG-värden) men använder andra algoritmer så IOB och COB kanske inte överenstämmer. För att följa AndroidAPS måste båda enheterna ha Internetåtkomst (via WiFi eller mobildata). NS Client som används som följare kommer både kunna övervaka och ge full kontroll över AndroidAPS. https://androidaps.readthedocs.io/en/latest/EN/Children/Children.html diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index f5104e8e2a..b7b32bbac5 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -43,9 +43,10 @@ Eversense-appen. Ta emot BG-data från Glimp Ta emot BG-data från 600SeriesAndroidUploader Ladda ner BG-data från Nightscout + Ta emot BG-data från xDrip+. Spara alla behandlingar som gjorts Följ och kontrollera AndroidAPS med din Wear OS-klocka - Visa AAPS-information på din xDrip-urtavla + Visa AAPS-information på din xDrip+ urtavla. Fjärrstyr AndroidAPS med SMS-kommandon. Insulin: KH: @@ -119,6 +120,7 @@ Eversense-appen. Ändra inmatning BG-källa Var ska AndroidAPS få sitt data ifrån? + xDrip+ APS-läge Closed Loop Open Loop @@ -284,6 +286,8 @@ Eversense-appen. Måltid Korrektion Åtgärder + (INAKTIVERAD KAN MEDFÖRA FARA) NS-Endast uppladdning + NS-endast uppladdning (inaktiverad synkronisering). Påverkar inte uppladdning av BG om inte en lokal källa som xDrip+ är vald. NS-profiler kan också användas.\nVARNING! Att inaktivera detta alternativ och därmed tillåta att NS påverkar AAPS kan orsaka fel och t. o. m. insulinöverdos om någon av dina komponenter (AAPS, NS, xDrip+) inte är helt rätt konfigurerade. Övervaka noga att data som visas av AAPS överensstämmer med verkligheten! Pump inte initierad Förfyllning Försäkra dig om att mängden motsvarar det som är specificerat för just ditt infusionsset. @@ -338,6 +342,7 @@ Eversense-appen. SMS Förkorta namnen på flikarna Använd alltid kort medeldelta istället för enkel delta + Användbart när ofiltrerade källor ger brusiga värden. Profil Standardvärde: 3 Detta är en grundsten i OpenAPS säkerhet. Detta begränsar dina temp basaler till maximalt 3x din största basaldos. Du behöver oftast inte ändra detta värde. Läs på och förstå skillnaden mellan 3x nuvarande och 3x daglig max som säkerhetsinställningar. Standardvärde: 4 Detta är en grundsten i OpenAPS säkerhet. Detta begränsar dina tempbasaler till maximalt 4 gånger din nuvarande basaldos, oberoende av din maximala basaldos. Detta för att undvika att man av misstag gör farliga inställningar. Om man når taket i denna inställning så kanske ändringar i andra inställningar behövs. De flesta behöver inte ändra denna inställning. @@ -351,6 +356,9 @@ Eversense-appen. Ogiltigt telefonnummer för SMS Kalibrering xDrip+ inte installerat + Kalibrering skickad till xDrip+ + Kalibrering skickad. Observera att xDrip+ måste vara inställd att ta emot kalibreringar. + xDrip+ tar inte emot kalibreringar Pump pausad Utför Inställningar för Virtuell pump @@ -453,6 +461,8 @@ Eversense-appen. Om Saknar behörighet att skicka SMS Behörighet saknas + xDrip+ Status (klocka) + xDrip+ Statusrad (klocka) xds Visa BGI Visa BGI i statusraden @@ -495,6 +505,7 @@ Eversense-appen. Avbryt Alla profiler laddades inte! Alla värden sparades inte! + Aktivera sändning till andra appar (som xDrip+) på denna telefon. Aktivera inte detta om du har fler än en förekomst av AAPS eller NSClient installerad! Aktivera lokala broadcasts Duration [min] OpenAPS SMB @@ -1165,6 +1176,7 @@ Eversense-appen. Donera dina data till vetenskapen OH Du har loggats ut från Open Humans + Klicka här om du vill logga in igen. Ladda bara upp om ansluten till WiFi Ladda bara upp vid laddning Jobbstatus: %s @@ -1176,6 +1188,7 @@ Eversense-appen. Döda inte min app? Larm Skicka SMS om pumpen inte kan nås + Rapportera om pump inte kan nås Larma när det är dags att äta Larma om %1$d min Bolusguide @@ -1184,4 +1197,6 @@ Eversense-appen. Få en påminnelse om att börja äta senare (istället för kalkylatorns resultat) om du ligger högt i BG Dags att äta!\nKör bolusguiden igen för ny beräkning. Dags att äta + Uppladdning av kraschloggar inaktiverad! + Graf diff --git a/omnipod/src/main/res/values-ru-rRU/strings.xml b/omnipod/src/main/res/values-ru-rRU/strings.xml index 6c20b5151e..9aca90148a 100644 --- a/omnipod/src/main/res/values-ru-rRU/strings.xml +++ b/omnipod/src/main/res/values-ru-rRU/strings.xml @@ -11,6 +11,7 @@ Показывать кнопку Приостановить подачу на вкладке Omnipod Показывать кнопку Pulse Log в меню управления Pod Показывать кнопку статистики RileyLink в меню управления подом + Включить учет расхода заряда батареи Включено обнаружение часового пояса Включено напоминание об истечении срока действия Часов до выключения @@ -65,6 +66,7 @@ Недопустимый адрес RileyLink. Операция невозможна.\n\n Сначала нужно настроить помпу Omnipod. Активная помпа не включена + Время в Pod не синхронизировано. Обновите время на вкладке Omnipod. Непредвиденная ошибка. Сообщите об ошибке! (%1$s:%2$s). Ошибка связи: не удалось проверить целостность сообщения Ошибка связи: получен недопустимый пакет от Pod diff --git a/omnipod/src/main/res/values-sk-rSK/strings.xml b/omnipod/src/main/res/values-sk-rSK/strings.xml index 728b703bf5..1e0cb688ad 100644 --- a/omnipod/src/main/res/values-sk-rSK/strings.xml +++ b/omnipod/src/main/res/values-sk-rSK/strings.xml @@ -11,6 +11,7 @@ Zobraziť tlačítko \"Pozastaviť podávanie\" na záložke Omnipod Zobraziť tlačítko Pulzný Log v menu Správa Podu Zobraziť tlačítko Štatistika RileyLink v menu Správa Podu + V Akciách povoliť zaznamenávanie výmeny batérie Letný čas / Detekcia časového pásma povolená Pripomenutie vypršania platnosti povolené Hodiny pred vypnutím @@ -65,6 +66,7 @@ Neplatná adresa RileyLinku. Operácia nie je možná.\n\nNajskôr je nutné nakonfigurovať Omnipod, kým bude možné túto funkciu použiť. Žiadny aktívny Pod + Čas na Pode nie je synchronizovaný. Aktualizujte prosím čas na záložke Omnipod. Došlo k neočakávanej chybe. Prosíme o jej nahlásenie! (%1$s: %2$s). Komunikácia zlyhala: overenie integrity správy zlyhalo Komunikácia zlyhala: boli prijaté neplatné pakety z Podu diff --git a/rileylink/src/main/res/values-ru-rRU/strings.xml b/rileylink/src/main/res/values-ru-rRU/strings.xml index bd7cc89f60..6876516159 100644 --- a/rileylink/src/main/res/values-ru-rRU/strings.xml +++ b/rileylink/src/main/res/values-ru-rRU/strings.xml @@ -22,15 +22,23 @@ Статус помпы Настройки RileyLink RileyLink + Адрес: + Имя: + Уровень заряда riley: + %1$d%% Статус подключения: Ошибка подключения: Устройство Тип устройства: + Настроенная модель устройства: + Подключенное устройство: Последняя использованная частота: Контакт последнего устройства: Версия прошивки: + BLE113: %1$s\nCC110: %2$s Серийный номер помы: Частота помпы: + %1$.2f МГц Инициализация Bluetooth… Ошибка Bluetooth @@ -52,9 +60,12 @@ POD недоступен Помпа Medtronic + Omnompod (Eros) Да Нет + Использовать уровень заряда батареи, который передает OrangeLink/EmaLink + НЕ РАБОТАЕТ с оригинальной RileyLink. Может не работать с альтернативными RileyLink. %1$d день %1$d дня diff --git a/rileylink/src/main/res/values-sk-rSK/strings.xml b/rileylink/src/main/res/values-sk-rSK/strings.xml index 362fe2b6e3..180ecb1b7a 100644 --- a/rileylink/src/main/res/values-sk-rSK/strings.xml +++ b/rileylink/src/main/res/values-sk-rSK/strings.xml @@ -22,15 +22,23 @@ Stav pumpy Nastavenie RileyLink RileyLink + Adresa: + Meno: + Úroveň batérie: + %1$d%% Stav pripojenia: Chyba pripojenia: Zariadenie Typ zariadenia: + Model nakonfigurovaného zariadenia: + Model pripojeného zariadenia: Posledná použitá frekvencia: Posledné spojenie zo zariadením: Verzia firmvéru: + BLE113: %1$s\nCC110: %2$s Sériové číslo pumpy: Frekvencia pumpy: + %1$.2f MHz Inicializácia Bluetooth... Chyba Bluetooth @@ -52,9 +60,12 @@ Pod nedostupný Pumpa Medtronic + Omnipod (Eros) Áno Nie + Ukázať úroveň batérie nahlásenú OrangeLinkom/RileyLinkom + NEPRACUJE s pôvodným RileyLinkom. Nemusí pracovať s inými alternatívami RileyLinku. %1$d deň %1$d dní diff --git a/wear/src/main/res/values-ru-rRU/strings.xml b/wear/src/main/res/values-ru-rRU/strings.xml index 4a2e4bbd04..7594ea3a08 100644 --- a/wear/src/main/res/values-ru-rRU/strings.xml +++ b/wear/src/main/res/values-ru-rRU/strings.xml @@ -69,6 +69,7 @@ eCarbs/производные углеводы Настройки Состояние + Синхронизировать повторно Прайм/заполнение Не показывать По умолчанию diff --git a/wear/src/main/res/values-sk-rSK/strings.xml b/wear/src/main/res/values-sk-rSK/strings.xml index 8a21ef4fdb..7c610bc379 100644 --- a/wear/src/main/res/values-sk-rSK/strings.xml +++ b/wear/src/main/res/values-sk-rSK/strings.xml @@ -69,6 +69,7 @@ eCarbs Nastavenia Stav + Opätovne synchronizovať Plnenie/Doplňovanie Žiadny Štandardný From 3682693c10778d3d2f077e0d55dd49e0bec1c2be Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 14 Jan 2021 12:28:15 +0100 Subject: [PATCH 06/61] prevent NPE --- app/build.gradle | 2 +- .../info/nightscout/androidaps/utils/ui/NumberPicker.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 00d652487c..ce1b0af2aa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -120,7 +120,7 @@ android { targetSdkVersion 28 multiDexEnabled true versionCode 1500 - version "2.8.1.1" + version "2.8.1.2-dev" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' diff --git a/core/src/main/java/info/nightscout/androidaps/utils/ui/NumberPicker.java b/core/src/main/java/info/nightscout/androidaps/utils/ui/NumberPicker.java index 1681ea4653..b90b25a81c 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/ui/NumberPicker.java +++ b/core/src/main/java/info/nightscout/androidaps/utils/ui/NumberPicker.java @@ -36,10 +36,10 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, Button minusButton; Button plusButton; - Double value; - Double minValue = 0d; - Double maxValue = 1d; - Double step = 1d; + double value = 0; + double minValue = 0d; + double maxValue = 1d; + double step = 1d; NumberFormat formatter; boolean allowZero = false; TextWatcher textWatcher = null; From 90f6908b229c043ed1a13989b1b81ca55aacefd5 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 14 Jan 2021 18:39:23 +0100 Subject: [PATCH 07/61] HistoryBrowser: synchronize access to graph --- .../historyBrowser/HistoryBrowseActivity.kt | 148 +++++++++--------- 1 file changed, 77 insertions(+), 71 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt index 255a73f755..b6bd7f6279 100644 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt @@ -69,6 +69,8 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { private var rangeToDisplay = 24 // for graph private var start: Long = 0 + private val graphLock = Object() + private var eventCustomCalculationFinished = EventCustomCalculationFinished() override fun onCreate(savedInstanceState: Bundle?) { @@ -218,40 +220,40 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { } private fun prepareGraphsIfNeeded(numOfGraphs: Int) { + synchronized(graphLock) { + if (numOfGraphs != secondaryGraphs.size - 1) { + //aapsLogger.debug("New secondary graph count ${numOfGraphs-1}") + // rebuild needed + secondaryGraphs.clear() + secondaryGraphsLabel.clear() + history_iobgraph.removeAllViews() + for (i in 1 until numOfGraphs) { + val relativeLayout = RelativeLayout(this) + relativeLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - if (numOfGraphs != secondaryGraphs.size - 1) { - //aapsLogger.debug("New secondary graph count ${numOfGraphs-1}") - // rebuild needed - secondaryGraphs.clear() - secondaryGraphsLabel.clear() - history_iobgraph.removeAllViews() - for (i in 1 until numOfGraphs) { - val relativeLayout = RelativeLayout(this) - relativeLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + val graph = GraphView(this) + graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, resourceHelper.dpToPx(100)).also { it.setMargins(0, resourceHelper.dpToPx(15), 0, resourceHelper.dpToPx(10)) } + graph.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid) + graph.gridLabelRenderer?.reloadStyles() + graph.gridLabelRenderer?.isHorizontalLabelsVisible = false + graph.gridLabelRenderer?.labelVerticalWidth = axisWidth + graph.gridLabelRenderer?.numVerticalLabels = 3 + graph.viewport.backgroundColor = Color.argb(20, 255, 255, 255) // 8% of gray + relativeLayout.addView(graph) - val graph = GraphView(this) - graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, resourceHelper.dpToPx(100)).also { it.setMargins(0, resourceHelper.dpToPx(15), 0, resourceHelper.dpToPx(10)) } - graph.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid) - graph.gridLabelRenderer?.reloadStyles() - graph.gridLabelRenderer?.isHorizontalLabelsVisible = false - graph.gridLabelRenderer?.labelVerticalWidth = axisWidth - graph.gridLabelRenderer?.numVerticalLabels = 3 - graph.viewport.backgroundColor = Color.argb(20, 255, 255, 255) // 8% of gray - relativeLayout.addView(graph) + val label = TextView(this) + val layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).also { it.setMargins(resourceHelper.dpToPx(30), resourceHelper.dpToPx(25), 0, 0) } + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP) + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT) + label.layoutParams = layoutParams + relativeLayout.addView(label) + secondaryGraphsLabel.add(label) - val label = TextView(this) - val layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).also { it.setMargins(resourceHelper.dpToPx(30), resourceHelper.dpToPx(25), 0, 0) } - layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP) - layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT) - label.layoutParams = layoutParams - relativeLayout.addView(label) - secondaryGraphsLabel.add(label) - - history_iobgraph.addView(relativeLayout) - secondaryGraphs.add(graph) + history_iobgraph.addView(relativeLayout) + secondaryGraphs.add(graph) + } } } - } private fun runCalculation(from: String) { @@ -317,55 +319,59 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2) } // ------------------ 2nd graph - for (g in 0 until secondaryGraphs.size) { - val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculatorPluginHistory, treatmentsPluginHistory) - var useIobForScale = false - var useCobForScale = false - var useDevForScale = false - var useRatioForScale = false - var useDSForScale = false - var useIAForScale = false - var useABSForScale = false - when { - menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true - menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true - menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true - menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true - menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true - menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true - menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true + synchronized(graphLock) { + for (g in 0 until secondaryGraphs.size) { + val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculatorPluginHistory, treatmentsPluginHistory) + var useIobForScale = false + var useCobForScale = false + var useDevForScale = false + var useRatioForScale = false + var useDSForScale = false + var useIAForScale = false + var useABSForScale = false + when { + menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true + } + + if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, menuChartSettings[g + 1][OverviewMenus.CharType.PRE.ordinal]) + if (menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5) + if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, toTime, useIAForScale, 0.8) + if (menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, toTime, useABSForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1.0) + + // set manual x bounds to have nice steps + secondGraphData.formatAxis(fromTime, toTime) + secondGraphData.addNowLine(pointer) + secondaryGraphsData.add(secondGraphData) } - - if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, menuChartSettings[g + 1][OverviewMenus.CharType.PRE.ordinal]) - if (menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5) - if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0) - if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0) - if (menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, toTime, useIAForScale, 0.8) - if (menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, toTime, useABSForScale, 1.0) - if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1.0) - - // set manual x bounds to have nice steps - secondGraphData.formatAxis(fromTime, toTime) - secondGraphData.addNowLine(pointer) - secondaryGraphsData.add(secondGraphData) } } } // finally enforce drawing of graphs in UI thread graphData.performUpdate() if (!bgOnly) - for (g in 0 until secondaryGraphs.size) { - secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1) - secondaryGraphs[g].visibility = (!bgOnly && ( - menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] || - menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] || - menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] || - menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] || - menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] || - menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] || - menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] - )).toVisibility() - secondaryGraphsData[g].performUpdate() + synchronized(graphLock) { + for (g in 0 until secondaryGraphs.size) { + secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1) + secondaryGraphs[g].visibility = (!bgOnly && ( + menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] + )).toVisibility() + secondaryGraphsData[g].performUpdate() + } } } } From 4c9052b29a166cb946fcc138afaa92458ff95b34 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 14 Jan 2021 18:45:51 +0100 Subject: [PATCH 08/61] prevent NPE --- .../plugins/treatments/fragments/TreatmentsBolusFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusFragment.kt index 421cfe172a..c4639114d4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusFragment.kt @@ -158,7 +158,7 @@ class TreatmentsBolusFragment : DaggerFragment() { } calculation.paintFlags = calculation.paintFlags or Paint.UNDERLINE_TEXT_FLAG remove.setOnClickListener { - val treatment = it.tag as Treatment + val treatment = it.tag as Treatment? ?: return@setOnClickListener activity?.let { activity -> val text = resourceHelper.gs(R.string.configbuilder_insulin) + ": " + resourceHelper.gs(R.string.formatinsulinunits, treatment.insulin) + "\n" + From 4d4e0ffab362e128f55a30a50695d78887076640 Mon Sep 17 00:00:00 2001 From: Philoul Date: Fri, 15 Jan 2021 00:27:05 +0100 Subject: [PATCH 09/61] Add String for Bolus Progress / Cancel Button for translation --- .../info/nightscout/androidaps/data/ListenerService.java | 7 ++++--- wear/src/main/res/values/strings.xml | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java b/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java index 2f048af9a7..ef32aecde9 100644 --- a/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java +++ b/wear/src/main/java/info/nightscout/androidaps/data/ListenerService.java @@ -37,6 +37,7 @@ import com.google.android.gms.wearable.WearableListenerService; import java.util.Set; import java.util.concurrent.TimeUnit; +import info.nightscout.androidaps.aaps; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interaction.AAPSPreferences; import info.nightscout.androidaps.interaction.actions.AcceptActivity; @@ -635,13 +636,13 @@ public class ListenerService extends WearableListenerService implements GoogleAp NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS) .setSmallIcon(R.drawable.ic_icon) - .setContentTitle("Bolus Progress") + .setContentTitle(aaps.gs(R.string.bolus_progress)) .setContentText(progresspercent + "% - " + progresstatus) - .setSubText("press to cancel") + .setSubText(aaps.gs(R.string.press_to_cancel)) .setContentIntent(cancelPendingIntent) .setPriority(NotificationCompat.PRIORITY_MAX) .setVibrate(vibratePattern) - .addAction(R.drawable.ic_cancel, "CANCEL BOLUS", cancelPendingIntent); + .addAction(R.drawable.ic_cancel, aaps.gs(R.string.cancel_bolus), cancelPendingIntent); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); diff --git a/wear/src/main/res/values/strings.xml b/wear/src/main/res/values/strings.xml index 3f455b036b..715bda4d95 100644 --- a/wear/src/main/res/values/strings.xml +++ b/wear/src/main/res/values/strings.xml @@ -100,6 +100,9 @@ timeshift bolus + Bolus Progress + press to cancel + CANCEL BOLUS Pump Loop From 534b27cb710bda3763ed7d27a722e608ef34a7e7 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 15 Jan 2021 13:34:05 +0100 Subject: [PATCH 10/61] prevent NPE --- .../androidaps/plugins/treatments/TreatmentsPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java index 507f649a55..cf7a11dcd3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java @@ -473,6 +473,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface for (long i = time - range(); i < time; i += T.mins(5).msecs()) { Profile profile = profileFunction.getProfile(i); + if (profile == null) continue; double basal = profile.getBasal(i); TemporaryBasal runningTBR = getTempBasalFromHistory(i); double running = basal; From d300a95e393c092bceb5d4b8ff6c30912bc5a436 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 15 Jan 2021 13:37:30 +0100 Subject: [PATCH 11/61] prevent NPE --- .../nightscout/androidaps/queue/QueueThread.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java index 0eac5ff630..9dbd2c3ef4 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java @@ -81,11 +81,13 @@ public class QueueThread extends Thread { pump.stopConnecting(); pump.disconnect("watchdog"); SystemClock.sleep(1000); - BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - mBluetoothAdapter.disable(); - SystemClock.sleep(1000); - mBluetoothAdapter.enable(); - SystemClock.sleep(1000); + BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (bluetoothAdapter != null) { + bluetoothAdapter.disable(); + SystemClock.sleep(1000); + bluetoothAdapter.enable(); + SystemClock.sleep(1000); + } //start over again once after watchdog barked //Notification notification = new Notification(Notification.OLD_NSCLIENT, "Watchdog", Notification.URGENT); //rxBus.send(new EventNewNotification(notification)); From edd34622fd39bd93cc67db713d5e0a54b245a2b9 Mon Sep 17 00:00:00 2001 From: Sam Spycher Date: Fri, 15 Jan 2021 19:26:58 +0100 Subject: [PATCH 12/61] Prevent NPE when checking for battery level This is a simple caller-side fix to prevent NullPointerException when checking battery level. The NPE happened when the BT stack returned an empty array in the response with a `RESULT_SUCCESS` result code. We now check for empty array, and log that as a seperate error is such a response is received. --- .../pump/common/hw/rileylink/ble/RFSpy.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java index 2b3257ffca..0f3f92cb5d 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java @@ -2,6 +2,8 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble; import android.os.SystemClock; +import org.apache.commons.lang3.ArrayUtils; + import java.util.Optional; import java.util.UUID; @@ -111,13 +113,17 @@ public class RFSpy { public Integer retrieveBatteryLevel() { BLECommOperationResult result = rileyLinkBle.readCharacteristic_blocking(batteryServiceUUID, batteryLevelUUID); if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) { - int value = result.value[0]; - aapsLogger.debug(LTag.PUMPBTCOMM, "BLE battery level: {}", value); - return value; + if (ArrayUtils.isNotEmpty(result.value)) { + int value = result.value[0]; + aapsLogger.debug(LTag.PUMPBTCOMM, "BLE battery level: {}", value); + return value; + } else { + aapsLogger.error(LTag.PUMPBTCOMM, "getBatteryLevel received an empty result. Value: " + result.value); + } } else { aapsLogger.error(LTag.PUMPBTCOMM, "getBatteryLevel failed with code: " + result.resultCode); - return null; } + return null; } // This gets the version from the BLE113, not from the CC1110. From 5f3fdca06365ee4aa268904d4aadc80b90b4af28 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sat, 16 Jan 2021 18:13:59 +0100 Subject: [PATCH 13/61] lint --- .../general/overview/StatusLightHandler.kt | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt index dbdfe39bb4..38cf5c815b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt @@ -30,32 +30,32 @@ class StatusLightHandler @Inject constructor( /** * applies the extended statusLight subview on the overview fragment */ - fun updateStatusLights(careportal_canulaage: TextView?, careportal_insulinage: TextView?, careportal_reservoirlevel: TextView?, careportal_sensorage: TextView?, careportal_sensorbatterylevel: TextView?, careportal_pbage: TextView?, careportal_batterylevel: TextView?) { + fun updateStatusLights(careportal_cannula_age: TextView?, careportal_insulin_age: TextView?, careportal_reservoir_level: TextView?, careportal_sensor_age: TextView?, careportal_sensor_battery_level: TextView?, careportal_pb_age: TextView?, careportal_battery_level: TextView?) { val pump = activePlugin.activePump val bgSource = activePlugin.activeBgSource - handleAge(careportal_canulaage, CareportalEvent.SITECHANGE, R.string.key_statuslights_cage_warning, 48.0, R.string.key_statuslights_cage_critical, 72.0) - handleAge(careportal_insulinage, CareportalEvent.INSULINCHANGE, R.string.key_statuslights_iage_warning, 72.0, R.string.key_statuslights_iage_critical, 144.0) - handleAge(careportal_sensorage, CareportalEvent.SENSORCHANGE, R.string.key_statuslights_sage_warning, 216.0, R.string.key_statuslights_sage_critical, 240.0) + handleAge(careportal_cannula_age, CareportalEvent.SITECHANGE, R.string.key_statuslights_cage_warning, 48.0, R.string.key_statuslights_cage_critical, 72.0) + handleAge(careportal_insulin_age, CareportalEvent.INSULINCHANGE, R.string.key_statuslights_iage_warning, 72.0, R.string.key_statuslights_iage_critical, 144.0) + handleAge(careportal_sensor_age, CareportalEvent.SENSORCHANGE, R.string.key_statuslights_sage_warning, 216.0, R.string.key_statuslights_sage_critical, 240.0) if (pump.pumpDescription.isBatteryReplaceable) { - handleAge(careportal_pbage, CareportalEvent.PUMPBATTERYCHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0) + handleAge(careportal_pb_age, CareportalEvent.PUMPBATTERYCHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0) } if (!config.NSCLIENT) { if (pump.model() == PumpType.Insulet_Omnipod) { - handleOmnipodReservoirLevel(careportal_reservoirlevel, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U") + handleOmnipodReservoirLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U") } else { - handleLevel(careportal_reservoirlevel, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U") + handleLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U") } if (bgSource.sensorBatteryLevel != -1) - handleLevel(careportal_sensorbatterylevel, R.string.key_statuslights_sbat_critical, 5.0, R.string.key_statuslights_sbat_warning, 20.0, bgSource.sensorBatteryLevel.toDouble(), "%") + handleLevel(careportal_sensor_battery_level, R.string.key_statuslights_sbat_critical, 5.0, R.string.key_statuslights_sbat_warning, 20.0, bgSource.sensorBatteryLevel.toDouble(), "%") else - careportal_sensorbatterylevel?.text = "" + careportal_sensor_battery_level?.text = "" } if (!config.NSCLIENT) { - if (pump.model() == PumpType.Insulet_Omnipod && pump is OmnipodPumpPlugin) { // instanceof check is needed because at startup, pump can still be VirtualPumpPlugin and that will cause a crash because of the class cast below - handleOmnipodBatteryLevel(careportal_batterylevel, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%", (pump as OmnipodPumpPlugin).isUseRileyLinkBatteryLevel) + if (pump.model() == PumpType.Insulet_Omnipod && pump is OmnipodPumpPlugin) { // instance of check is needed because at startup, pump can still be VirtualPumpPlugin and that will cause a crash because of the class cast below + handleOmnipodBatteryLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%", pump.isUseRileyLinkBatteryLevel) } else if (pump.model() != PumpType.AccuChekCombo) { - handleLevel(careportal_batterylevel, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%") + handleLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%") } } } @@ -81,6 +81,7 @@ class StatusLightHandler @Inject constructor( } // Omnipod only reports reservoir level when it's 50 units or less, so we display "50+U" for any value > 50 + @Suppress("SameParameterValue") private fun handleOmnipodReservoirLevel(view: TextView?, criticalSetting: Int, criticalDefaultValue: Double, warnSetting: Int, warnDefaultValue: Double, level: Double, units: String) { if (level > OmnipodConstants.MAX_RESERVOIR_READING) { @Suppress("SetTextI18n") @@ -91,6 +92,7 @@ class StatusLightHandler @Inject constructor( } } + @Suppress("SameParameterValue") private fun handleOmnipodBatteryLevel(view: TextView?, criticalSetting: Int, criticalDefaultValue: Double, warnSetting: Int, warnDefaultValue: Double, level: Double, units: String, useRileyLinkBatteryLevel: Boolean) { if (useRileyLinkBatteryLevel) { handleLevel(view, criticalSetting, criticalDefaultValue, warnSetting, warnDefaultValue, level, units) From 22f9ccab32fed0a0d35f606481eacce46419eace Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sat, 16 Jan 2021 18:29:18 +0100 Subject: [PATCH 14/61] simplify code --- app/src/main/AndroidManifest.xml | 1 + .../plugins/aps/loop/LoopPlugin.java | 53 ++++++++----------- .../general/openhumans/OpenHumansUploader.kt | 27 +++++----- .../notifications/NotificationStore.kt | 25 +++------ .../PersistentNotificationPlugin.kt | 14 ++--- .../pump/insight/LocalInsightPlugin.java | 22 ++++---- .../androidaps/receivers/AutoStartReceiver.kt | 10 ++-- .../androidaps/utils/AndroidPermission.kt | 13 +++-- .../services/AlarmSoundServiceHelper.kt | 13 ++--- .../utils/protection/PasswordCheck.kt | 26 ++++----- 10 files changed, 82 insertions(+), 122 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e0e2a6b05b..861ee368ca 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" package="info.nightscout.androidaps"> + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index 0c27aeac44..6b075a1b0f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -7,7 +7,6 @@ import android.app.PendingIntent; import android.app.TaskStackBuilder; import android.content.Context; import android.content.Intent; -import android.os.Build; import android.os.SystemClock; import androidx.core.app.NotificationCompat; @@ -185,12 +184,12 @@ public class LoopPlugin extends PluginBase implements LoopInterface { .observeOn(Schedulers.io()) .subscribe(event -> invoke("EventTempTargetChange", true), fabricPrivacy::logException) ); - /** - * This method is triggered once autosens calculation has completed, so the LoopPlugin - * has current data to work with. However, autosens calculation can be triggered by multiple - * sources and currently only a new BG should trigger a loop run. Hence we return early if - * the event causing the calculation is not EventNewBg. - *

+ /* + This method is triggered once autosens calculation has completed, so the LoopPlugin + has current data to work with. However, autosens calculation can be triggered by multiple + sources and currently only a new BG should trigger a loop run. Hence we return early if + the event causing the calculation is not EventNewBg. +

*/ disposable.add(rxBus .toObservable(EventAutosensCalculationFinished.class) @@ -212,15 +211,12 @@ public class LoopPlugin extends PluginBase implements LoopInterface { } private void createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - - NotificationManager mNotificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - @SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID, - CHANNEL_ID, - NotificationManager.IMPORTANCE_HIGH); - mNotificationManager.createNotificationChannel(channel); - } + NotificationManager mNotificationManager = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + @SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID, + CHANNEL_ID, + NotificationManager.IMPORTANCE_HIGH); + mNotificationManager.createNotificationChannel(channel); } @Override @@ -240,10 +236,6 @@ public class LoopPlugin extends PluginBase implements LoopInterface { } } - public long suspendedTo() { - return loopSuspendedTill; - } - public void suspendTo(long endTime) { loopSuspendedTill = endTime; isSuperBolus = false; @@ -341,8 +333,9 @@ public class LoopPlugin extends PluginBase implements LoopInterface { } return isDisconnected; } + public boolean treatmentTimethreshold(int duartionMinutes) { - long threshold = System.currentTimeMillis() + (duartionMinutes*60*1000); + long threshold = System.currentTimeMillis() + (duartionMinutes * 60 * 1000); boolean bool = false; if (treatmentsPlugin.getLastBolusTime() > threshold || treatmentsPlugin.getLastCarbTime() > threshold) bool = true; @@ -414,7 +407,7 @@ public class LoopPlugin extends PluginBase implements LoopInterface { // safety check for multiple SMBs long lastBolusTime = treatmentsPlugin.getLastBolusTime(); if (lastBolusTime != 0 && lastBolusTime + T.mins(3).msecs() > System.currentTimeMillis()) { - getAapsLogger().debug(LTag.APS, "SMB requsted but still in 3 min interval"); + getAapsLogger().debug(LTag.APS, "SMB requested but still in 3 min interval"); resultAfterConstraints.smb = 0; } @@ -456,31 +449,31 @@ public class LoopPlugin extends PluginBase implements LoopInterface { && resultAfterConstraints.carbsReq >= sp.getInt(R.string.key_smb_enable_carbs_suggestions_threshold, 0) && carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimethreshold(-15)) { - if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local,true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, false)) { + if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, false)) { Notification carbreqlocal = new Notification(Notification.CARBS_REQUIRED, resultAfterConstraints.getCarbsRequiredText(), Notification.NORMAL); rxBus.send(new EventNewNotification(carbreqlocal)); } if (sp.getBoolean(R.string.key_ns_create_announcements_from_carbs_req, false)) { nsUpload.uploadError(resultAfterConstraints.getCarbsRequiredText()); } - if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local,true) && sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, false)){ + if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, false)) { Intent intentAction5m = new Intent(context, CarbSuggestionReceiver.class); intentAction5m.putExtra("ignoreDuration", 5); PendingIntent pendingIntent5m = PendingIntent.getBroadcast(context, 1, intentAction5m, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Action actionIgnore5m = new - NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore5m,"Ignore 5m"), pendingIntent5m); + NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore5m, "Ignore 5m"), pendingIntent5m); Intent intentAction15m = new Intent(context, CarbSuggestionReceiver.class); intentAction15m.putExtra("ignoreDuration", 15); PendingIntent pendingIntent15m = PendingIntent.getBroadcast(context, 1, intentAction15m, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Action actionIgnore15m = new - NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore15m,"Ignore 15m"), pendingIntent15m); + NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore15m, "Ignore 15m"), pendingIntent15m); Intent intentAction30m = new Intent(context, CarbSuggestionReceiver.class); intentAction30m.putExtra("ignoreDuration", 30); PendingIntent pendingIntent30m = PendingIntent.getBroadcast(context, 1, intentAction30m, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Action actionIgnore30m = new - NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore30m,"Ignore 30m"), pendingIntent30m); + NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore30m, "Ignore 30m"), pendingIntent30m); NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID); builder.setSmallIcon(R.drawable.notif_icon) @@ -511,7 +504,7 @@ public class LoopPlugin extends PluginBase implements LoopInterface { } else { //If carbs were required previously, but are no longer needed, dismiss notifications - if ( prevCarbsreq > 0 ) { + if (prevCarbsreq > 0) { dismissSuggestion(); rxBus.send(new EventDismissNotification(Notification.CARBS_REQUIRED)); } @@ -591,8 +584,8 @@ public class LoopPlugin extends PluginBase implements LoopInterface { } } - public void disableCarbSuggestions(int duartionMinutes) { - carbsSuggestionsSuspendedUntil = System.currentTimeMillis() + (duartionMinutes*60*1000); + public void disableCarbSuggestions(int durationMinutes) { + carbsSuggestionsSuspendedUntil = System.currentTimeMillis() + (durationMinutes * 60 * 1000); dismissSuggestion(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt index af530665f0..eefaa2963e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt @@ -85,6 +85,7 @@ class OpenHumansUploader @Inject constructor( } private val openHumansAPI = OpenHumansAPI(OPEN_HUMANS_URL, CLIENT_ID, CLIENT_SECRET, REDIRECT_URL) + @Suppress("PrivatePropertyName") private val FILE_NAME_DATE_FORMAT = SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.US).apply { timeZone = TimeZone.getTimeZone("UTC") } private var isSetup @@ -126,12 +127,12 @@ class OpenHumansUploader @Inject constructor( private val appId: UUID get() { val id = sp.getStringOrNull("openhumans_appid", null) - if (id == null) { + return if (id == null) { val generated = UUID.randomUUID() sp.putString("openhumans_appid", generated.toString()) - return generated + generated } else { - return UUID.fromString(id) + UUID.fromString(id) } } @@ -140,7 +141,7 @@ class OpenHumansUploader @Inject constructor( private val wakeLock = (context.getSystemService(Context.POWER_SERVICE) as PowerManager) .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS::OpenHumans") - val preferenceChangeDisposable = CompositeDisposable() + private val preferenceChangeDisposable = CompositeDisposable() override fun onStart() { super.onStart() @@ -453,7 +454,8 @@ class OpenHumansUploader @Inject constructor( aapsLogger.error(LTag.OHUPLOADER, "Segmental upload exceptional", it) } - fun uploadData(maxEntries: Long?): Completable = gatherData(maxEntries) + @Suppress("SameParameterValue") + private fun uploadData(maxEntries: Long?): Completable = gatherData(maxEntries) .flatMap { data -> refreshAccessTokensIfNeeded().map { accessToken -> accessToken to data } } .flatMap { uploadFile(it.first, it.second).andThen(Single.just(it.second)) } .flatMapCompletable { @@ -616,14 +618,12 @@ class OpenHumansUploader @Inject constructor( } private fun setupNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val notificationManagerCompat = NotificationManagerCompat.from(context) - notificationManagerCompat.createNotificationChannel(NotificationChannel( - NOTIFICATION_CHANNEL, - resourceHelper.gs(R.string.open_humans), - NotificationManager.IMPORTANCE_DEFAULT - )) - } + val notificationManagerCompat = NotificationManagerCompat.from(context) + notificationManagerCompat.createNotificationChannel(NotificationChannel( + NOTIFICATION_CHANNEL, + resourceHelper.gs(R.string.open_humans), + NotificationManager.IMPORTANCE_DEFAULT + )) } private class UploadData( @@ -633,6 +633,7 @@ class OpenHumansUploader @Inject constructor( val highestQueueId: Long? ) + @Suppress("PrivatePropertyName") private val HEX_DIGITS = "0123456789ABCDEF".toCharArray() private fun ByteArray.toHexString(): String { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt index 35fd71c6e8..9d23950e53 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt @@ -8,7 +8,6 @@ import android.content.Context import android.content.Intent import android.media.AudioManager import android.media.RingtoneManager -import android.os.Build import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -132,14 +131,12 @@ class NotificationStore @Inject constructor( } fun createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - usesChannels = true - val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - @SuppressLint("WrongConstant") val channel = NotificationChannel(CHANNEL_ID, - CHANNEL_ID, - NotificationManager.IMPORTANCE_HIGH) - mNotificationManager.createNotificationChannel(channel) - } + usesChannels = true + val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + @SuppressLint("WrongConstant") val channel = NotificationChannel(CHANNEL_ID, + CHANNEL_ID, + NotificationManager.IMPORTANCE_HIGH) + mNotificationManager.createNotificationChannel(channel) } @Synchronized @@ -162,16 +159,6 @@ class NotificationStore @Inject constructor( return clone } - /* - private fun unSnooze() { - if (sp.getBoolean(R.string.key_nsalarm_staledata, false)) { - val notification = Notification(Notification.NSALARM, resourceHelper.gs(R.string.nsalarm_staledata), Notification.URGENT) - sp.putLong(R.string.key_snoozedTo, System.currentTimeMillis()) - add(notification) - aapsLogger.debug(LTag.NOTIFICATION, "Snoozed to current time and added back notification!") - } - } - */ inner class NotificationRecyclerViewAdapter internal constructor(private val notificationsList: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): NotificationsViewHolder { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt index 20bb7a010a..385247ce43 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt @@ -5,7 +5,6 @@ import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent -import android.os.Build import androidx.core.app.NotificationCompat import androidx.core.app.RemoteInput import androidx.core.app.TaskStackBuilder @@ -106,11 +105,9 @@ class PersistentNotificationPlugin @Inject constructor( } private fun createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - val channel = NotificationChannel(notificationHolder.channelID, notificationHolder.channelID as CharSequence, NotificationManager.IMPORTANCE_HIGH) - mNotificationManager.createNotificationChannel(channel) - } + val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val channel = NotificationChannel(notificationHolder.channelID, notificationHolder.channelID as CharSequence, NotificationManager.IMPORTANCE_HIGH) + mNotificationManager.createNotificationChannel(channel) } override fun onStop() { @@ -121,10 +118,7 @@ class PersistentNotificationPlugin @Inject constructor( private fun triggerNotificationUpdate() { updateNotification() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - context.startForegroundService(Intent(context, DummyService::class.java)) - else - context.startService(Intent(context, DummyService::class.java)) + context.startForegroundService(Intent(context, DummyService::class.java)) } private fun updateNotification() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java index c02404ff69..2459c7a4fa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java @@ -6,7 +6,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -57,7 +56,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.common.ManufacturerType; import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction; import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; -import info.nightscout.androidaps.queue.commands.CustomCommand; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue; import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; @@ -135,6 +133,7 @@ import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_erro import info.nightscout.androidaps.plugins.pump.insight.utils.ExceptionTranslator; import info.nightscout.androidaps.plugins.pump.insight.utils.ParameterBlockUtil; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.queue.commands.CustomCommand; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.TimeChangeType; import info.nightscout.androidaps.utils.resources.ResourceHelper; @@ -294,12 +293,10 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface, } private void createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - NotificationChannel channel = new NotificationChannel(ALERT_CHANNEL_ID, resourceHelper.gs(R.string.insight_alert_notification_channel), NotificationManager.IMPORTANCE_HIGH); - channel.setSound(null, null); - notificationManager.createNotificationChannel(channel); - } + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + NotificationChannel channel = new NotificationChannel(ALERT_CHANNEL_ID, resourceHelper.gs(R.string.insight_alert_notification_channel), NotificationManager.IMPORTANCE_HIGH); + channel.setSound(null, null); + notificationManager.createNotificationChannel(channel); } @Override @@ -600,7 +597,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface, bolusMessage.setDuration(0); bolusMessage.setExtendedAmount(0); bolusMessage.setImmediateAmount(insulin); - bolusMessage.setVibration(sp.getBoolean(detailedBolusInfo.isSMB ? R.string.key_disable_vibration_auto : R.string.key_disable_vibration ,false)); + bolusMessage.setVibration(sp.getBoolean(detailedBolusInfo.isSMB ? R.string.key_disable_vibration_auto : R.string.key_disable_vibration, false)); bolusID = connectionService.requestMessage(bolusMessage).await().getBolusId(); bolusCancelled = false; } @@ -724,8 +721,8 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface, PumpEnactResult cancelTBRResult = cancelTempBasalOnly(); if (cancelTBRResult.success) { PumpEnactResult ebResult = setExtendedBolusOnly((absoluteRate - getBaseBasalRate()) / 60D - * ((double) durationInMinutes), durationInMinutes, - sp.getBoolean(R.string.key_disable_vibration_auto,false)); + * ((double) durationInMinutes), durationInMinutes, + sp.getBoolean(R.string.key_disable_vibration_auto, false)); if (ebResult.success) { result.success = true; result.enacted = true; @@ -803,7 +800,8 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface, @NonNull @Override public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { PumpEnactResult result = cancelExtendedBolusOnly(); - if (result.success) result = setExtendedBolusOnly(insulin, durationInMinutes, sp.getBoolean(R.string.key_disable_vibration,false)); + if (result.success) + result = setExtendedBolusOnly(insulin, durationInMinutes, sp.getBoolean(R.string.key_disable_vibration, false)); try { fetchStatus(); readHistory(); diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/AutoStartReceiver.kt b/app/src/main/java/info/nightscout/androidaps/receivers/AutoStartReceiver.kt index 7b2eb03f96..1260299f09 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/AutoStartReceiver.kt +++ b/app/src/main/java/info/nightscout/androidaps/receivers/AutoStartReceiver.kt @@ -3,16 +3,12 @@ package info.nightscout.androidaps.receivers import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.os.Build import info.nightscout.androidaps.plugins.general.persistentNotification.DummyService class AutoStartReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { - if (intent.action == Intent.ACTION_BOOT_COMPLETED) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - context.startForegroundService(Intent(context, DummyService::class.java)) - else - context.startService(Intent(context, DummyService::class.java)) - } + if (intent.action == Intent.ACTION_BOOT_COMPLETED) + context.startForegroundService(Intent(context, DummyService::class.java)) } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt index b2d294da1a..a2afdb1c19 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt @@ -35,6 +35,7 @@ class AndroidPermission @Inject constructor( ) { companion object { + const val CASE_STORAGE = 0x1 const val CASE_SMS = 0x2 const val CASE_LOCATION = 0x3 @@ -103,13 +104,11 @@ class AndroidPermission @Inject constructor( rxBus.send(EventNewNotification(notification)) } else rxBus.send(EventDismissNotification(Notification.PERMISSION_SMS)) // Following is a bug in Android 8 - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) { - if (permissionNotGranted(activity, Manifest.permission.READ_PHONE_STATE)) { - val notification = NotificationWithAction(injector, Notification.PERMISSION_PHONESTATE, resourceHelper.gs(R.string.smscommunicator_missingphonestatepermission), Notification.URGENT) - notification.action(R.string.request, Runnable { askForPermission(activity, arrayOf(Manifest.permission.READ_PHONE_STATE), CASE_PHONE_STATE) }) - rxBus.send(EventNewNotification(notification)) - } else rxBus.send(EventDismissNotification(Notification.PERMISSION_PHONESTATE)) - } + if (permissionNotGranted(activity, Manifest.permission.READ_PHONE_STATE)) { + val notification = NotificationWithAction(injector, Notification.PERMISSION_PHONESTATE, resourceHelper.gs(R.string.smscommunicator_missingphonestatepermission), Notification.URGENT) + notification.action(R.string.request, Runnable { askForPermission(activity, arrayOf(Manifest.permission.READ_PHONE_STATE), CASE_PHONE_STATE) }) + rxBus.send(EventNewNotification(notification)) + } else rxBus.send(EventDismissNotification(Notification.PERMISSION_PHONESTATE)) } } diff --git a/core/src/main/java/info/nightscout/androidaps/services/AlarmSoundServiceHelper.kt b/core/src/main/java/info/nightscout/androidaps/services/AlarmSoundServiceHelper.kt index 243dcb5872..a01106c5b0 100644 --- a/core/src/main/java/info/nightscout/androidaps/services/AlarmSoundServiceHelper.kt +++ b/core/src/main/java/info/nightscout/androidaps/services/AlarmSoundServiceHelper.kt @@ -6,6 +6,7 @@ import android.content.Intent import android.content.ServiceConnection import android.os.Build import android.os.IBinder +import androidx.annotation.RequiresApi import info.nightscout.androidaps.interfaces.NotificationHolderInterface import javax.inject.Inject import javax.inject.Singleton @@ -20,6 +21,7 @@ import javax.inject.Singleton Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{e317f7e u0 info.nightscout.nsclient/info.nightscout.androidaps.services.AlarmSoundService} */ +@RequiresApi(Build.VERSION_CODES.O) @Singleton class AlarmSoundServiceHelper @Inject constructor( private val notificationHolder: NotificationHolderInterface @@ -33,10 +35,7 @@ class AlarmSoundServiceHelper @Inject constructor( val alarmSoundService: AlarmSoundService = binder.getService() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - context.startForegroundService(getServiceIntent(context, sound)) - else - context.startService(getServiceIntent(context, sound)) + context.startForegroundService(getServiceIntent(context, sound)) // This is the key: Without waiting Android Framework to call this method // inside Service.onCreate(), immediately call here to post the notification. @@ -47,7 +46,6 @@ class AlarmSoundServiceHelper @Inject constructor( } override fun onServiceDisconnected(name: ComponentName?) { - TODO("Not yet implemented") } } @@ -58,10 +56,7 @@ class AlarmSoundServiceHelper @Inject constructor( // Just call startForegroundService instead since we cannot bind a service to a // broadcast receiver context. The service also have to call startForeground in // this case. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - context.startForegroundService(getServiceIntent(context, sound)) - else - context.startService(getServiceIntent(context, sound)) + context.startForegroundService(getServiceIntent(context, sound)) } } diff --git a/core/src/main/java/info/nightscout/androidaps/utils/protection/PasswordCheck.kt b/core/src/main/java/info/nightscout/androidaps/utils/protection/PasswordCheck.kt index 79e270f012..1efe3a9ff6 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/protection/PasswordCheck.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/protection/PasswordCheck.kt @@ -7,6 +7,7 @@ import android.view.LayoutInflater import android.view.View import android.widget.EditText import android.widget.TextView +import androidx.annotation.RequiresApi import androidx.annotation.StringRes import info.nightscout.androidaps.core.R import info.nightscout.androidaps.utils.CryptoUtil @@ -19,6 +20,7 @@ import javax.inject.Singleton // since androidx.autofill.HintConstants are not available const val AUTOFILL_HINT_NEW_PASSWORD = "newPassword" +@RequiresApi(Build.VERSION_CODES.O) @Singleton class PasswordCheck @Inject constructor( val sp: SP, @@ -45,11 +47,9 @@ class PasswordCheck @Inject constructor( userInput2.visibility = View.GONE - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val autoFillHintPasswordKind = context.getString(preference) - userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}") - userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES - } + val autoFillHintPasswordKind = context.getString(preference) + userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}") + userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES alertDialogBuilder .setCancelable(false) @@ -80,11 +80,9 @@ class PasswordCheck @Inject constructor( val userInput = promptsView.findViewById(R.id.password_prompt_pass) as EditText val userInput2 = promptsView.findViewById(R.id.password_prompt_pass_confirm) as EditText - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val autoFillHintPasswordKind = context.getString(preference) - userInput.setAutofillHints(AUTOFILL_HINT_NEW_PASSWORD, "aaps_${autoFillHintPasswordKind}") - userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES - } + val autoFillHintPasswordKind = context.getString(preference) + userInput.setAutofillHints(AUTOFILL_HINT_NEW_PASSWORD, "aaps_${autoFillHintPasswordKind}") + userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES alertDialogBuilder .setCancelable(false) @@ -145,11 +143,9 @@ class PasswordCheck @Inject constructor( userInput2.visibility = View.GONE - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val autoFillHintPasswordKind = context.getString(preference) - userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}") - userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES - } + val autoFillHintPasswordKind = context.getString(preference) + userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}") + userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES alertDialogBuilder .setCancelable(false) From d40559d44409d4b65df4e6f7e40d05409210113d Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sat, 16 Jan 2021 18:36:57 +0100 Subject: [PATCH 15/61] LocationServiceHelper --- .../general/automation/AutomationPlugin.kt | 33 ++++------ .../androidaps/services/LocationService.kt | 14 ++++- .../services/LocationServiceHelper.kt | 62 +++++++++++++++++++ 3 files changed, 87 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/services/LocationServiceHelper.kt diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt index 1ec46d6131..ca3ce0d3be 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt @@ -1,8 +1,6 @@ package info.nightscout.androidaps.plugins.general.automation import android.content.Context -import android.content.Intent -import android.os.Build import android.os.Handler import android.os.HandlerThread import android.os.SystemClock @@ -27,7 +25,7 @@ import info.nightscout.androidaps.plugins.general.automation.events.EventAutomat import info.nightscout.androidaps.plugins.general.automation.triggers.* import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished import info.nightscout.androidaps.queue.Callback -import info.nightscout.androidaps.services.LocationService +import info.nightscout.androidaps.services.LocationServiceHelper import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T @@ -55,6 +53,7 @@ class AutomationPlugin @Inject constructor( private val rxBus: RxBusWrapper, private val constraintChecker: ConstraintChecker, aapsLogger: AAPSLogger, + private val locationServiceHelper: LocationServiceHelper, private val dateUtil: DateUtil ) : PluginBase(PluginDescription() .mainType(PluginType.GENERAL) @@ -91,10 +90,7 @@ class AutomationPlugin @Inject constructor( } override fun onStart() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - context.startForegroundService(Intent(context, LocationService::class.java)) - else - context.startService(Intent(context, LocationService::class.java)) + locationServiceHelper.startService(context) super.onStart() loadFromSP() @@ -105,17 +101,14 @@ class AutomationPlugin @Inject constructor( .observeOn(Schedulers.io()) .subscribe({ e -> if (e.isChanged(resourceHelper, R.string.key_location)) { - context.stopService(Intent(context, LocationService::class.java)) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - context.startForegroundService(Intent(context, LocationService::class.java)) - else - context.startService(Intent(context, LocationService::class.java)) + locationServiceHelper.stopService(context) + locationServiceHelper.startService(context) } - }, { fabricPrivacy.logException(it) }) + }, fabricPrivacy::logException) disposable += rxBus .toObservable(EventAutomationDataChanged::class.java) .observeOn(Schedulers.io()) - .subscribe({ storeToSP() }, { fabricPrivacy.logException(it) }) + .subscribe({ storeToSP() }, fabricPrivacy::logException) disposable += rxBus .toObservable(EventLocationChange::class.java) .observeOn(Schedulers.io()) @@ -124,19 +117,19 @@ class AutomationPlugin @Inject constructor( aapsLogger.debug(LTag.AUTOMATION, "Grabbed location: $it.location.latitude $it.location.longitude Provider: $it.location.provider") processActions() } - }, { fabricPrivacy.logException(it) }) + }, fabricPrivacy::logException) disposable += rxBus .toObservable(EventChargingState::class.java) .observeOn(Schedulers.io()) - .subscribe({ processActions() }, { fabricPrivacy.logException(it) }) + .subscribe({ processActions() }, fabricPrivacy::logException) disposable += rxBus .toObservable(EventNetworkChange::class.java) .observeOn(Schedulers.io()) - .subscribe({ processActions() }, { fabricPrivacy.logException(it) }) + .subscribe({ processActions() }, fabricPrivacy::logException) disposable += rxBus .toObservable(EventAutosensCalculationFinished::class.java) .observeOn(Schedulers.io()) - .subscribe({ processActions() }, { fabricPrivacy.logException(it) }) + .subscribe({ processActions() }, fabricPrivacy::logException) disposable += rxBus .toObservable(EventBTChange::class.java) .observeOn(Schedulers.io()) @@ -144,13 +137,13 @@ class AutomationPlugin @Inject constructor( aapsLogger.debug(LTag.AUTOMATION, "Grabbed new BT event: $it") btConnects.add(it) processActions() - }, { fabricPrivacy.logException(it) }) + }, fabricPrivacy::logException) } override fun onStop() { disposable.clear() loopHandler.removeCallbacks(refreshLoop) - context.stopService(Intent(context, LocationService::class.java)) + locationServiceHelper.stopService(context) super.onStop() } diff --git a/app/src/main/java/info/nightscout/androidaps/services/LocationService.kt b/app/src/main/java/info/nightscout/androidaps/services/LocationService.kt index 2357dcebeb..fe2d02ba66 100644 --- a/app/src/main/java/info/nightscout/androidaps/services/LocationService.kt +++ b/app/src/main/java/info/nightscout/androidaps/services/LocationService.kt @@ -1,3 +1,5 @@ +@file:Suppress("PrivatePropertyName") + package info.nightscout.androidaps.services import android.Manifest @@ -8,6 +10,7 @@ import android.content.Intent import android.content.pm.PackageManager import android.location.Location import android.location.LocationManager +import android.os.Binder import android.os.Bundle import android.os.IBinder import androidx.core.app.ActivityCompat @@ -44,9 +47,18 @@ class LocationService : DaggerService() { private val LOCATION_INTERVAL_PASSIVE = T.mins(1).msecs() // this doesn't cost more power companion object { + private const val LOCATION_DISTANCE = 10f } + inner class LocalBinder : Binder() { + + fun getService(): LocationService = this@LocationService + } + + private val binder = LocalBinder() + override fun onBind(intent: Intent): IBinder = binder + inner class LocationListener internal constructor(val provider: String) : android.location.LocationListener { init { @@ -148,8 +160,6 @@ class LocationService : DaggerService() { disposable.clear() } - override fun onBind(intent: Intent?): IBinder? = null - private fun initializeLocationManager() { aapsLogger.debug(LTag.LOCATION, "initializeLocationManager - Provider: " + sp.getString(R.string.key_location, "NONE")) if (locationManager == null) { diff --git a/app/src/main/java/info/nightscout/androidaps/services/LocationServiceHelper.kt b/app/src/main/java/info/nightscout/androidaps/services/LocationServiceHelper.kt new file mode 100644 index 0000000000..3767d0c2a2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/services/LocationServiceHelper.kt @@ -0,0 +1,62 @@ +package info.nightscout.androidaps.services + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.os.IBinder +import info.nightscout.androidaps.interfaces.NotificationHolderInterface +import javax.inject.Inject +import javax.inject.Singleton + +/* + This code replaces following + val intent = Intent(context, LocationService::class.java) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) context.startForegroundService(intent) else context.startService(intent) + + it fails randomly with error + Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{e317f7e u0 info.nightscout.nsclient/info.nightscout.androidaps.services.LocationService} + + */ +@Singleton +class LocationServiceHelper @Inject constructor( + private val notificationHolder: NotificationHolderInterface +) { + + fun startService(context: Context) { + val connection = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName?, service: IBinder?) { + // The binder of the service that returns the instance that is created. + val binder = service as LocationService.LocalBinder + + val locationService: LocationService = binder.getService() + + context.startForegroundService(Intent(context, LocationService::class.java)) + + // This is the key: Without waiting Android Framework to call this method + // inside Service.onCreate(), immediately call here to post the notification. + locationService.startForeground(notificationHolder.notificationID, notificationHolder.notification) + + // Release the connection to prevent leaks. + context.unbindService(this) + } + + override fun onServiceDisconnected(name: ComponentName?) { + } + } + + try { + context.bindService(Intent(context, LocationService::class.java), connection, Context.BIND_AUTO_CREATE) + } catch (ignored: RuntimeException) { + // This is probably a broadcast receiver context even though we are calling getApplicationContext(). + // Just call startForegroundService instead since we cannot bind a service to a + // broadcast receiver context. The service also have to call startForeground in + // this case. + context.startForegroundService(Intent(context, LocationService::class.java)) + } + } + + fun stopService(context: Context) = + context.stopService(Intent(context, LocationService::class.java)) + +} \ No newline at end of file From 6f08626e320c747fcd13227261b105d72f3ad909 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sat, 16 Jan 2021 18:48:04 +0100 Subject: [PATCH 16/61] prevent empty string --- .../androidaps/dialogs/ProfileViewerDialog.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt index 504fcd28aa..b9223dd1e0 100644 --- a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt +++ b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt @@ -190,8 +190,8 @@ class ProfileViewerDialog : DaggerDialogFragment() { } private fun basals(profile1: Profile, profile2: Profile): Spanned { - var prev1 = 0.0 - var prev2 = 0.0 + var prev1 = -1.0 + var prev2 = -1.0 val s = StringBuilder() for (hour in 0..23) { val val1 = profile1.getBasalTimeFromMidnight(hour * 60 * 60) @@ -213,8 +213,8 @@ class ProfileViewerDialog : DaggerDialogFragment() { } private fun ics(profile1: Profile, profile2: Profile): Spanned { - var prev1 = 0.0 - var prev2 = 0.0 + var prev1 = -1.0 + var prev2 = -1.0 val s = StringBuilder() for (hour in 0..23) { val val1 = profile1.getIcTimeFromMidnight(hour * 60 * 60) @@ -230,8 +230,8 @@ class ProfileViewerDialog : DaggerDialogFragment() { } private fun isfs(profile1: Profile, profile2: Profile): Spanned { - var prev1 = 0.0 - var prev2 = 0.0 + var prev1 = -1.0 + var prev2 = -1.0 val units = profileFunction.getUnits() val s = StringBuilder() for (hour in 0..23) { @@ -248,10 +248,10 @@ class ProfileViewerDialog : DaggerDialogFragment() { } private fun targets(profile1: Profile, profile2: Profile):Spanned { - var prev1l = 0.0 - var prev1h = 0.0 - var prev2l = 0.0 - var prev2h = 0.0 + var prev1l = -1.0 + var prev1h = -1.0 + var prev2l = -1.0 + var prev2h = -1.0 val units = profileFunction.getUnits() val s = StringBuilder() for (hour in 0..23) { From 8a683ee5714f2e0be7c45891db0056be29c4ff44 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 17 Jan 2021 13:15:23 +0100 Subject: [PATCH 17/61] fix test --- .../nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt index 09729850e0..1b93fed0cf 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt @@ -1,5 +1,6 @@ package info.nightscout.androidaps.plugins.aps.loop +import android.app.NotificationManager import android.content.Context import dagger.Lazy import dagger.android.AndroidInjector @@ -52,7 +53,7 @@ class LoopPluginTest : TestBase() { @Mock lateinit var fabricPrivacy: FabricPrivacy @Mock lateinit var receiverStatusStore: ReceiverStatusStore @Mock lateinit var nsUpload: NSUpload - + @Mock lateinit var notificationManager: NotificationManager private lateinit var hardLimits: HardLimits lateinit var loopPlugin: LoopPlugin @@ -63,6 +64,7 @@ class LoopPluginTest : TestBase() { loopPlugin = LoopPlugin(injector, aapsLogger, rxBus, sp, Config(), constraintChecker, resourceHelper, profileFunction, context, commandQueue, activePlugin, treatmentsPlugin, virtualPumpPlugin, actionStringHandler, iobCobCalculatorPlugin, receiverStatusStore, fabricPrivacy, nsUpload, hardLimits) `when`(activePlugin.activePump).thenReturn(virtualPumpPlugin) + `when`(context.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(notificationManager) } @Test From 68faba89513dbb42b3ba25d471735a77f15c7db2 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 17 Jan 2021 13:23:59 +0100 Subject: [PATCH 18/61] DummyServiceHelper --- .../persistentNotification/DummyService.kt | 11 +++- .../DummyServiceHelper.kt | 66 +++++++++++++++++++ .../PersistentNotificationPlugin.kt | 46 ++++++------- .../androidaps/receivers/AutoStartReceiver.kt | 11 ++-- 4 files changed, 106 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyServiceHelper.kt diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.kt index ecca16c581..6d45fcd721 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.kt @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.persistentNotification import android.app.Notification import android.app.Service import android.content.Intent +import android.os.Binder import android.os.IBinder import dagger.android.DaggerService import info.nightscout.androidaps.events.EventAppExit @@ -27,7 +28,13 @@ class DummyService : DaggerService() { private val disposable = CompositeDisposable() - override fun onBind(intent: Intent?): IBinder? = null + inner class LocalBinder : Binder() { + + fun getService(): DummyService = this@DummyService + } + + private val binder = LocalBinder() + override fun onBind(intent: Intent): IBinder = binder override fun onCreate() { super.onCreate() @@ -44,7 +51,7 @@ class DummyService : DaggerService() { .subscribe({ aapsLogger.debug(LTag.CORE, "EventAppExit received") stopSelf() - }, fabricPrivacy::logException ) + }, fabricPrivacy::logException) ) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyServiceHelper.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyServiceHelper.kt new file mode 100644 index 0000000000..d1adfc00ed --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyServiceHelper.kt @@ -0,0 +1,66 @@ +package info.nightscout.androidaps.plugins.general.persistentNotification + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.os.Build +import android.os.IBinder +import androidx.annotation.RequiresApi +import info.nightscout.androidaps.interfaces.NotificationHolderInterface +import javax.inject.Inject +import javax.inject.Singleton + +/* + This code replaces following + val alarm = Intent(context, DummyService::class.java) + alarm.putExtra("soundid", n.soundId) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) context.startForegroundService(alarm) else context.startService(alarm) + + it fails randomly with error + Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{e317f7e u0 info.nightscout.nsclient/info.nightscout.androidaps.services.DummyService} + + */ +@RequiresApi(Build.VERSION_CODES.O) +@Singleton +class DummyServiceHelper @Inject constructor( + private val notificationHolder: NotificationHolderInterface +) { + + fun startService(context: Context) { + val connection = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName?, service: IBinder?) { + // The binder of the service that returns the instance that is created. + val binder: DummyService.LocalBinder = service as DummyService.LocalBinder + + val dummyService: DummyService = binder.getService() + + context.startForegroundService(Intent(context, DummyService::class.java)) + + // This is the key: Without waiting Android Framework to call this method + // inside Service.onCreate(), immediately call here to post the notification. + dummyService.startForeground(notificationHolder.notificationID, notificationHolder.notification) + + // Release the connection to prevent leaks. + context.unbindService(this) + } + + override fun onServiceDisconnected(name: ComponentName?) { + } + } + + try { + context.bindService(Intent(context, DummyService::class.java), connection, Context.BIND_AUTO_CREATE) + } catch (ignored: RuntimeException) { + // This is probably a broadcast receiver context even though we are calling getApplicationContext(). + // Just call startForegroundService instead since we cannot bind a service to a + // broadcast receiver context. The service also have to call startForeground in + // this case. + context.startForegroundService(Intent(context, DummyService::class.java)) + } + } + + fun stopService(context: Context) { + context.stopService(Intent(context, DummyService::class.java)) + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt index 385247ce43..c5ee21253e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt @@ -30,18 +30,20 @@ import io.reactivex.schedulers.Schedulers import javax.inject.Inject import javax.inject.Singleton +@Suppress("PrivatePropertyName") @Singleton class PersistentNotificationPlugin @Inject constructor( injector: HasAndroidInjector, aapsLogger: AAPSLogger, resourceHelper: ResourceHelper, - private var profileFunction: ProfileFunction, - private var fabricPrivacy: FabricPrivacy, - private var activePlugins: ActivePluginProvider, - private var iobCobCalculatorPlugin: IobCobCalculatorPlugin, - private var rxBus: RxBusWrapper, - private var context: Context, - private var notificationHolder: NotificationHolder, + private val profileFunction: ProfileFunction, + private val fabricPrivacy: FabricPrivacy, + private val activePlugins: ActivePluginProvider, + private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, + private val rxBus: RxBusWrapper, + private val context: Context, + private val notificationHolder: NotificationHolder, + private val dummyServiceHelper: DummyServiceHelper, private val iconsProvider: IconsProvider, private val databaseHelper: DatabaseHelperInterface ) : PluginBase(PluginDescription() @@ -112,13 +114,13 @@ class PersistentNotificationPlugin @Inject constructor( override fun onStop() { disposable.clear() - context.stopService(Intent(context, DummyService::class.java)) + dummyServiceHelper.stopService(context) super.onStop() } private fun triggerNotificationUpdate() { updateNotification() - context.startForegroundService(Intent(context, DummyService::class.java)) + dummyServiceHelper.startService(context) } private fun updateNotification() { @@ -128,31 +130,31 @@ class PersistentNotificationPlugin @Inject constructor( var line3: String? = null var unreadConversationBuilder: NotificationCompat.CarExtender.UnreadConversation.Builder? = null if (profileFunction.isProfileValid("Notification")) { - var line1_aa: String + var line1aa: String val units = profileFunction.getUnits() val lastBG = iobCobCalculatorPlugin.lastBg() val glucoseStatus = GlucoseStatus(injector).glucoseStatusData if (lastBG != null) { - line1_aa = lastBG.valueToUnitsToString(units) - line1 = line1_aa + line1aa = lastBG.valueToUnitsToString(units) + line1 = line1aa if (glucoseStatus != null) { line1 += (" Δ" + Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " avgΔ" + Profile.toSignedUnitsString(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units)) - line1_aa += " " + lastBG.directionToSymbol(databaseHelper) + line1aa += " " + lastBG.directionToSymbol(databaseHelper) } else { line1 += " " + resourceHelper.gs(R.string.old_data) + " " - line1_aa += "$line1." + line1aa += "$line1." } } else { - line1_aa = resourceHelper.gs(R.string.missed_bg_readings) - line1 = line1_aa + line1aa = resourceHelper.gs(R.string.missed_bg_readings) + line1 = line1aa } val activeTemp = activePlugins.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis()) if (activeTemp != null) { line1 += " " + activeTemp.toStringShort() - line1_aa += " " + activeTemp.toStringShort() + "." + line1aa += " " + activeTemp.toStringShort() + "." } //IOB activePlugins.activeTreatments.updateTotalIOBTreatments() @@ -160,11 +162,11 @@ class PersistentNotificationPlugin @Inject constructor( val bolusIob = activePlugins.activeTreatments.lastCalculationTreatments.round() val basalIob = activePlugins.activeTreatments.lastCalculationTempBasals.round() line2 = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculatorPlugin.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() - val line2_aa = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculatorPlugin.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + "." + val line2aa = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculatorPlugin.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + "." line3 = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h" - var line3_aa = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h." + var line3aa = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h." line3 += " - " + profileFunction.getProfileName() - line3_aa += " - " + profileFunction.getProfileName() + "." + line3aa += " - " + profileFunction.getProfileName() + "." /// For Android Auto val msgReadIntent = Intent() .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) @@ -188,12 +190,12 @@ class PersistentNotificationPlugin @Inject constructor( // Build a RemoteInput for receiving voice input from devices val remoteInput = RemoteInput.Builder(EXTRA_VOICE_REPLY).build() // Create the UnreadConversation - unreadConversationBuilder = NotificationCompat.CarExtender.UnreadConversation.Builder(line1_aa + "\n" + line2_aa) + unreadConversationBuilder = NotificationCompat.CarExtender.UnreadConversation.Builder(line1aa + "\n" + line2aa) .setLatestTimestamp(System.currentTimeMillis()) .setReadPendingIntent(msgReadPendingIntent) .setReplyAction(msgReplyPendingIntent, remoteInput) /// Add dot to produce a "more natural sounding result" - unreadConversationBuilder.addMessage(line3_aa) + unreadConversationBuilder.addMessage(line3aa) /// End Android Auto } else { line1 = resourceHelper.gs(R.string.noprofileset) diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/AutoStartReceiver.kt b/app/src/main/java/info/nightscout/androidaps/receivers/AutoStartReceiver.kt index 1260299f09..782a23d2de 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/AutoStartReceiver.kt +++ b/app/src/main/java/info/nightscout/androidaps/receivers/AutoStartReceiver.kt @@ -1,14 +1,17 @@ package info.nightscout.androidaps.receivers -import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import info.nightscout.androidaps.plugins.general.persistentNotification.DummyService +import dagger.android.DaggerBroadcastReceiver +import info.nightscout.androidaps.plugins.general.persistentNotification.DummyServiceHelper -class AutoStartReceiver : BroadcastReceiver() { +class AutoStartReceiver constructor( + private val dummyServiceHelper: DummyServiceHelper +) : DaggerBroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { + super.onReceive(context, intent) if (intent.action == Intent.ACTION_BOOT_COMPLETED) - context.startForegroundService(Intent(context, DummyService::class.java)) + dummyServiceHelper.startService(context) } } \ No newline at end of file From 3f561943dc3f59c8374d273ac4705963de61fc14 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 17 Jan 2021 15:46:03 +0100 Subject: [PATCH 19/61] avoid ConcurrentModificationException --- .../androidaps/plugins/general/automation/AutomationPlugin.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt index ca3ce0d3be..5e95d6773d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt @@ -193,7 +193,9 @@ class AutomationPlugin @Inject constructor( } aapsLogger.debug(LTag.AUTOMATION, "processActions") - for (event in automationEvents) { + val iterator = automationEvents.iterator() + while (iterator.hasNext()) { + val event = iterator.next() if (event.isEnabled && event.shouldRun() && event.trigger.shouldRun() && event.getPreconditions().shouldRun()) { if (event.systemAction || userEventsEnabled) { val actions = event.actions From 270b6623ea93e63c577798b60c9f1aee21ab3ca4 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 18 Jan 2021 11:06:37 +0100 Subject: [PATCH 20/61] prevent IndexOutOfBoundsException --- .../activities/ProfileHelperActivity.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt index efb7e57b19..5476d29519 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt @@ -221,13 +221,15 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() { } private fun getProfile(age: Double, tdd: Double, weight: Double, basalPct: Double, tab: Int): Profile? = - when (typeSelected[tab]) { - ProfileType.MOTOL_DEFAULT -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits()) - ProfileType.DPV_DEFAULT -> defaultProfileDPV.profile(age, tdd, basalPct, profileFunction.getUnits()) - ProfileType.CURRENT -> profileFunction.getProfile()?.convertToNonCustomizedProfile() - ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileInterface.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString()) - ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile() - } + try { // profile must not exist + when (typeSelected[tab]) { + ProfileType.MOTOL_DEFAULT -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits()) + ProfileType.DPV_DEFAULT -> defaultProfileDPV.profile(age, tdd, basalPct, profileFunction.getUnits()) + ProfileType.CURRENT -> profileFunction.getProfile()?.convertToNonCustomizedProfile() + ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileInterface.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString()) + ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile() + } + } catch (e: Exception) { null } private fun getProfileName(age: Double, tdd: Double, weight: Double, basalSumPct: Double, tab: Int): String = when (typeSelected[tab]) { From 3f18f94c797e5f1a4d465fd0b57424042d8ed691 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 18 Jan 2021 11:41:29 +0100 Subject: [PATCH 21/61] fix RunningConfiguration.kt --- .../configBuilder/RunningConfiguration.kt | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt b/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt index 3eb4d2ab94..4d5f08cb4d 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt @@ -51,33 +51,40 @@ class RunningConfiguration @Inject constructor( // called in NSClient mode only fun apply(configuration: JSONObject) { - val insulin = InsulinInterface.InsulinType.fromInt(JsonHelper.safeGetInt(configuration, "insulin", InsulinInterface.InsulinType.UNKNOWN.value)) - for (p in activePlugin.getSpecificPluginsListByInterface(InsulinInterface::class.java)) { - val insulinPlugin = p as InsulinInterface - if (insulinPlugin.id == insulin) { - if (!p.isEnabled()) { - aapsLogger.debug(LTag.CORE, "Changing insulin plugin to ${insulin.name}") - configBuilder.performPluginSwitch(p, true, PluginType.INSULIN) + if (configuration.has("insulin")) { + val insulin = InsulinInterface.InsulinType.fromInt(JsonHelper.safeGetInt(configuration, "insulin", InsulinInterface.InsulinType.UNKNOWN.value)) + for (p in activePlugin.getSpecificPluginsListByInterface(InsulinInterface::class.java)) { + val insulinPlugin = p as InsulinInterface + if (insulinPlugin.id == insulin) { + if (!p.isEnabled()) { + aapsLogger.debug(LTag.CORE, "Changing insulin plugin to ${insulin.name}") + configBuilder.performPluginSwitch(p, true, PluginType.INSULIN) + } + insulinPlugin.applyConfiguration(configuration.getJSONObject("insulinConfiguration")) } - insulinPlugin.applyConfiguration(configuration.getJSONObject("insulinConfiguration")) } } - val sensitivity = SensitivityInterface.SensitivityType.fromInt(JsonHelper.safeGetInt(configuration, "sensitivity", SensitivityInterface.SensitivityType.UNKNOWN.value)) - for (p in activePlugin.getSpecificPluginsListByInterface(SensitivityInterface::class.java)) { - val sensitivityPlugin = p as SensitivityInterface - if (sensitivityPlugin.id == sensitivity) { - if (!p.isEnabled()) { - aapsLogger.debug(LTag.CORE, "Changing sensitivity plugin to ${sensitivity.name}") - configBuilder.performPluginSwitch(p, true, PluginType.SENSITIVITY) + if (configuration.has("sensitivity")) { + val sensitivity = SensitivityInterface.SensitivityType.fromInt(JsonHelper.safeGetInt(configuration, "sensitivity", SensitivityInterface.SensitivityType.UNKNOWN.value)) + for (p in activePlugin.getSpecificPluginsListByInterface(SensitivityInterface::class.java)) { + val sensitivityPlugin = p as SensitivityInterface + if (sensitivityPlugin.id == sensitivity) { + if (!p.isEnabled()) { + aapsLogger.debug(LTag.CORE, "Changing sensitivity plugin to ${sensitivity.name}") + configBuilder.performPluginSwitch(p, true, PluginType.SENSITIVITY) + } + sensitivityPlugin.applyConfiguration(configuration.getJSONObject("sensitivityConfiguration")) } - sensitivityPlugin.applyConfiguration(configuration.getJSONObject("sensitivityConfiguration")) } } - val pumpType = JsonHelper.safeGetString(configuration, "pump", PumpType.GenericAAPS.description) - sp.putString(R.string.key_virtualpump_type, pumpType) - activePlugin.activePump.pumpDescription.setPumpDescription(PumpType.getByDescription(pumpType)) + if (configuration.has("pump")) { + val pumpType = JsonHelper.safeGetString(configuration, "pump", PumpType.GenericAAPS.description) + sp.putString(R.string.key_virtualpump_type, pumpType) + activePlugin.activePump.pumpDescription.setPumpDescription(PumpType.getByDescription(pumpType)) + aapsLogger.debug(LTag.CORE, "Changing pump type to ${pumpType}") + } if (configuration.has("overviewConfiguration")) activePlugin.activeOverview.applyConfiguration(configuration.getJSONObject("overviewConfiguration")) From 65a39d91be93fd436c130eb84bb510bb325e4767 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 18 Jan 2021 17:36:18 +0100 Subject: [PATCH 22/61] refactor import/export to create DaggerAppCompatActivityWithResult --- .../java/info/nightscout/androidaps/Config.kt | 4 +- .../nightscout/androidaps/MainActivity.kt | 16 +- .../activities/SingleFragmentActivity.kt | 13 +- .../dependencyInjection/ActivitiesModule.kt | 2 - .../dependencyInjection/AppModule.kt | 2 + .../dependencyInjection/PreferencesModule.kt | 2 - .../objectives/objectives/Objective.java | 7 +- .../general/maintenance/ImportExportPrefs.kt | 53 ++- .../maintenance/MaintenanceFragment.kt | 3 +- .../androidaps/setupwizard/SWDefinition.kt | 4 +- .../setupwizard/SetupWizardActivity.kt | 11 +- app/src/main/res/values/colors.xml | 4 - app/src/main/res/values/objectives.xml | 12 - app/src/main/res/values/strings.xml | 48 --- .../DaggerAppCompatActivityWithResult.kt | 17 + .../activities/NoSplashAppCompatActivity.kt | 4 +- .../androidaps/core/di/CoreFragmentsModule.kt | 2 + .../androidaps/interfaces/ConfigInterface.kt | 2 + .../interfaces/ImportExportPrefsInterface.kt | 15 + .../versionChecker/VersionCheckerUtils.kt | 11 +- .../maintenance/PrefFileListProvider.kt | 396 ++++++++---------- .../plugins/general/maintenance/PrefsFile.kt | 21 + .../general/maintenance/PrefsFileContract.kt | 27 ++ .../maintenance/PrefsFormatsHandler.kt | 6 + .../general/maintenance/PrefsImportDir.kt | 6 + .../activities/PrefImportListActivity.kt | 5 +- .../maintenance/formats/ClassicPrefsFormat.kt | 3 +- .../formats/EncryptedPrefsFormat.kt | 3 +- .../maintenance/formats/PrefsFormat.kt | 7 +- .../androidaps/utils/storage/FileStrorage.kt | 32 +- .../androidaps/utils/storage/Storage.kt | 22 +- .../src/main/res/drawable/ic_meta_date.xml | 16 +- .../main/res/drawable/ic_meta_encryption.xml | 16 +- .../src/main/res/drawable/ic_meta_error.xml | 18 +- .../src/main/res/drawable/ic_meta_flavour.xml | 16 +- .../src/main/res/drawable/ic_meta_format.xml | 16 +- .../src/main/res/drawable/ic_meta_model.xml | 16 +- .../src/main/res/drawable/ic_meta_name.xml | 16 +- .../src/main/res/drawable/ic_meta_ok.xml | 0 .../src/main/res/drawable/ic_meta_version.xml | 16 +- .../src/main/res/drawable/ic_meta_warning.xml | 18 +- .../maintenance_importlist_activity.xml | 0 .../layout/maintenance_importlist_item.xml | 0 core/src/main/res/values/colors.xml | 5 + core/src/main/res/values/strings.xml | 77 +++- 45 files changed, 491 insertions(+), 499 deletions(-) create mode 100644 core/src/main/java/info/nightscout/androidaps/activities/DaggerAppCompatActivityWithResult.kt create mode 100644 core/src/main/java/info/nightscout/androidaps/interfaces/ImportExportPrefsInterface.kt rename {app => core}/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt (96%) rename {app => core}/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt (78%) create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFile.kt create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFileContract.kt create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFormatsHandler.kt create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsImportDir.kt rename {app => core}/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt (97%) rename {app => core}/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/ClassicPrefsFormat.kt (98%) rename {app => core}/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt (99%) rename {app => core}/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt (97%) rename {app => core}/src/main/java/info/nightscout/androidaps/utils/storage/FileStrorage.kt (95%) rename {app => core}/src/main/java/info/nightscout/androidaps/utils/storage/Storage.kt (79%) rename {app => core}/src/main/res/drawable/ic_meta_date.xml (98%) rename {app => core}/src/main/res/drawable/ic_meta_encryption.xml (98%) rename {app => core}/src/main/res/drawable/ic_meta_error.xml (98%) rename {app => core}/src/main/res/drawable/ic_meta_flavour.xml (98%) rename {app => core}/src/main/res/drawable/ic_meta_format.xml (99%) rename {app => core}/src/main/res/drawable/ic_meta_model.xml (98%) rename {app => core}/src/main/res/drawable/ic_meta_name.xml (98%) rename {app => core}/src/main/res/drawable/ic_meta_ok.xml (100%) rename {app => core}/src/main/res/drawable/ic_meta_version.xml (99%) rename {app => core}/src/main/res/drawable/ic_meta_warning.xml (97%) rename {app => core}/src/main/res/layout/maintenance_importlist_activity.xml (100%) rename {app => core}/src/main/res/layout/maintenance_importlist_item.xml (100%) diff --git a/app/src/main/java/info/nightscout/androidaps/Config.kt b/app/src/main/java/info/nightscout/androidaps/Config.kt index c5edf0c438..036474f58d 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.kt +++ b/app/src/main/java/info/nightscout/androidaps/Config.kt @@ -5,11 +5,13 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class Config @Inject constructor(): ConfigInterface{ +class Config @Inject constructor() : ConfigInterface { override val SUPPORTEDNSVERSION = 1002 // 0.10.00 override val APS = BuildConfig.FLAVOR == "full" override val NSCLIENT = BuildConfig.FLAVOR == "nsclient" || BuildConfig.FLAVOR == "nsclient2" override val PUMPCONTROL = BuildConfig.FLAVOR == "pumpcontrol" override val PUMPDRIVERS = BuildConfig.FLAVOR == "full" || BuildConfig.FLAVOR == "pumpcontrol" + override val FLAVOR = BuildConfig.FLAVOR + override val VERSION_NAME = BuildConfig.VERSION_NAME } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.kt b/app/src/main/java/info/nightscout/androidaps/MainActivity.kt index b07111ed3b..91b22d72e7 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.kt @@ -47,8 +47,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils -import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs -import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.setupwizard.SetupWizardActivity @@ -92,18 +90,11 @@ class MainActivity : NoSplashAppCompatActivity() { @Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var signatureVerifierPlugin: SignatureVerifierPlugin @Inject lateinit var config: Config - @Inject lateinit var importExportPrefs: ImportExportPrefs private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle private var pluginPreferencesMenuItem: MenuItem? = null private var menu: Menu? = null - val callForPrefFile = registerForActivityResult(PrefsFileContract()) { - it?.let { - importExportPrefs.importSharedPreferences(this, it) - } - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Iconify.with(FontAwesomeModule()) @@ -203,10 +194,9 @@ class MainActivity : NoSplashAppCompatActivity() { if (p.isEnabled() && p.hasFragment() && !p.isFragmentVisible() && !p.pluginDescription.neverVisible) { val menuItem = menu.add(p.name) menuItem.isCheckable = true - if(p.menuIcon != -1) { + if (p.menuIcon != -1) { menuItem.setIcon(p.menuIcon) - } else - { + } else { menuItem.setIcon(R.drawable.ic_settings) } menuItem.setOnMenuItemClickListener { @@ -283,7 +273,7 @@ class MainActivity : NoSplashAppCompatActivity() { } override fun onCreateOptionsMenu(menu: Menu): Boolean { - this.menu = menu + this.menu = menu menuInflater.inflate(R.menu.menu_main, menu) pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences) setPluginPreferenceMenuName() diff --git a/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.kt index 862509249e..9b01150122 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.kt @@ -5,29 +5,20 @@ import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem -import dagger.android.support.DaggerAppCompatActivity import info.nightscout.androidaps.R import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.plugins.configBuilder.PluginStore -import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs -import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract import info.nightscout.androidaps.utils.locale.LocaleHelper import info.nightscout.androidaps.utils.protection.ProtectionCheck import javax.inject.Inject -class SingleFragmentActivity : DaggerAppCompatActivity() { +class SingleFragmentActivity : DaggerAppCompatActivityWithResult() { + @Inject lateinit var pluginStore: PluginStore @Inject lateinit var protectionCheck: ProtectionCheck - @Inject lateinit var importExportPrefs: ImportExportPrefs private var plugin: PluginBase? = null - val callForPrefFile = registerForActivityResult(PrefsFileContract()) { - it?.let { - importExportPrefs.importSharedPreferences(this, it) - } - } - public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_single_fragment) diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ActivitiesModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ActivitiesModule.kt index f6790caa25..54f139f0e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ActivitiesModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ActivitiesModule.kt @@ -6,7 +6,6 @@ import info.nightscout.androidaps.MainActivity import info.nightscout.androidaps.activities.* import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity -import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansLoginActivity import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity import info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity @@ -40,7 +39,6 @@ abstract class ActivitiesModule { @ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity @ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity @ContributesAndroidInjector abstract fun contributesDefaultProfileActivity(): ProfileHelperActivity - @ContributesAndroidInjector abstract fun contributesPrefImportListActivity(): PrefImportListActivity @ContributesAndroidInjector abstract fun contributesOpenHumansLoginActivity(): OpenHumansLoginActivity } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt index 4fb00e9bb5..3acf9d9297 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt @@ -12,6 +12,7 @@ import info.nightscout.androidaps.db.DatabaseHelperProvider import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.PluginStore +import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.queue.CommandQueue @@ -58,5 +59,6 @@ open class AppModule { @Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface @Binds fun bindUploadQueueInterface(uploadQueue: UploadQueue): UploadQueueInterface @Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolder): NotificationHolderInterface + @Binds fun bindImportExportPrefsInterface(importExportPrefs: ImportExportPrefs): ImportExportPrefsInterface } } diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PreferencesModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PreferencesModule.kt index 39fb959c15..738f53872a 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PreferencesModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PreferencesModule.kt @@ -2,7 +2,6 @@ package info.nightscout.androidaps.dependencyInjection import dagger.Module import dagger.android.ContributesAndroidInjector -import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider import info.nightscout.androidaps.plugins.general.maintenance.formats.ClassicPrefsFormat import info.nightscout.androidaps.plugins.general.maintenance.formats.EncryptedPrefsFormat @@ -13,7 +12,6 @@ import info.nightscout.androidaps.utils.CryptoUtil abstract class PreferencesModule { @ContributesAndroidInjector abstract fun cryptoUtilInjector(): CryptoUtil - @ContributesAndroidInjector abstract fun importExportPrefsInjector(): ImportExportPrefs @ContributesAndroidInjector abstract fun encryptedPrefsFormatInjector(): EncryptedPrefsFormat @ContributesAndroidInjector abstract fun classicPrefsFormatInjector(): ClassicPrefsFormat @ContributesAndroidInjector abstract fun prefImportListProviderInjector(): PrefFileListProvider diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java index feef4a4222..95942c4ed2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; -import android.app.Activity; import android.content.Context; import android.graphics.Color; import android.text.util.Linkify; @@ -185,9 +184,9 @@ public abstract class Objective { int days = (int) Math.floor((double) duration / T.days(1).msecs()); int hours = (int) Math.floor((double) duration / T.hours(1).msecs()); int minutes = (int) Math.floor((double) duration / T.mins(1).msecs()); - if (days > 0) return resourceHelper.gq(R.plurals.objective_days, days, days); - else if (hours > 0) return resourceHelper.gq(R.plurals.objective_hours, hours, hours); - else return resourceHelper.gq(R.plurals.objective_minutes, minutes, minutes); + if (days > 0) return resourceHelper.gq(R.plurals.days, days, days); + else if (hours > 0) return resourceHelper.gq(R.plurals.hours, hours, hours); + else return resourceHelper.gq(R.plurals.minutes, minutes, minutes); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.kt index d114aaa72c..17693ec7ef 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.kt @@ -12,16 +12,15 @@ import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import info.nightscout.androidaps.BuildConfig -import info.nightscout.androidaps.MainActivity import info.nightscout.androidaps.R +import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult import info.nightscout.androidaps.activities.PreferencesActivity -import info.nightscout.androidaps.activities.SingleFragmentActivity import info.nightscout.androidaps.events.EventAppExit +import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.maintenance.formats.* -import info.nightscout.androidaps.setupwizard.SetupWizardActivity import info.nightscout.androidaps.utils.AndroidPermission import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.ToastUtils @@ -40,6 +39,7 @@ import java.io.IOException import java.util.* import javax.inject.Inject import javax.inject.Singleton +import kotlin.system.exitProcess /** * Created by mike on 03.07.2016. @@ -57,19 +57,17 @@ class ImportExportPrefs @Inject constructor( private val classicPrefsFormat: ClassicPrefsFormat, private val encryptedPrefsFormat: EncryptedPrefsFormat, private val prefFileList: PrefFileListProvider -) { +) : ImportExportPrefsInterface { - val TAG = LTag.CORE - - fun prefsFileExists(): Boolean { + override fun prefsFileExists(): Boolean { return prefFileList.listPreferenceFiles().size > 0 } - fun exportSharedPreferences(f: Fragment) { + override fun exportSharedPreferences(f: Fragment) { f.activity?.let { exportSharedPreferences(it) } } - fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable) { + override fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable) { fragment.context?.let { ctx -> val permission = ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE) @@ -119,8 +117,7 @@ class ImportExportPrefs @Inject constructor( // name we detect from OS val systemName = n1 ?: n2 ?: n3 ?: n4 ?: n5 ?: n6 ?: defaultPatientName - val name = if (patientName.isNotEmpty() && patientName != defaultPatientName) patientName else systemName - return name + return if (patientName.isNotEmpty() && patientName != defaultPatientName) patientName else systemName } private fun prefsEncryptionIsDisabled() = @@ -134,6 +131,7 @@ class ImportExportPrefs @Inject constructor( }) } + @Suppress("SameParameterValue") private fun askForEncryptionPass(activity: FragmentActivity, @StringRes canceledMsg: Int, @StringRes passwordName: Int, @StringRes passwordExplanation: Int?, @StringRes passwordWarning: Int?, then: ((password: String) -> Unit)) { passwordCheck.queryAnyPassword(activity, passwordName, R.string.key_master_password, passwordExplanation, passwordWarning, { password -> @@ -143,6 +141,7 @@ class ImportExportPrefs @Inject constructor( }) } + @Suppress("SameParameterValue") private fun askForMasterPassIfNeeded(activity: FragmentActivity, @StringRes canceledMsg: Int, then: ((password: String) -> Unit)) { if (prefsEncryptionIsDisabled()) { then("") @@ -239,49 +238,45 @@ class ImportExportPrefs @Inject constructor( ToastUtils.okToast(activity, resourceHelper.gs(R.string.exported)) } catch (e: FileNotFoundException) { ToastUtils.errorToast(activity, resourceHelper.gs(R.string.filenotfound) + " " + newFile) - log.error(TAG, "Unhandled exception", e) + log.error(LTag.CORE, "Unhandled exception", e) } catch (e: IOException) { ToastUtils.errorToast(activity, e.message) - log.error(TAG, "Unhandled exception", e) + log.error(LTag.CORE, "Unhandled exception", e) } catch (e: PrefFileNotFoundError) { ToastUtils.Long.errorToast(activity, resourceHelper.gs(R.string.preferences_export_canceled) + "\n\n" + resourceHelper.gs(R.string.filenotfound) + ": " + e.message + "\n\n" + resourceHelper.gs(R.string.needstoragepermission)) - log.error(TAG, "File system exception", e) + log.error(LTag.CORE, "File system exception", e) } catch (e: PrefIOError) { ToastUtils.Long.errorToast(activity, resourceHelper.gs(R.string.preferences_export_canceled) + "\n\n" + resourceHelper.gs(R.string.needstoragepermission) + ": " + e.message) - log.error(TAG, "File system exception", e) + log.error(LTag.CORE, "File system exception", e) } } } - fun importSharedPreferences(fragment: Fragment) { + override fun importSharedPreferences(fragment: Fragment) { fragment.activity?.let { fragmentAct -> importSharedPreferences(fragmentAct) } } - fun importSharedPreferences(activity: FragmentActivity) { + override fun importSharedPreferences(activity: FragmentActivity) { try { - if (activity is SingleFragmentActivity) - activity.callForPrefFile.launch(null) - if (activity is MainActivity) - activity.callForPrefFile.launch(null) - if (activity is SetupWizardActivity) + if (activity is DaggerAppCompatActivityWithResult) activity.callForPrefFile.launch(null) } catch (e: IllegalArgumentException) { // this exception happens on some early implementations of ActivityResult contracts // when registered and called for the second time ToastUtils.errorToast(activity, resourceHelper.gs(R.string.goto_main_try_again)) - log.error(TAG, "Internal android framework exception", e) + log.error(LTag.CORE, "Internal android framework exception", e) } } - fun importSharedPreferences(activity: FragmentActivity, importFile: PrefsFile) { + override fun importSharedPreferences(activity: FragmentActivity, importFile: PrefsFile) { askToConfirmImport(activity, importFile) { password -> @@ -301,7 +296,7 @@ class ImportExportPrefs @Inject constructor( promptForDecryptionPasswordIfNeeded(activity, prefsAttempted, importOkAttempted, format, importFile) { prefs, importOk -> // if at end we allow to import preferences - val importPossible = (importOk || buildHelper.isEngineeringMode()) && (prefs.values.size > 0) + val importPossible = (importOk || buildHelper.isEngineeringMode()) && (prefs.values.isNotEmpty()) PrefImportSummaryDialog.showSummary(activity, importOk, importPossible, prefs, { if (importPossible) { @@ -325,9 +320,9 @@ class ImportExportPrefs @Inject constructor( } catch (e: PrefFileNotFoundError) { ToastUtils.errorToast(activity, resourceHelper.gs(R.string.filenotfound) + " " + importFile) - log.error(TAG, "Unhandled exception", e) + log.error(LTag.CORE, "Unhandled exception", e) } catch (e: PrefIOError) { - log.error(TAG, "Unhandled exception", e) + log.error(LTag.CORE, "Unhandled exception", e) ToastUtils.errorToast(activity, e.message) } } @@ -346,13 +341,13 @@ class ImportExportPrefs @Inject constructor( private fun restartAppAfterImport(context: Context) { sp.putBoolean(R.string.key_setupwizard_processed, true) show(context, resourceHelper.gs(R.string.setting_imported), resourceHelper.gs(R.string.restartingapp), Runnable { - log.debug(TAG, "Exiting") + log.debug(LTag.CORE, "Exiting") rxBus.send(EventAppExit()) if (context is AppCompatActivity) { context.finish() } System.runFinalization() - System.exit(0) + exitProcess(0) }) } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt index a0ca451fee..921cf19327 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup import dagger.android.support.DaggerFragment import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface import info.nightscout.androidaps.plugins.general.food.FoodPlugin import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin @@ -23,7 +24,7 @@ class MaintenanceFragment : DaggerFragment() { @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var foodPlugin: FoodPlugin - @Inject lateinit var importExportPrefs: ImportExportPrefs + @Inject lateinit var importExportPrefs: ImportExportPrefsInterface override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.maintenance_fragment, container, false) diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt index 755a033576..4aa72c3054 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt @@ -11,6 +11,7 @@ import info.nightscout.androidaps.dialogs.ProfileSwitchDialog import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin @@ -18,7 +19,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragment import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin -import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService @@ -55,7 +55,7 @@ class SWDefinition @Inject constructor( private val loopPlugin: LoopPlugin, private val nsClientPlugin: NSClientPlugin, private val nsProfilePlugin: NSProfilePlugin, - private val importExportPrefs: ImportExportPrefs, + private val importExportPrefs: ImportExportPrefsInterface, private val androidPermission: AndroidPermission, private val cryptoUtil: CryptoUtil, private val config: Config diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.kt b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.kt index bd68fb98a0..262a38e634 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.kt @@ -14,8 +14,6 @@ import info.nightscout.androidaps.events.EventProfileNeedsUpdate import info.nightscout.androidaps.events.EventProfileStoreChanged import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs -import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange @@ -44,7 +42,6 @@ class SetupWizardActivity : NoSplashAppCompatActivity() { @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var sp: SP @Inject lateinit var fabricPrivacy: FabricPrivacy - @Inject lateinit var importExportPrefs: ImportExportPrefs private val disposable = CompositeDisposable() private lateinit var screens: List @@ -52,12 +49,6 @@ class SetupWizardActivity : NoSplashAppCompatActivity() { private val intentMessage = "WIZZARDPAGE" - val callForPrefFile = registerForActivityResult(PrefsFileContract()) { - it?.let { - importExportPrefs.importSharedPreferences(this, it) - } - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) update(applicationContext) @@ -213,7 +204,7 @@ class SetupWizardActivity : NoSplashAppCompatActivity() { if (permissions.isNotEmpty()) { if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) { when (requestCode) { - AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted + AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted show(this, resourceHelper.gs(R.string.permission), resourceHelper.gs(R.string.alert_dialog_storage_permission_text)) AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY -> { diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e0547a25f9..40c97ed6eb 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -64,10 +64,6 @@ #2E2E2E - #77dd77 - #FF8C00 - #FF5555 - #FFFFFF #BBBBBB diff --git a/app/src/main/res/values/objectives.xml b/app/src/main/res/values/objectives.xml index 0a4fa6c2cf..cf4dfd2c7a 100644 --- a/app/src/main/res/values/objectives.xml +++ b/app/src/main/res/values/objectives.xml @@ -66,16 +66,4 @@ Failed retrieve time Objective requirements not met - - %1$d day - %1$d days - - - %1$d hour - %1$d hours - - - %1$d minute - %1$d minutes - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8817f5c20d..e89fdb1795 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -204,8 +204,6 @@ This file was exported and encrypted with different master password. Provide old master password to decrypt file. As a result of successful import current master password WILL BE REPLACED with that old master password! - Select file to import - Please check preferences before importing: Preferences cannot be imported! Preferences should not be imported! @@ -214,45 +212,6 @@ Import Import anyway (DANGEROUS!) - Preferences were created with different variant of AAPS (%1$s) while you have: %2$s.\n\nSome settings may be missing or invalid - after importing please check and update your preferences. - Preferences were created on a different device. It is OK if you are importing from older/different phone, but make sure imported preferences are correct! - You are using the outdated legacy format from old versions of AAPS, which is not secure! Only use it as a last resort, if you do not have an export in current, JSON format. - Imported preferences are already %1$s days old! Maybe you have more up-to-date preferences or you choose the wrong file? Remember to export preferences regularly! - Invalid date-time format! - Preferences from different minor version of application. It is OK if you are importing after upgrade, but check after import if preferences are still correct! - Preferences from different major version of application. Major versions differ significantly and may have incompatible preferences! Make sure after import that preferences are still correct! - - File format - Created at - AAPS Version - Build Variant - Exporting device patient name - Exporting device model - File encryption - - Old export format - New encrypted format - New debug format (unencrypted) - Unknown export format - - Settings file tampered - Settings file is secure - Using not secure, unencrypted settings format - JSON format error, missing required field (format, content, metadata or security) - Decryption error, the given password cannot decrypt the file - - File checksum (hash) missing, cannot verify the authenticity of settings! - File was modified after export! - Decryption error, parsing preferences failed! - Decryption error, the provided password is invalid or settings file was modified! It may happen that the imported file was exported with a different Master password. - Missing encryption configuration, settings format is invalid! - Unsupported or not specified encryption algorithm! - - exported %1$s ago - exported at %1$s - exported less than hour ago - in directory: %1$s - End User License Agreement MUST NOT BE USED TO MAKE MEDICAL DECISIONS. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. I UNDERSTAND AND AGREE @@ -977,7 +936,6 @@ Log settings Reset to defaults NSClient malfunction. Consider NS and NSClient restart. - Version %1$s available Time offset aps_mode Preferred APS mode @@ -1158,12 +1116,6 @@ COPY Add new Version Checker - last_time_this_version_detected - last_versionchecker_waring - last_versionchecker_plugin_waring - last_revoked_certs_check - Signature verifier - We have detected that you are running an invalid version. Loop disabled! old version very old version diff --git a/core/src/main/java/info/nightscout/androidaps/activities/DaggerAppCompatActivityWithResult.kt b/core/src/main/java/info/nightscout/androidaps/activities/DaggerAppCompatActivityWithResult.kt new file mode 100644 index 0000000000..fb124926f3 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/activities/DaggerAppCompatActivityWithResult.kt @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.activities + +import dagger.android.support.DaggerAppCompatActivity +import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface +import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract +import javax.inject.Inject + +open class DaggerAppCompatActivityWithResult : DaggerAppCompatActivity() { + + @Inject lateinit var importExportPrefs: ImportExportPrefsInterface + + val callForPrefFile = registerForActivityResult(PrefsFileContract()) { + it?.let { + importExportPrefs.importSharedPreferences(this, it) + } + } +} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt b/core/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt index 6ded8b95b5..78e2e009e3 100644 --- a/core/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt +++ b/core/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt @@ -2,12 +2,10 @@ package info.nightscout.androidaps.activities import android.content.Context import android.os.Bundle -import dagger.android.support.DaggerAppCompatActivity import info.nightscout.androidaps.core.R import info.nightscout.androidaps.utils.locale.LocaleHelper -//@Suppress("registered") -open class NoSplashAppCompatActivity : DaggerAppCompatActivity() { +open class NoSplashAppCompatActivity : DaggerAppCompatActivityWithResult() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/core/src/main/java/info/nightscout/androidaps/core/di/CoreFragmentsModule.kt b/core/src/main/java/info/nightscout/androidaps/core/di/CoreFragmentsModule.kt index 43bfc39cca..35ab98ff52 100644 --- a/core/src/main/java/info/nightscout/androidaps/core/di/CoreFragmentsModule.kt +++ b/core/src/main/java/info/nightscout/androidaps/core/di/CoreFragmentsModule.kt @@ -9,11 +9,13 @@ import info.nightscout.androidaps.dialogs.BolusProgressDialog import info.nightscout.androidaps.dialogs.ErrorDialog import info.nightscout.androidaps.dialogs.NtpProgressDialog import info.nightscout.androidaps.dialogs.ProfileViewerDialog +import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity @Module @Suppress("unused") abstract class CoreFragmentsModule { + @ContributesAndroidInjector abstract fun contributesPrefImportListActivity(): PrefImportListActivity @ContributesAndroidInjector abstract fun contributesTDDStatsActivity(): TDDStatsActivity @ContributesAndroidInjector abstract fun contributeBolusProgressHelperActivity(): BolusProgressHelperActivity @ContributesAndroidInjector abstract fun contributeErrorHelperActivity(): ErrorHelperActivity diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/ConfigInterface.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/ConfigInterface.kt index b5071628b5..693dd64988 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/ConfigInterface.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/ConfigInterface.kt @@ -6,4 +6,6 @@ interface ConfigInterface { val NSCLIENT: Boolean val PUMPCONTROL: Boolean val PUMPDRIVERS: Boolean + val FLAVOR: String + val VERSION_NAME: String } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/ImportExportPrefsInterface.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/ImportExportPrefsInterface.kt new file mode 100644 index 0000000000..3212b80a87 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/ImportExportPrefsInterface.kt @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.interfaces + +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import info.nightscout.androidaps.plugins.general.maintenance.PrefsFile + +interface ImportExportPrefsInterface { + + fun importSharedPreferences(activity: FragmentActivity, importFile: PrefsFile) + fun importSharedPreferences(activity: FragmentActivity) + fun importSharedPreferences(fragment: Fragment) + fun prefsFileExists(): Boolean + fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable) + fun exportSharedPreferences(f: Fragment) +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt b/core/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt index 64bb5980c3..a3df7d43c6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtils.kt @@ -2,9 +2,8 @@ package info.nightscout.androidaps.plugins.constraints.versionChecker import android.content.Context import android.net.ConnectivityManager -import info.nightscout.androidaps.BuildConfig -import info.nightscout.androidaps.MainApp -import info.nightscout.androidaps.R +import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.interfaces.ConfigInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBusWrapper @@ -24,6 +23,7 @@ class VersionCheckerUtils @Inject constructor( val sp: SP, val resourceHelper: ResourceHelper, val rxBus: RxBusWrapper, + private val config: ConfigInterface, val context: Context ) { @@ -50,7 +50,7 @@ class VersionCheckerUtils @Inject constructor( Thread { try { val version: String? = findVersion(URL("https://raw.githubusercontent.com/nightscout/AndroidAPS/master/app/build.gradle").readText()) - compareWithCurrentVersion(version, BuildConfig.VERSION_NAME) + compareWithCurrentVersion(version, config.VERSION_NAME) } catch (e: IOException) { aapsLogger.error(LTag.CORE, "Github master version check error: $e") } @@ -130,6 +130,7 @@ class VersionCheckerUtils @Inject constructor( } companion object { + private val CHECK_EVERY = TimeUnit.DAYS.toMillis(1) private val WARN_EVERY = TimeUnit.DAYS.toMillis(1) } @@ -148,7 +149,7 @@ fun findVersion(file: String?): String? { fun String.versionStrip() = this.mapNotNull { when (it) { in '0'..'9' -> it - '.' -> it + '.' -> it else -> null } }.joinToString(separator = "") \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt similarity index 78% rename from app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt index 691796009d..22784677ab 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt @@ -1,220 +1,178 @@ -package info.nightscout.androidaps.plugins.general.maintenance - -import android.content.Context -import android.content.Intent -import android.os.Build -import android.os.Environment -import android.os.Parcelable -import androidx.activity.result.contract.ActivityResultContract -import androidx.fragment.app.FragmentActivity -import info.nightscout.androidaps.BuildConfig -import info.nightscout.androidaps.R -import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils -import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity -import info.nightscout.androidaps.plugins.general.maintenance.formats.* -import info.nightscout.androidaps.utils.resources.ResourceHelper -import info.nightscout.androidaps.utils.storage.Storage -import kotlinx.android.parcel.Parcelize -import kotlinx.android.parcel.RawValue -import org.joda.time.DateTime -import org.joda.time.Days -import org.joda.time.Hours -import org.joda.time.LocalDateTime -import org.joda.time.format.DateTimeFormat -import java.io.File -import javax.inject.Inject -import javax.inject.Singleton - -enum class PrefsImportDir { - ROOT_DIR, - AAPS_DIR -} - -@Parcelize -data class PrefsFile( - val name: String, - val file: File, - val baseDir: File, - val dirKind: PrefsImportDir, - val handler: PrefsFormatsHandler, - - // metadata here is used only for list display - val metadata: @RawValue Map -) : Parcelable - -class PrefsFileContract : ActivityResultContract() { - - companion object { - - const val OUTPUT_PARAM = "prefs_file" - } - - override fun parseResult(resultCode: Int, intent: Intent?): PrefsFile? { - return when (resultCode) { - FragmentActivity.RESULT_OK -> intent?.getParcelableExtra(OUTPUT_PARAM) - else -> null - } - } - - override fun createIntent(context: Context, input: Void?): Intent { - return Intent(context, PrefImportListActivity::class.java) - } -} - -fun getCurrentDeviceModelString() = - Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")" - -@Singleton -class PrefFileListProvider @Inject constructor( - private val resourceHelper: ResourceHelper, - private val classicPrefsFormat: ClassicPrefsFormat, - private val encryptedPrefsFormat: EncryptedPrefsFormat, - private val storage: Storage, - private val versionCheckerUtils: VersionCheckerUtils -) { - - companion object { - - private val path = File(Environment.getExternalStorageDirectory().toString()) - private val aapsPath = File(path, "AAPS" + File.separator + "preferences") - private const val IMPORT_AGE_NOT_YET_OLD_DAYS = 60 - } - - /** - * This function tries to list possible preference files from main SDCard root dir and AAPS/preferences dir - * and tries to do quick assessment for preferences format plausibility. - * It does NOT load full metadata or is 100% accurate - it tries to do QUICK detection, based on: - * - file name and extension - * - predicted file contents - */ - fun listPreferenceFiles(loadMetadata: Boolean = false): MutableList { - val prefFiles = mutableListOf() - - // searching rood dir for legacy files - path.walk().maxDepth(1).filter { it.isFile && (it.name.endsWith(".json") || it.name.contains("Preferences")) }.forEach { - val contents = storage.getFileContents(it) - val detectedNew = encryptedPrefsFormat.isPreferencesFile(it, contents) - val detectedOld = !detectedNew && classicPrefsFormat.isPreferencesFile(it, contents) - if (detectedNew || detectedOld) { - val formatHandler = if (detectedNew) PrefsFormatsHandler.ENCRYPTED else PrefsFormatsHandler.CLASSIC - prefFiles.add(PrefsFile(it.name, it, path, PrefsImportDir.ROOT_DIR, formatHandler, metadataFor(loadMetadata, formatHandler, contents))) - } - } - - // searching dedicated dir, only for new JSON format - aapsPath.walk().filter { it.isFile && it.name.endsWith(".json") }.forEach { - val contents = storage.getFileContents(it) - if (encryptedPrefsFormat.isPreferencesFile(it, contents)) { - prefFiles.add(PrefsFile(it.name, it, aapsPath, PrefsImportDir.AAPS_DIR, PrefsFormatsHandler.ENCRYPTED, metadataFor(loadMetadata, PrefsFormatsHandler.ENCRYPTED, contents))) - } - } - - // we sort only if we have metadata to be used for that - if (loadMetadata) { - prefFiles.sortWith( - compareByDescending { it.handler } - .thenBy { it.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.status } - .thenByDescending { it.metadata[PrefsMetadataKey.CREATED_AT]?.value } - ) - } - - return prefFiles - } - - private fun metadataFor(loadMetadata: Boolean, formatHandler: PrefsFormatsHandler, contents: String): PrefMetadataMap { - if (!loadMetadata) { - return mapOf() - } - return checkMetadata(when (formatHandler) { - PrefsFormatsHandler.CLASSIC -> classicPrefsFormat.loadMetadata(contents) - PrefsFormatsHandler.ENCRYPTED -> encryptedPrefsFormat.loadMetadata(contents) - }) - } - - fun legacyFile(): File { - return File(path, resourceHelper.gs(R.string.app_name) + "Preferences") - } - - fun ensureExportDirExists() { - if (!aapsPath.exists()) { - aapsPath.mkdirs() - } - } - - fun newExportFile(): File { - val timeLocal = LocalDateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss")) - return File(aapsPath, timeLocal + "_" + BuildConfig.FLAVOR + ".json") - } - - // check metadata for known issues, change their status and add info with explanations - fun checkMetadata(metadata: Map): Map { - val meta = metadata.toMutableMap() - - meta[PrefsMetadataKey.AAPS_FLAVOUR]?.let { flavour -> - val flavourOfPrefs = flavour.value - if (flavour.value != BuildConfig.FLAVOR) { - flavour.status = PrefsStatus.WARN - flavour.info = resourceHelper.gs(R.string.metadata_warning_different_flavour, flavourOfPrefs, BuildConfig.FLAVOR) - } - } - - meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model -> - if (model.value != getCurrentDeviceModelString()) { - model.status = PrefsStatus.WARN - model.info = resourceHelper.gs(R.string.metadata_warning_different_device) - } - } - - meta[PrefsMetadataKey.CREATED_AT]?.let { createdAt -> - try { - val date1 = DateTime.parse(createdAt.value) - val date2 = DateTime.now() - - val daysOld = Days.daysBetween(date1.toLocalDate(), date2.toLocalDate()).days - - if (daysOld > IMPORT_AGE_NOT_YET_OLD_DAYS) { - createdAt.status = PrefsStatus.WARN - createdAt.info = resourceHelper.gs(R.string.metadata_warning_old_export, daysOld.toString()) - } - } catch (e: Exception) { - createdAt.status = PrefsStatus.WARN - createdAt.info = resourceHelper.gs(R.string.metadata_warning_date_format) - } - } - - meta[PrefsMetadataKey.AAPS_VERSION]?.let { version -> - val currentAppVer = versionCheckerUtils.versionDigits(BuildConfig.VERSION_NAME) - val metadataVer = versionCheckerUtils.versionDigits(version.value) - - if ((currentAppVer.size >= 2) && (metadataVer.size >= 2) && (Math.abs(currentAppVer[1] - metadataVer[1]) > 1)) { - version.status = PrefsStatus.WARN - version.info = resourceHelper.gs(R.string.metadata_warning_different_version) - } - - if ((currentAppVer.isNotEmpty()) && (metadataVer.isNotEmpty()) && (currentAppVer[0] != metadataVer[0])) { - version.status = PrefsStatus.WARN - version.info = resourceHelper.gs(R.string.metadata_urgent_different_version) - } - } - - return meta - } - - fun formatExportedAgo(utcTime: String): String { - val refTime = DateTime.now() - val itTime = DateTime.parse(utcTime) - val days = Days.daysBetween(itTime, refTime).days - val hours = Hours.hoursBetween(itTime, refTime).hours - - return if (hours == 0) { - resourceHelper.gs(R.string.exported_less_than_hour_ago) - } else if ((hours < 24) && (hours > 0)) { - resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.objective_hours, hours, hours)) - } else if ((days < IMPORT_AGE_NOT_YET_OLD_DAYS) && (days > 0)) { - resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.objective_days, days, days)) - } else { - resourceHelper.gs(R.string.exported_at, utcTime.substring(0, 10)) - } - } - +package info.nightscout.androidaps.plugins.general.maintenance + +import android.os.Build +import android.os.Environment +import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.interfaces.ConfigInterface +import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils +import info.nightscout.androidaps.plugins.general.maintenance.formats.* +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.storage.Storage +import org.joda.time.DateTime +import org.joda.time.Days +import org.joda.time.Hours +import org.joda.time.LocalDateTime +import org.joda.time.format.DateTimeFormat +import java.io.File +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.math.abs + +fun getCurrentDeviceModelString() = + Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")" + +@Singleton +class PrefFileListProvider @Inject constructor( + private val resourceHelper: ResourceHelper, + private val config: ConfigInterface, + private val classicPrefsFormat: ClassicPrefsFormat, + private val encryptedPrefsFormat: EncryptedPrefsFormat, + private val storage: Storage, + private val versionCheckerUtils: VersionCheckerUtils +) { + + companion object { + + private val path = File(Environment.getExternalStorageDirectory().toString()) + private val aapsPath = File(path, "AAPS" + File.separator + "preferences") + private const val IMPORT_AGE_NOT_YET_OLD_DAYS = 60 + } + + /** + * This function tries to list possible preference files from main SDCard root dir and AAPS/preferences dir + * and tries to do quick assessment for preferences format plausibility. + * It does NOT load full metadata or is 100% accurate - it tries to do QUICK detection, based on: + * - file name and extension + * - predicted file contents + */ + fun listPreferenceFiles(loadMetadata: Boolean = false): MutableList { + val prefFiles = mutableListOf() + + // searching rood dir for legacy files + path.walk().maxDepth(1).filter { it.isFile && (it.name.endsWith(".json") || it.name.contains("Preferences")) }.forEach { + val contents = storage.getFileContents(it) + val detectedNew = encryptedPrefsFormat.isPreferencesFile(it, contents) + val detectedOld = !detectedNew && classicPrefsFormat.isPreferencesFile(it, contents) + if (detectedNew || detectedOld) { + val formatHandler = if (detectedNew) PrefsFormatsHandler.ENCRYPTED else PrefsFormatsHandler.CLASSIC + prefFiles.add(PrefsFile(it.name, it, path, PrefsImportDir.ROOT_DIR, formatHandler, metadataFor(loadMetadata, formatHandler, contents))) + } + } + + // searching dedicated dir, only for new JSON format + aapsPath.walk().filter { it.isFile && it.name.endsWith(".json") }.forEach { + val contents = storage.getFileContents(it) + if (encryptedPrefsFormat.isPreferencesFile(it, contents)) { + prefFiles.add(PrefsFile(it.name, it, aapsPath, PrefsImportDir.AAPS_DIR, PrefsFormatsHandler.ENCRYPTED, metadataFor(loadMetadata, PrefsFormatsHandler.ENCRYPTED, contents))) + } + } + + // we sort only if we have metadata to be used for that + if (loadMetadata) { + prefFiles.sortWith( + compareByDescending { it.handler } + .thenBy { it.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.status } + .thenByDescending { it.metadata[PrefsMetadataKey.CREATED_AT]?.value } + ) + } + + return prefFiles + } + + private fun metadataFor(loadMetadata: Boolean, formatHandler: PrefsFormatsHandler, contents: String): PrefMetadataMap { + if (!loadMetadata) { + return mapOf() + } + return checkMetadata(when (formatHandler) { + PrefsFormatsHandler.CLASSIC -> classicPrefsFormat.loadMetadata(contents) + PrefsFormatsHandler.ENCRYPTED -> encryptedPrefsFormat.loadMetadata(contents) + }) + } + + fun legacyFile(): File { + return File(path, resourceHelper.gs(R.string.app_name) + "Preferences") + } + + fun ensureExportDirExists() { + if (!aapsPath.exists()) { + aapsPath.mkdirs() + } + } + + fun newExportFile(): File { + val timeLocal = LocalDateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss")) + return File(aapsPath, timeLocal + "_" + config.FLAVOR + ".json") + } + + // check metadata for known issues, change their status and add info with explanations + fun checkMetadata(metadata: Map): Map { + val meta = metadata.toMutableMap() + + meta[PrefsMetadataKey.AAPS_FLAVOUR]?.let { flavour -> + val flavourOfPrefs = flavour.value + if (flavour.value != config.FLAVOR) { + flavour.status = PrefsStatus.WARN + flavour.info = resourceHelper.gs(R.string.metadata_warning_different_flavour, flavourOfPrefs, config.FLAVOR) + } + } + + meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model -> + if (model.value != getCurrentDeviceModelString()) { + model.status = PrefsStatus.WARN + model.info = resourceHelper.gs(R.string.metadata_warning_different_device) + } + } + + meta[PrefsMetadataKey.CREATED_AT]?.let { createdAt -> + try { + val date1 = DateTime.parse(createdAt.value) + val date2 = DateTime.now() + + val daysOld = Days.daysBetween(date1.toLocalDate(), date2.toLocalDate()).days + + if (daysOld > IMPORT_AGE_NOT_YET_OLD_DAYS) { + createdAt.status = PrefsStatus.WARN + createdAt.info = resourceHelper.gs(R.string.metadata_warning_old_export, daysOld.toString()) + } + } catch (e: Exception) { + createdAt.status = PrefsStatus.WARN + createdAt.info = resourceHelper.gs(R.string.metadata_warning_date_format) + } + } + + meta[PrefsMetadataKey.AAPS_VERSION]?.let { version -> + val currentAppVer = versionCheckerUtils.versionDigits(config.VERSION_NAME) + val metadataVer = versionCheckerUtils.versionDigits(version.value) + + if ((currentAppVer.size >= 2) && (metadataVer.size >= 2) && (abs(currentAppVer[1] - metadataVer[1]) > 1)) { + version.status = PrefsStatus.WARN + version.info = resourceHelper.gs(R.string.metadata_warning_different_version) + } + + if ((currentAppVer.isNotEmpty()) && (metadataVer.isNotEmpty()) && (currentAppVer[0] != metadataVer[0])) { + version.status = PrefsStatus.WARN + version.info = resourceHelper.gs(R.string.metadata_urgent_different_version) + } + } + + return meta + } + + fun formatExportedAgo(utcTime: String): String { + val refTime = DateTime.now() + val itTime = DateTime.parse(utcTime) + val days = Days.daysBetween(itTime, refTime).days + val hours = Hours.hoursBetween(itTime, refTime).hours + + return if (hours == 0) { + resourceHelper.gs(R.string.exported_less_than_hour_ago) + } else if ((hours < 24) && (hours > 0)) { + resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.hours, hours, hours)) + } else if ((days < IMPORT_AGE_NOT_YET_OLD_DAYS) && (days > 0)) { + resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.days, days, days)) + } else { + resourceHelper.gs(R.string.exported_at, utcTime.substring(0, 10)) + } + } + } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFile.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFile.kt new file mode 100644 index 0000000000..8efcbca36b --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFile.kt @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.plugins.general.maintenance + +import android.os.Parcelable +import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefMetadata +import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey +import kotlinx.android.parcel.Parcelize +import kotlinx.android.parcel.RawValue +import java.io.File + +@Parcelize +data class PrefsFile( + val name: String, + val file: File, + val baseDir: File, + val dirKind: PrefsImportDir, + val handler: PrefsFormatsHandler, + + // metadata here is used only for list display + val metadata: @RawValue Map +) : Parcelable + diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFileContract.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFileContract.kt new file mode 100644 index 0000000000..69eae2dd21 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFileContract.kt @@ -0,0 +1,27 @@ +package info.nightscout.androidaps.plugins.general.maintenance + +import android.content.Context +import android.content.Intent +import androidx.activity.result.contract.ActivityResultContract +import androidx.fragment.app.FragmentActivity +import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity + +class PrefsFileContract : ActivityResultContract() { + + companion object { + + const val OUTPUT_PARAM = "prefs_file" + } + + override fun parseResult(resultCode: Int, intent: Intent?): PrefsFile? { + return when (resultCode) { + FragmentActivity.RESULT_OK -> intent?.getParcelableExtra(OUTPUT_PARAM) + else -> null + } + } + + override fun createIntent(context: Context, input: Void?): Intent { + return Intent(context, PrefImportListActivity::class.java) + } +} + diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFormatsHandler.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFormatsHandler.kt new file mode 100644 index 0000000000..6908c794df --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFormatsHandler.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.general.maintenance + +enum class PrefsFormatsHandler { + CLASSIC, + ENCRYPTED +} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsImportDir.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsImportDir.kt new file mode 100644 index 0000000000..ed596d9bb9 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsImportDir.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.general.maintenance + +enum class PrefsImportDir { + ROOT_DIR, + AAPS_DIR +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt index 9f71e46afb..2308c0f7a4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt @@ -12,11 +12,11 @@ import androidx.fragment.app.FragmentActivity import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerAppCompatActivity -import info.nightscout.androidaps.R +import info.nightscout.androidaps.core.R import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider import info.nightscout.androidaps.plugins.general.maintenance.PrefsFile import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract -import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsFormatsHandler +import info.nightscout.androidaps.plugins.general.maintenance.PrefsFormatsHandler import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsStatus import info.nightscout.androidaps.utils.locale.LocaleHelper @@ -46,6 +46,7 @@ class PrefImportListActivity : DaggerAppCompatActivity() { inner class RecyclerViewAdapter internal constructor(private var prefFileList: List) : RecyclerView.Adapter() { inner class PrefFileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + var fileName: TextView = itemView.findViewById(R.id.filelist_name) var fileDir: TextView = itemView.findViewById(R.id.filelist_dir) var metaDateTime: TextView = itemView.findViewById(R.id.meta_date_time) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/ClassicPrefsFormat.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/ClassicPrefsFormat.kt similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/ClassicPrefsFormat.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/ClassicPrefsFormat.kt index f264e7c06d..8123be8d98 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/ClassicPrefsFormat.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/ClassicPrefsFormat.kt @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.general.maintenance.formats import info.nightscout.androidaps.Constants -import info.nightscout.androidaps.R +import info.nightscout.androidaps.core.R import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.storage.Storage import java.io.File @@ -17,6 +17,7 @@ class ClassicPrefsFormat @Inject constructor( ) : PrefsFormat { companion object { + val FORMAT_KEY = "aaps_old" } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt similarity index 99% rename from app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt index e31a5215bb..3019354d33 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/EncryptedPrefsFormat.kt @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.general.maintenance.formats -import info.nightscout.androidaps.R +import info.nightscout.androidaps.core.R import info.nightscout.androidaps.utils.CryptoUtil import info.nightscout.androidaps.utils.extensions.hexStringToByteArray import info.nightscout.androidaps.utils.extensions.toHex @@ -23,6 +23,7 @@ class EncryptedPrefsFormat @Inject constructor( ) : PrefsFormat { companion object { + val FORMAT_KEY_ENC = "aaps_encrypted" val FORMAT_KEY_NOENC = "aaps_structured" diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt index d0d3935023..01a58461c7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt @@ -4,7 +4,7 @@ import android.content.Context import android.os.Parcelable import androidx.annotation.DrawableRes import androidx.annotation.StringRes -import info.nightscout.androidaps.R +import info.nightscout.androidaps.core.R import kotlinx.android.parcel.Parcelize import java.io.File @@ -74,11 +74,6 @@ enum class PrefsStatus(@DrawableRes val icon: Int) { DISABLED(R.drawable.ic_meta_error) } -enum class PrefsFormatsHandler { - CLASSIC, - ENCRYPTED -} - class PrefFileNotFoundError(message: String) : Exception(message) class PrefIOError(message: String) : Exception(message) class PrefFormatError(message: String) : Exception(message) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/storage/FileStrorage.kt b/core/src/main/java/info/nightscout/androidaps/utils/storage/FileStrorage.kt similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/utils/storage/FileStrorage.kt rename to core/src/main/java/info/nightscout/androidaps/utils/storage/FileStrorage.kt index 40be1e65c3..410d0f3860 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/storage/FileStrorage.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/storage/FileStrorage.kt @@ -1,17 +1,17 @@ -package info.nightscout.androidaps.utils.storage - -import java.io.File -import javax.inject.Singleton - -@Singleton -class FileStorage : Storage { - - override fun getFileContents(file: File): String { - return file.readText() - } - - override fun putFileContents(file: File, contents: String) { - file.writeText(contents) - } - +package info.nightscout.androidaps.utils.storage + +import java.io.File +import javax.inject.Singleton + +@Singleton +class FileStorage : Storage { + + override fun getFileContents(file: File): String { + return file.readText() + } + + override fun putFileContents(file: File, contents: String) { + file.writeText(contents) + } + } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/utils/storage/Storage.kt b/core/src/main/java/info/nightscout/androidaps/utils/storage/Storage.kt similarity index 79% rename from app/src/main/java/info/nightscout/androidaps/utils/storage/Storage.kt rename to core/src/main/java/info/nightscout/androidaps/utils/storage/Storage.kt index 475cd2675e..81668e8d40 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/storage/Storage.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/storage/Storage.kt @@ -1,11 +1,11 @@ -package info.nightscout.androidaps.utils.storage - -import java.io.File - -// This may seems unnecessary abstraction - but it will simplify testing -interface Storage { - - fun getFileContents(file: File) : String - fun putFileContents(file: File, contents: String) - -} +package info.nightscout.androidaps.utils.storage + +import java.io.File + +// This may seems unnecessary abstraction - but it will simplify testing +interface Storage { + + fun getFileContents(file: File): String + fun putFileContents(file: File, contents: String) + +} diff --git a/app/src/main/res/drawable/ic_meta_date.xml b/core/src/main/res/drawable/ic_meta_date.xml similarity index 98% rename from app/src/main/res/drawable/ic_meta_date.xml rename to core/src/main/res/drawable/ic_meta_date.xml index 190392aaa1..322065cb7a 100644 --- a/app/src/main/res/drawable/ic_meta_date.xml +++ b/core/src/main/res/drawable/ic_meta_date.xml @@ -1,9 +1,9 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_meta_encryption.xml b/core/src/main/res/drawable/ic_meta_encryption.xml similarity index 98% rename from app/src/main/res/drawable/ic_meta_encryption.xml rename to core/src/main/res/drawable/ic_meta_encryption.xml index 597b35a77a..288d433b91 100644 --- a/app/src/main/res/drawable/ic_meta_encryption.xml +++ b/core/src/main/res/drawable/ic_meta_encryption.xml @@ -1,9 +1,9 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_meta_error.xml b/core/src/main/res/drawable/ic_meta_error.xml similarity index 98% rename from app/src/main/res/drawable/ic_meta_error.xml rename to core/src/main/res/drawable/ic_meta_error.xml index e5d213f774..83ccad4559 100644 --- a/app/src/main/res/drawable/ic_meta_error.xml +++ b/core/src/main/res/drawable/ic_meta_error.xml @@ -1,10 +1,10 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_meta_flavour.xml b/core/src/main/res/drawable/ic_meta_flavour.xml similarity index 98% rename from app/src/main/res/drawable/ic_meta_flavour.xml rename to core/src/main/res/drawable/ic_meta_flavour.xml index a7fe7f3471..5802ebdef0 100644 --- a/app/src/main/res/drawable/ic_meta_flavour.xml +++ b/core/src/main/res/drawable/ic_meta_flavour.xml @@ -1,9 +1,9 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_meta_format.xml b/core/src/main/res/drawable/ic_meta_format.xml similarity index 99% rename from app/src/main/res/drawable/ic_meta_format.xml rename to core/src/main/res/drawable/ic_meta_format.xml index 2023a4934d..8626d79926 100644 --- a/app/src/main/res/drawable/ic_meta_format.xml +++ b/core/src/main/res/drawable/ic_meta_format.xml @@ -1,9 +1,9 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_meta_model.xml b/core/src/main/res/drawable/ic_meta_model.xml similarity index 98% rename from app/src/main/res/drawable/ic_meta_model.xml rename to core/src/main/res/drawable/ic_meta_model.xml index eca3e69c59..af6cf0cd87 100644 --- a/app/src/main/res/drawable/ic_meta_model.xml +++ b/core/src/main/res/drawable/ic_meta_model.xml @@ -1,9 +1,9 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_meta_name.xml b/core/src/main/res/drawable/ic_meta_name.xml similarity index 98% rename from app/src/main/res/drawable/ic_meta_name.xml rename to core/src/main/res/drawable/ic_meta_name.xml index ad120e037a..27057d07e2 100644 --- a/app/src/main/res/drawable/ic_meta_name.xml +++ b/core/src/main/res/drawable/ic_meta_name.xml @@ -1,9 +1,9 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_meta_ok.xml b/core/src/main/res/drawable/ic_meta_ok.xml similarity index 100% rename from app/src/main/res/drawable/ic_meta_ok.xml rename to core/src/main/res/drawable/ic_meta_ok.xml diff --git a/app/src/main/res/drawable/ic_meta_version.xml b/core/src/main/res/drawable/ic_meta_version.xml similarity index 99% rename from app/src/main/res/drawable/ic_meta_version.xml rename to core/src/main/res/drawable/ic_meta_version.xml index ddf95f2fa9..c208dc6ac5 100644 --- a/app/src/main/res/drawable/ic_meta_version.xml +++ b/core/src/main/res/drawable/ic_meta_version.xml @@ -1,9 +1,9 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_meta_warning.xml b/core/src/main/res/drawable/ic_meta_warning.xml similarity index 97% rename from app/src/main/res/drawable/ic_meta_warning.xml rename to core/src/main/res/drawable/ic_meta_warning.xml index 9cf5ce2c36..ebcead1ca7 100644 --- a/app/src/main/res/drawable/ic_meta_warning.xml +++ b/core/src/main/res/drawable/ic_meta_warning.xml @@ -1,10 +1,10 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/layout/maintenance_importlist_activity.xml b/core/src/main/res/layout/maintenance_importlist_activity.xml similarity index 100% rename from app/src/main/res/layout/maintenance_importlist_activity.xml rename to core/src/main/res/layout/maintenance_importlist_activity.xml diff --git a/app/src/main/res/layout/maintenance_importlist_item.xml b/core/src/main/res/layout/maintenance_importlist_item.xml similarity index 100% rename from app/src/main/res/layout/maintenance_importlist_item.xml rename to core/src/main/res/layout/maintenance_importlist_item.xml diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml index 8398b9a9eb..285162799c 100644 --- a/core/src/main/res/values/colors.xml +++ b/core/src/main/res/values/colors.xml @@ -77,5 +77,10 @@ #CCFFFFFF #E6FFFFFF + + #77dd77 + #FF8C00 + #FF5555 + diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 4d7b8ab6d2..2f66691ece 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -266,29 +266,62 @@ Glucose Mute for 5 minutes - - - - - - - - + + File format + Created at + AAPS Version + Build Variant + Exporting device patient name + Exporting device model + File encryption + Old export format + New encrypted format + New debug format (unencrypted) + Unknown export format + exported %1$s ago + exported at %1$s + exported less than hour ago + in directory: %1$s + Select file to import + Preferences were created with different variant of AAPS (%1$s) while you have: %2$s.\n\nSome settings may be missing or invalid - after importing please check and update your preferences. + Preferences were created on a different device. It is OK if you are importing from older/different phone, but make sure imported preferences are correct! + You are using the outdated legacy format from old versions of AAPS, which is not secure! Only use it as a last resort, if you do not have an export in current, JSON format. + Imported preferences are already %1$s days old! Maybe you have more up-to-date preferences or you choose the wrong file? Remember to export preferences regularly! + Invalid date-time format! + Preferences from different minor version of application. It is OK if you are importing after upgrade, but check after import if preferences are still correct! + Preferences from different major version of application. Major versions differ significantly and may have incompatible preferences! Make sure after import that preferences are still correct! + Settings file tampered + Settings file is secure + Using not secure, unencrypted settings format + JSON format error, missing required field (format, content, metadata or security) + Decryption error, the given password cannot decrypt the file + File checksum (hash) missing, cannot verify the authenticity of settings! + File was modified after export! + Decryption error, parsing preferences failed! + Decryption error, the provided password is invalid or settings file was modified! It may happen that the imported file was exported with a different Master password. + Missing encryption configuration, settings format is invalid! + Unsupported or not specified encryption algorithm! - - - - - - - - - - - - - - + + last_time_this_version_detected + last_versionchecker_waring + last_versionchecker_plugin_waring + last_revoked_certs_check + Signature verifier + We have detected that you are running an invalid version. Loop disabled! + Version %1$s available + + %1$d day + %1$d days + + + %1$d hour + %1$d hours + + + %1$d minute + %1$d minutes + \ No newline at end of file From 9e2fb90bb78eed101473ed4442a2222ca5b25586 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 18 Jan 2021 17:40:37 +0100 Subject: [PATCH 23/61] fix tests --- app/jacoco.exec | Bin 0 -> 79946 bytes .../versionChecker/VersionCheckerUtilsKtTest.kt | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 app/jacoco.exec diff --git a/app/jacoco.exec b/app/jacoco.exec new file mode 100644 index 0000000000000000000000000000000000000000..aef5037acf47867bdaf0bdc64ec90bf0fd9e08d2 GIT binary patch literal 79946 zcmeHQ349aP_P%KfWhqTBARtQ%SY#`fZmgA3T9#5;pe>7RAx)+wkR~BZX<2O9wD3?6 zWpP0S0RW|B+_osyY}RNtGQG-;5@%-nm= zJ?A^$`Hrlhz~9Fo`I&O2Q~EBdu3?&<8g(~>WYe0A@3WtIz1=|JSJWDw8=x zZOF_FiG%maDav6g^%TmY>}Swf&B_#b7iU%Jm|q*(g3VzY4tvZ!OYtSp>;r>jS^!vu8dlh(DPOINGeGu?A>dNztTD^rbrK{AG zIV9GgH(N|9_@u{TIYQ;F5FVuZ`jA3pJ&J}r+$rMqW~)xCkGG#Ri2Wcn$4CXm8ZwP4 zJzS~0Hs0#LIq2*<{YvyS&xz@$%sk{ob4I*gYk^DDr&v@Lt9huA+;fB6Ks^4_v27ML z=`s*?<~bEJz=O>O{UAzbq)g)w+O-SqLa5ja`Qm4%F1~#D>ayu5oaYp-S2IX!wirw~ zF*;o&qK^Rl^U2z!T~lXXMq$;Qg`P6QteHmVBk_{sZ7W)vcdcvi5^B%$d*Z!w4T zCokT9cz@E?+kMX*`WSWO`8UkH$H8@jersAtOVp&j=Zks>*0@v)PWd!0jT(oopEV?n&MovH!c6m|-bH z;2e}Gl`>n}hNFq_C{lJlxiK_WaRha!<{lh_x!DU9u+Op}9NzfCANm8wqegi$RPKY< zZV25wZGO2|wR7Kb>Y)B6lfgtLzUwObY~%^=_ipIsRy%JWbf$(jr3}XuUF%stD!)JK z$8(z;8^O20v282D%QhWcuaEe;c{Mj@QH5xzbd^|1N1eR1F2_H8`Rlob*O82OO-{8^Rw@Ln zw=NC#4OsmX0@{3ASbQp}n&(#4w!@kuWxlKq=W5_>X$Af{WAK7GlW$#e@6L$HZcrYG zcSI~*-&8esH0s3j%o!7tqDrTR!M;efL{YU6eo1{ir>M!$pHVlSf5|my$yB0#^gMy@z8$PKH^-dmhXtIJ_mzPAFOUiV7g@}q(Cc&(28KGUq`kmT%s zR`V#6$_N{;j~XBJ8S+(e$=5?r1kZD-^5G}Qy~DlckxA~2KMI-0p-QO4+0rp$i%+2k^duFCQ5 zElD9ddDx#QRnS@KYowPYxnhG!Wy(=9pV8AbI@_AkbenZrE*`8ajn8{m(~Wm0=dK+W zpK8Nzy@SS`+8vC#^IYY9%O;L8t4&(k!Nlit5pHZ6{GWxo$%j!7p0k)JHKhg11=F2< zNAARGP60QOBF@o7ytKTy+j|LF&!P~X^DvVKoWuTlmD-X_fkSN>)1EUoWG-<}x;nIH z_t3O3HtzY6ew~0U_>bf9kN2yG2clwEpAUr}G4L9v@oBTNE1 z`Z4HgBT^a#D|d7sRl-|F~*TfD2AUJ-GW1$H4y zL(j{2h;(bU5ay%9LZt7SIOxp%m)m-y(yr`>#l z^HuyKW#4_tkkxAGxp-wF!n-#G@9|p|(Tmp$bM+5c4+y+V@ZxrjFV65ixF?Z!Ykc6p z2d_8Ipr`8C@Ll7gaO3zN*YU<<;BWz;Iq3P*$Z8DKgg;ef}ZZD3a&yxXuaK0*-4EbjxOq9%Xw^gn#?$#H?{iVO&V#<-p#Grt1l{5<2`8&(lrGcvo z`5_<1a;2(F8I&bVHj{SS1z~rCqPASW(Cp3mybiwofe@q_+<-)t-U?u?#cBeu3T#Zh z+j7AeAZKv67+_oV@4>CaLrplyZPhl>z46 zlYquQ1w;@G2ym9)1K&E=B=greKJMsYuMR^-pbTvB7mj8SrnDGSM;06Q?b2#I7QkMT40>{pIzXHtG2qz86t-O4@8XuHefu;GbUy+k zpbowBP!&Isr zb>_w`jgV68)TpcrZuB{VJYkjjSo`F#PvZxDORNq6U9Fn?WoA_tMSiDD6kLxvNNph3 zW-$ka)(Z3-QXx(D@XAlGzWH_T*!tBc02~=nSbKJGh8|Pc6pi(Y9}TC%E^`JD~!(P#^`NBMRU0 zZE^+u1QBosP*hPZ<`?>B%>+_hcGj8;r2M_$h|hMvHGg!yMsJ{TJVv8x7u@cS65`AQ z-BD$%j#8OO@Gd+dnG+SQjqv^B2I|9ejg_|^y;-f(!X^?z$HYk~DH&O9Rv+7NT!z~m z=+kQHw(q}i%T7LMCnH-{BH)|k8-ij<_-ruMl1Y*C8*n&H)@J>cAJG#$cgzI)hBSrj zF_Fkfv(VAMz7eqLSzfHu)qiwl^?)m>RrmaL#_mz~Y%tUkq;J9z_S!P{^ov`c*6`*| zU9ZZ;Ggg%3N|plp@K)oa2bwlr!HZ~Bo`O})8OSY>3{yQoUBzNajflO*v3?)7C|NZ1 z88nt>x;)I)J-|2PvcFolRt2VaYxNb16Zt)~^Vj@wa_tAM9L-S(77wKd z8xT>E0M~n0=bmZ&;jKZuc#fTO1S6-O0%SWi#W0W9?D!CrM|M#-ylXIE2DCXieDQPg z*S3B9dfQUoVXWqko$1=z;eSgQtqLmLwAWwlcyW#wB`R7YyCFAP3j-o4Ik2Q4oo^|C zbnDls9~(O~s&#efZoiCVN~MALcY*9WldWNrXv}prJMs9y{4TR7-V{pJUO+NMh+6C| z$7E$R4y;f}M9e}3H4nlQN6eCfUiIIB@GV{t+~V0TMaOvo=&ENW!%HE^2^+bwOqFDy zW46h*?F~e@?~kEx9A2`iCofOB>Tj@nzj2g~P)KrUdWF?YyxsNQMbmcQ=%2}JM;>NN z<~o_33dnNx63L$u0DWHi$Y8U5_RF#B8HLv}4YpQC-+Y!Nvj6lc7>Y_?%}sm~E^AOl zMHISjV}nX^q3$!a{E)}t(oTMO;+=~F%F|-n@KS6Zc5KY{2q1yV;cSXsad}wO$#vVW zuH&7(5A!YeJ7t|v%Zj_#Ww_Oi+zIFVZ(iXRbFoUVlyf5iwm{Sv4+*{U)t9Lwj`R8n zRj&@#O;fT-TteoN5XF^y1jX&9R(IEEdZaTbZZy;gKv~KJ-)&-wGT0SS(}7HpWe_z8 z9VD#1M@W%kz`eGIkF0pT)rmshv`^KGhjAat=EdPy#5*g6B1!{({JwCz0#CWtJ>tu$ zk)ixtS`M?-kyeSZm4FQ|xl@4z0f~@7p9l~7IwJGCG5kT%sUsd^!yxi29RC9nD;2Df zqzhZNRc%Se-wR0WzwD!LH9zU+^Okb~e~k6TQl@Dw>Ph2EugOr}t<}>AQ5N@jV)^N% z!=G26o;>gZy<{Az6gw0^7(;^$RujMh!f{3k$ok`MG?{$&yXaX0>mK@B)HLtOv2{XX zEPw=$IQGO$*$#DaZGpUPyQfMbQ~SwB7@l!VYoTe znB<+Ag;_^43%6&&c-Kf`*S@lSaG-rQuX4YC60FqpQsM5~o3^&$1sSJ`X_eDiW)iep1=KgAj-nm4S zFG0`@r!PT-XC8Igc}aIkKn$=8Qh^w5>1eg_63eEkk*ETQM$!M#X{kxvkiVblX0m%IUv!>YM!~tP8hg zdwO``Z;oa}7M#OrA8lmbQ-c21Au41SW14lCWhyNb@c&8<}{-l$` zd3oAg6B$POw;-dZp%yYs@eu{ zqp?I#o8l_LcHjB_)Bpaz?XyIoMvNq;m@+dO*Ab+tN!TI2zTr@0=35XI1zA~|k;B<@ zBxZ-yG)W!M)byC_2Y^r`k)4#_38T|K*0j4ZE>Is@xZpQ6zv#F5mb*I3a51 zQTHQBdWM69m`Vj53Ine5<^b5dm>Z8n`C_$9w%Y)G6kHpEG&qJ4w{*|^UKU$ zfubwX`s>xE9HWKO(1kV3mu!~hwg2;nYaugAmA3c_bN+vF{pOl-K@0I>QU4C7+btWz zua`m?WATQxRD(sO3-+fyN0I1?TsH5!GbQ7F(17ZKGG33#k*fyjPVuZ0DFGW#6^U7n z7V2hybw_BLpRLYtV199wS_!!~t%0}+72%_vEIt3h0$z?U1Nl)zP|ytO-R6)%RCd1{ z3q_-xfa($XMEE?x(%AO30!v&a)&k}pUNYdD9?vODi`}mhqh;42dD(1c%+*Z;ehlC} z19PLXWGxv8w&^5v!)g^QSS}8GnmPBge|zuq`cY({K?{MBKtlrUaeEv|Y7tJa?k5`? z<~LoSo(4Ad3a?Tnxhq37oGQ7@7LqmGDM5-AmC;>#CNR>>( zomjie+#|oskoVA2Ja(0yv<{XL?F%=29uPUtfIxYhH*NYAZ@81!pggGU54=u%m8*%Z zY$dx?ScK9AV!!@`eKsbCIrSCnNgYg@=l^_tt4Z7}bA&pTXBmkl zd^{sh3y=TV4roZd9?dcYRuel>Y?6!A+PhFSwr%#qlE=>1B#51-$fP4XG?`p+{{4~T z)(Azy>GoY@++A&7V0Ph-S$}a4FNFN?r^_eId;37dGST!FhXS&`F3hky){N{Aj5B+S znqlNAxy&#Sk@4|R!3k}d$d5cZ)~5YXcCz{4!@L?gRc~*0?sY$%!JttN)LGRat6%pT z!jcBaa6a3`g&Xj`+wTfQ^((V13C&pvih4$!DyJj;C}h|(DkH?z*|bUSAz59=P(oS; zznn|~I;hEV1LPeR3w+Z|l0K~+?YXu|V#7*LG%f-M(F2W(u08UGK0c0yKAu$SfO&UD zh7-@eGIdlzBRQ|sLDj~?xwmr4sUiJrvb4=d1@Fs6)^WTxe_nL(%L~T3UtPi4F#sq% z#dQF`+B!Xb8}@7afxzg8wP=YT2@36Gm`6#&iH!nnKA!F<#F`x=es|vFRb!_8tFgc> zwQ>MLGrUk|^*r~tivo{G*pF9XK1bZu%q(8CGkF*ok=6M8s#k}C5TNgRVomRP9RGet?< zM-Nf?%BNZw#;DdU5*Y0|@k0BWWIiELFDb~8fXs7k;<9%83zNGD#00r4yOc>e&x_jNJp?XOyaC!`b~(ZwmBwoV%ja`)ruES&rA-`MKV< zuWnzjzUhSvl`D}^H5sHbPl7@n9W{KML(N2nrPg8YccSYG)1(_k0u9>(&BjQE=;Xh% zOgI~87b!+7_WH>WZejP?X|PNgqP=(bpVa=IAe;vA0uw_?2gfS{;DE@qG8VE z@0wHrsunSR#Mq@YmbGk@`{x#c28IP?9Qir|$^e_7NQkU;xn0(piS*zhV5w!TNht7p zhw_%AJ54X+6`$b9{0-Atp&Sr44r&rRF7(SOf%SYIZy#6W(e`oD>hD0{?I8tcnA$>$ z?~am|@zouKIK@5O=O+1izF^PG&m(d_?0p+?=low@C{EIRD3aAW%mfyL05GS!Kb5fg zaL`cRCTLafF!sIFo)=9~n4g6?M0cD%p4Xod16yzmD%xZCv7pi^|C zw3bOJMvBrjfF~rhRc=ng{YC2~o zA56@i*UOz^D_Zh}Zej1(i&htvbsknT^>;Pu=D0Tm_#FEjt&z57Nn=U`|0lj`CWQ zuMEps{p~}KWF@E~Ira>TRrq*{g+-F-9+uA$&?;RXRjvS!6-y<7^P>NnRa=I?u$Z@z zuj}e&mlO*y)1_->NO-V2)r(_g2XZ$W-DwlYY?d0?CY3_y+6T94rZaL$r zo7=)Afn)0l22eQ^o&--E^4rXFXK#*(>#?DnI4*YFy1VI|pc&k#?moBvnkd zt-SN38^(w|hdnPD4-H<3%P2;&qe2EtMX+Q?fv<0$>v9F?budR?#N{gxF;(dZ3-mWc zNk~|D*>C;Dm-6eD@eY99H8n!`LI=?XeTW7c--pogOpcLyOLkR0t329|u!g$9AGXzW zK!?(st8+7J@rq+YgA+&H3_UTn%1&`>5%YR7j}^p0e12*4vZm|9JEU}s!ZC_1i{z*d z9;cgIvV5a4-#vGVwp);)r!SE;U-gRQkGunmIPH)E1>U_Wc#q$zh+b~+(pi5XiJAs( zz^?Jd8NLViBtCSQ;1GERhm_TMZW}yw_v@YCtK~);8!!Wo{g*K0>%kJ1s3|iu-vH4O zCygq)88ZNPlJ!$5`op~}`_y_^`^K7~y_Yn|Lmhb`M)yUq@S7X% z4Qm%^qCZ&1pT7L{+`{X?W8_;vQ>~Ph3IQb#T^jVshCHX-{uVa+*f*Q1K^?*14F&lgor>ngIc(o!HsJ0_nxg~dnLQn!$ds2H z9`1gelPNi$3ey{xjZ5$|X~P&+a5t)V(M3NPR_ip}q{Nxu-6^eE90J z>F&Fd;0nSpkRw2B;4N_)PD~t6!XbvzE;t8g#JNWsTJA>iddBzX;9&J@taPzXg2h{o z@7%T?*irs_GH-T=Gim6y111%GVy5j|x=Kwc4tE!+HbF9id%TNBy!v%pdG)5=91=&1 z-ZGOn$e^clOhKV?Z&9&+TLOy-iuGI5jZ>K71o~$bnXg4oea@QNI7L3Gu$wPwoU+Z? zIHmWo_@O60xv*aFI7GrYh)?gv6kY3CKPtaJFDHaEG5I^dLOV?9^TnR5v)JX=qIBQO zIiFP@UQ}8Qna*mwpirN_BD75CT-z*kE;lewCPj_KYU8CIZ{J(^Dz6$kXX>&J z8DJGAs>d)`jeEA*>d-vGJ59EQlHZewYYMpi!D z?|n1iaGI>m`YS)8C#uCF3~7q<({P6y^lIa}`NxVTB2-Npwe^_|z#(q-XQ zUXP2x0AkY27L!VCp?5CkA>4t7z>1<*ehlbo@`+foL$pYkN&-RH3?SoK4uyYpZDeD? z`$;(LCld5Bh6gI1wPCZ}0M>?ERVlU#?CC-o$Vt8WarCo+%jySIFBa#zUwk4*rM54a z*uCPuY52eo00qc{i7U3bkw+A4;IbqseJPmD!Wq7vW|0WQ{dRr2YZqPmf_$;WRVmSu z(Nk&wnCMCUq5SMAg?D70E)0RiEouAcBZN?M;e_|SEe7LECn!ae0M zfOA1MjKzeN`Lar`P^nlV&z;?=r;YV4%6JQj?2fY5kQM@eV&OlPPHokxzzqd0T);A8 ztQJrO)0^YqmoC6OfWxEpEaGTG;yYV=J0zGMT_frTKz9)$ih#r+xc04dhMm+b_(8(?Hfk z9IOVGV`BCZ13X7_$51N5RIaP6a8D{+6P6yKVW8`JFEFoBjXZ}xOOz3vQ3g`&MdE2z zf2H%m8Bgb1FDw=zreQ=R7$Fu{r9lMAMRtzdQ!@YU+=X9`<<;v4mXAFfP8%PikqFB= z4#9|QFmsCXPmVaw#d#w!B3lFTPEVqf64mV%h$JklFFh^)e(f9YR=X!8XN5URyqqOF z%B--?(a`67wvR{M8VOWe#Cb+)2}*D7_&jnj>G^iZb&KmB)*YA;8Ym_O#r*NM8O#>f zH_1JG2HG?y2h7y|>rKrSUfC$Fw?x>DOx*)?sMTjsnjq#kNT`X>DgGY~e}s31ae7fu0W=mN;LoH9V$1Fv4%066woHP&#e9B}MjDoUfHDoL~u0 z(yims=UydDrTR@dFlS4>39q0S9_vO@sa#i{v2ZSgYVhd;KfPz0;lbQ2-2wj5d&BJ! zR#SauUw%tHotKDQDU}^Znbjt(k*GBX-J-LZQi5WvgWkZDGo8|R2}`3QRB06BpAYWN z_~$Y2it&*bLtd`D6_UV5t`U?(&vvQGHWcp243t`aL=37$_zsMu81{sCG^Brp`kd0x zDaBSk+U_YtQYj|_Y$vATu@hlIdP-Xw>VqGZGfEdKL@A&>4_m4LQU%WAf6l1EY6$_S z&}7hRh|b6ZlOT@5PP@1ZaUpB9l(KH}jvV(szDcK_6Z|@F=RW)O0nLvPt6-Behd>I8 zbWUa&ejy`WekC1<%?Xx}VtUZ=qvcn=8SR6l@Kr-QZQtDf(sxPKcONHeR3wiplVOqc z#Ju0G0X^|A>yGzR$CNq&A5CtLf_NN5n%=2`IZ(Tg5E17kxnxpE$qW=%A1a=BXWJ*M zVVt=`A0K#a%Z||YXe`e-3R~4K-4sO-;hfvSL%*YmaBk57JJyq!p;pJ!V66lUH33pd zvY9}Ic-KpkqE=69LuVImS4hpmi+ZFiJdbKjAGCoVD5z+dX2+EFyr@9+VTsxyMv|$P z7BVgaikv6Zm`l%J7eamWy}t#w_!{IXzZrJP8{b`v5_k-*yX0IXXJ?SY8&vQPrx&l!Uk%$a=al6&&i#A$9&9_UFOu$R=wbBdY_{h7B?oSQ2E znKU4LO|rAV>YkE`6!DUhjpxC3g*(bbw<{D}Q13Kf4|X?NHf(*}P6s6ahx=5#+Nh>5 z-fYBPvxjREKPASi7{=+jEsKtmn;<+=nSs7M7SxYbF4m z><^p4V}eDNXV`MZm?`^1Bd=oVGLM{yGEr;=w;-p1`v|%3y|9GxnKt=tpe%}kMgsw% zieds$p%|w4EVuZ`^Z7PN7-f$h8eb$=pmHdUzy6@oI4My&S1Y8ZC@P|>DxI-Dt+z9; z2_qz_tLnp@bydFyTkn223GAgB!8rQwAPh-hf1JC%c-9X1uy9D7-w|qkqz}O)sZtVS z6vN^1N~BC7NLYd%U+xcJrS#?gE-{T+S{e;0*y7M=YKX9ec&*4gL@QEyN{piXy$du|A}h_w8z@zJ9A3HO%%t2$I;Ph0_cRO^p1iC*M2;peWz6`rx22b zLY!*|X8`A-#&q?eFGsuxm?RB-M8$a^;r$eN`j7z@>S>8_X~>2QSruv2wV}y|5WnWS zT`RI+6FdxNVBx2~;~l(_GS-s-OZuaa_N(+^cpe()=IUe%M!AxdAZe$Z5<=f>Hr_wt z;=C(wcOH&n-8ymQjw*~z=z53ltAdjYUytzG`JJuWMghr{Yze10Y6>mGE?Pud0$#7g zEs?~^T1(atsr~HFzi4!O+w)>Az5x<2$|;W#g+xhuEJ>ufExJ{c6f)Vm@*c*YFAh$2 zb9tFFTz6H{noBta3R6LST1w^Z$%}i9Uvu-7i`7Hal@==3tSFhKDv`K$Mfj*EOV59> zfOl5jmlqsFW%tXmP%$QxDhJp&EEOxk(l{4lrJA7E-E3ye)lCC_4B+KTGq)9M$}w6D zgfQm9ERm?bo!R6-@%!jgdmo$fg>HNGW6!BxWhn0seS1hxw6T@i0D6`}{96Ke%ejSn z;i$`v*93c+npLYuUU?T{Zc;e~ljez@kpq{c(bX%*f4RJ4+fyT|6={6%4YIC!BVts< z=kwS4Z}49ndgcUgv3=zUo_H_UP+~h~yY*~<=)P8><;f8w+GQOIw~l0?l_g+)vyRsXv?E)d$8H(cW3YO*Woe4gRKX&*LQa8J+z_8;x(u}&zvTW&j8}JWKw#|#2(Id-_>*CT_P1Z zgzlN$VjLp*QYOX;`VH9iqubM_TR)_!s1^*50M2|FT|u5YTEI~sN3u^dc% zm!e9ihN((o;6!ZRgS$?ZIv%XkYA_#(ZPoO6UxeM0lm~6fi$(oA zoNl*lO!Z}W@rJZigGHqaW^x^pMP<3)+Hi|8b!4$&-!83Ye*z)PB!iwXy({;rQq;}H z;&aK1XH?p`L%T&pgr}!Lt2?q|cm9ldO?^gE*)1u+Pw=A#slGm>P+5T$Lf(vVzSxl zAu~QnjhW8dIF3tKiX-ApOcoO=1~at!pwL<}PuDJs3~QwlniLcsD+5dK^oQ{H`nLK_ zP_WY+iQ7X-=RxMEDZKHiQ&yCDO`dX@>|2r(d_FpBBT7RSLPr3)BD3C z)c{9~4jye%v%(m2x>aUd3|DdAfz7>Eo!r*M8dz=SkVxyfoRYTCe`DO?zl8uE_)V5N z@|#bZSL;1FbHgluXoQ(E4W-2Z&27(D*g$>Bb3N@C-9!l-tD3BQ=*K7@c8{b&)uCO1 zY)deY1c)cdE45Y}MO=6lGD6uB@v(sc4jl{tvu0!Om=f!uK~)i(o(c-beqRZ0LJvdQqnzc)K!?xWGBu zTvjZbSOc>CQ}lO4)kL{*Co&4xD4BOGzQnPJlsHPIpHX1*K(*vJ-Q1Gp8;$wAt-S7= z9Wl`PK1*exxaAo2isZP*6U$F89saz6SKZ(BZ0x$G&oszjHF+y=4Jnq8pz!kYjqigK zqIMqTZIbNzJYemmX!RL7muKsb$|dMzEw*A~*ZATL--CM+tI3RUEeSiiU_DsFJ-BJ^ z5!>&rR#od`I|a%s*XU%0^=ImHY_>owSrv&SB_9GZn5<}KO(_;>7CQRZHv%?2>xOUO z>Q&NgY)Dd)13Vxpich4h6cMZSP75DnDbl2{>(_*W4yno~nBn%Yeu)&-8IKfT7a9wkBL$;-)9NW4Llg~EAA6Rx*2 zES5B(A+-s$qok5YJB%f%K#`!SAXz71C2LGAOHgY1iIt^mUv%I9NwJ!ZlwJc9Zf(*z z<-EFmuAnD*2AQFsB^#`Ijh`P9!uoQU7~VI1EB!5gZT`II;FlMSb^i_r>a1$$>kD_d zQc=7&VE^ZHtIb0>mlXKC+(-hWa+yS_Y{v~ATinVc{glPl6G_>y2W~bSO9NuVsQ{&v Zln#$Z^^lCG2iaUHB{}6-s_xO*{}1uMto;B0 literal 0 HcmV?d00001 diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtilsKtTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtilsKtTest.kt index db693198bb..8d85f1e340 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtilsKtTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/versionChecker/VersionCheckerUtilsKtTest.kt @@ -1,8 +1,8 @@ package info.nightscout.androidaps.plugins.constraints.versionChecker import android.content.Context +import info.nightscout.androidaps.Config import info.nightscout.androidaps.TestBase -import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -19,11 +19,12 @@ class VersionCheckerUtilsKtTest : TestBase() { @Mock lateinit var sp: SP @Mock lateinit var resourceHelper: ResourceHelper @Mock lateinit var context: Context + val config = Config() val rxBus = RxBusWrapper() @Before fun setup() { - versionCheckerUtils = VersionCheckerUtils(aapsLogger, sp, resourceHelper, rxBus, context) + versionCheckerUtils = VersionCheckerUtils(aapsLogger, sp, resourceHelper, rxBus, config, context) } @Test From e26ae1af7dc527856cea95ab467a8fdd08a8c48c Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 18 Jan 2021 22:47:55 +0100 Subject: [PATCH 24/61] asking for permissions refactor --- .../java/info/nightscout/androidaps/Config.kt | 4 + .../nightscout/androidaps/MainActivity.kt | 19 --- .../activities/PreferencesActivity.kt | 4 - .../activities/ProfileHelperActivity.kt | 7 +- .../RequestDexcomPermissionActivity.kt | 1 + .../androidaps/activities/StatsActivity.kt | 4 +- .../androidaps/activities/SurveyActivity.kt | 2 - .../historyBrowser/HistoryBrowseActivity.kt | 2 - .../general/maintenance/ImportExportPrefs.kt | 8 +- .../activities/QuickWizardListActivity.kt | 2 - .../activities/SmsCommunicatorOtpActivity.kt | 3 +- .../androidaps/setupwizard/SWDefinition.kt | 6 +- .../setupwizard/SetupWizardActivity.kt | 29 +---- .../androidaps/utils/AndroidPermission.kt | 58 ++++----- app/src/main/res/values/strings.xml | 1 - core/core_dependencies.gradle | 1 + .../DaggerAppCompatActivityWithResult.kt | 31 +++++ .../androidaps/interfaces/ConfigInterface.kt | 1 + .../maintenance/PrefFileListProvider.kt | 6 +- .../activities/PrefImportListActivity.kt | 113 +++++++++--------- .../OptimizationPermissionContract.kt | 20 ++++ ...l => maintenance_import_list_activity.xml} | 2 +- ...m.xml => maintenance_import_list_item.xml} | 0 core/src/main/res/values/strings.xml | 3 + .../dana/activities/DanaHistoryActivity.kt | 2 - .../activities/DanaUserOptionsActivity.kt | 2 - .../danars/activities/EnterPinActivity.kt | 2 - .../pump/omnipod/ui/PodManagementActivity.kt | 2 - 28 files changed, 155 insertions(+), 180 deletions(-) create mode 100644 core/src/main/java/info/nightscout/androidaps/utils/permissions/OptimizationPermissionContract.kt rename core/src/main/res/layout/{maintenance_importlist_activity.xml => maintenance_import_list_activity.xml} (94%) rename core/src/main/res/layout/{maintenance_importlist_item.xml => maintenance_import_list_item.xml} (100%) diff --git a/app/src/main/java/info/nightscout/androidaps/Config.kt b/app/src/main/java/info/nightscout/androidaps/Config.kt index 036474f58d..a598adc440 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.kt +++ b/app/src/main/java/info/nightscout/androidaps/Config.kt @@ -1,5 +1,6 @@ package info.nightscout.androidaps +import android.os.Build import info.nightscout.androidaps.interfaces.ConfigInterface import javax.inject.Inject import javax.inject.Singleton @@ -14,4 +15,7 @@ class Config @Inject constructor() : ConfigInterface { override val PUMPDRIVERS = BuildConfig.FLAVOR == "full" || BuildConfig.FLAVOR == "pumpcontrol" override val FLAVOR = BuildConfig.FLAVOR override val VERSION_NAME = BuildConfig.VERSION_NAME + + override val currentDeviceModelString = + Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")" } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.kt b/app/src/main/java/info/nightscout/androidaps/MainActivity.kt index 91b22d72e7..f200267a6c 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.kt @@ -2,7 +2,6 @@ package info.nightscout.androidaps import android.content.Context import android.content.Intent -import android.content.pm.PackageManager import android.graphics.Rect import android.os.Bundle import android.os.PersistableBundle @@ -22,7 +21,6 @@ import android.widget.TextView import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.Toolbar -import androidx.core.app.ActivityCompat import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.tabs.TabLayoutMediator import com.google.firebase.crashlytics.FirebaseCrashlytics @@ -58,7 +56,6 @@ import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest import info.nightscout.androidaps.utils.locale.LocaleHelper import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.resources.IconsProvider -import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.tabs.TabPageAdapter import info.nightscout.androidaps.utils.ui.UIRunnable @@ -77,7 +74,6 @@ class MainActivity : NoSplashAppCompatActivity() { @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var androidPermission: AndroidPermission @Inject lateinit var sp: SP - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var versionCheckerUtils: VersionCheckerUtils @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin @Inject lateinit var loopPlugin: LoopPlugin @@ -234,21 +230,6 @@ class MainActivity : NoSplashAppCompatActivity() { } } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (permissions.isNotEmpty()) { - if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) { - when (requestCode) { - AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted - OKDialog.show(this, "", resourceHelper.gs(R.string.alert_dialog_storage_permission_text)) - - AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY, AndroidPermission.CASE_PHONE_STATE, AndroidPermission.CASE_SYSTEM_WINDOW -> { - } - } - } - } - } - override fun dispatchTouchEvent(event: MotionEvent): Boolean { if (event.action == MotionEvent.ACTION_DOWN) { val v = currentFocus diff --git a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.kt index 3a2fda604b..e9b90cd79c 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.kt @@ -8,14 +8,10 @@ import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceScreen import info.nightscout.androidaps.R import info.nightscout.androidaps.utils.locale.LocaleHelper -import info.nightscout.androidaps.utils.resources.ResourceHelper import kotlinx.android.synthetic.main.activity_preferences.* -import javax.inject.Inject class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback { - @Inject lateinit var resourceHelper: ResourceHelper - var preferenceId = 0 var myPreferenceFragment: MyPreferenceFragment? = null diff --git a/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt index 5476d29519..caf38bfca9 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt @@ -24,15 +24,14 @@ import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.extensions.toVisibility -import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.stats.TddCalculator import kotlinx.android.synthetic.main.activity_profilehelper.* import java.text.DecimalFormat import javax.inject.Inject class ProfileHelperActivity : NoSplashAppCompatActivity() { + @Inject lateinit var aapsLogger: AAPSLogger - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var tddCalculator: TddCalculator @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var defaultProfile: DefaultProfile @@ -229,7 +228,9 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() { ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileInterface.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString()) ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile() } - } catch (e: Exception) { null } + } catch (e: Exception) { + null + } private fun getProfileName(age: Double, tdd: Double, weight: Double, basalSumPct: Double, tab: Int): String = when (typeSelected[tab]) { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt index a87224dc30..8eb93156b1 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt @@ -15,6 +15,7 @@ class RequestDexcomPermissionActivity : DialogAppCompatActivity() { } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) finish() } diff --git a/app/src/main/java/info/nightscout/androidaps/activities/StatsActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/StatsActivity.kt index ca26266f8f..805ea291af 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/StatsActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/StatsActivity.kt @@ -3,18 +3,16 @@ package info.nightscout.androidaps.activities import android.os.Bundle import info.nightscout.androidaps.R import info.nightscout.androidaps.utils.ActivityMonitor -import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.stats.TddCalculator import info.nightscout.androidaps.utils.stats.TirCalculator -import info.nightscout.androidaps.utils.resources.ResourceHelper import kotlinx.android.synthetic.main.activity_stats.* import javax.inject.Inject class StatsActivity : NoSplashAppCompatActivity() { + @Inject lateinit var tddCalculator: TddCalculator @Inject lateinit var tirCalculator: TirCalculator - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var activityMonitor: ActivityMonitor override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/SurveyActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/SurveyActivity.kt index 1d03ddb344..96b5dccf5b 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/SurveyActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/SurveyActivity.kt @@ -16,7 +16,6 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.InstanceId import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.ToastUtils -import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.stats.TddCalculator import info.nightscout.androidaps.utils.stats.TirCalculator import kotlinx.android.synthetic.main.activity_survey.* @@ -24,7 +23,6 @@ import javax.inject.Inject class SurveyActivity : NoSplashAppCompatActivity() { @Inject lateinit var aapsLogger: AAPSLogger - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var tddCalculator: TddCalculator @Inject lateinit var tirCalculator: TirCalculator diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt index b6bd7f6279..f8188545ea 100644 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt @@ -31,7 +31,6 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.extensions.toVisibility -import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable @@ -49,7 +48,6 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var sp: SP - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var iobCobCalculatorPluginHistory: IobCobCalculatorPluginHistory diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.kt index 17693ec7ef..d1edbbca20 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.kt @@ -16,6 +16,7 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult import info.nightscout.androidaps.activities.PreferencesActivity import info.nightscout.androidaps.events.EventAppExit +import info.nightscout.androidaps.interfaces.ConfigInterface import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag @@ -53,6 +54,7 @@ class ImportExportPrefs @Inject constructor( private val buildHelper: BuildHelper, private val rxBus: RxBusWrapper, private val passwordCheck: PasswordCheck, + private val config: ConfigInterface, private val androidPermission: AndroidPermission, private val classicPrefsFormat: ClassicPrefsFormat, private val encryptedPrefsFormat: EncryptedPrefsFormat, @@ -74,8 +76,8 @@ class ImportExportPrefs @Inject constructor( if (permission != PackageManager.PERMISSION_GRANTED) { // We don't have permission so prompt the user fragment.activity?.let { - androidPermission.askForPermission(it, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE), AndroidPermission.CASE_STORAGE) + androidPermission.askForPermission(it, + arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) } } else { onGranted.run() @@ -91,7 +93,7 @@ class ImportExportPrefs @Inject constructor( metadata[PrefsMetadataKey.CREATED_AT] = PrefMetadata(DateUtil.toISOString(Date()), PrefsStatus.OK) metadata[PrefsMetadataKey.AAPS_VERSION] = PrefMetadata(BuildConfig.VERSION_NAME, PrefsStatus.OK) metadata[PrefsMetadataKey.AAPS_FLAVOUR] = PrefMetadata(BuildConfig.FLAVOR, PrefsStatus.OK) - metadata[PrefsMetadataKey.DEVICE_MODEL] = PrefMetadata(getCurrentDeviceModelString(), PrefsStatus.OK) + metadata[PrefsMetadataKey.DEVICE_MODEL] = PrefMetadata(config.currentDeviceModelString, PrefsStatus.OK) if (prefsEncryptionIsDisabled()) { metadata[PrefsMetadataKey.ENCRYPTION] = PrefMetadata("Disabled", PrefsStatus.DISABLED) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt index 96b33fb149..69c572b05e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt @@ -17,7 +17,6 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWiza import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.extensions.plusAssign -import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.wizard.QuickWizard import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable @@ -26,7 +25,6 @@ import javax.inject.Inject class QuickWizardListActivity : NoSplashAppCompatActivity() { @Inject lateinit var rxBus: RxBusWrapper - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var quickWizard: QuickWizard @Inject lateinit var dateUtil: DateUtil diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/activities/SmsCommunicatorOtpActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/activities/SmsCommunicatorOtpActivity.kt index 8c39199d35..f491aaf14b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/activities/SmsCommunicatorOtpActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/activities/SmsCommunicatorOtpActivity.kt @@ -21,17 +21,16 @@ import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePas import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.resources.ResourceHelper import kotlinx.android.synthetic.main.activity_smscommunicator_otp.* import net.glxn.qrgen.android.QRCode import javax.inject.Inject class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() { + @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin @Inject lateinit var otp: OneTimePassword - @Inject lateinit var resourceHelper: ResourceHelper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt index 4aa72c3054..f2604264c5 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt @@ -118,7 +118,7 @@ class SWDefinition @Inject constructor( .add(SWButton(injector) .text(R.string.askforpermission) .visibility { androidPermission.permissionNotGranted(context, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) } - .action { androidPermission.askForPermission(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY) }) + .action { androidPermission.askForPermission(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) }) .visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) } .validator { !androidPermission.permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) } private val screenPermissionBt = SWScreen(injector, R.string.permission) @@ -129,7 +129,7 @@ class SWDefinition @Inject constructor( .add(SWButton(injector) .text(R.string.askforpermission) .visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) } - .action { androidPermission.askForPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION, AndroidPermission.CASE_LOCATION) }) + .action { androidPermission.askForPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) }) .visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) } .validator { !androidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) } private val screenPermissionStore = SWScreen(injector, R.string.permission) @@ -140,7 +140,7 @@ class SWDefinition @Inject constructor( .add(SWButton(injector) .text(R.string.askforpermission) .visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) } - .action { androidPermission.askForPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE) }) + .action { androidPermission.askForPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) }) .visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) } .validator { !androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) } private val screenImport = SWScreen(injector, R.string.nav_import) diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.kt b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.kt index 262a38e634..74d13aaf91 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.kt @@ -1,11 +1,9 @@ package info.nightscout.androidaps.setupwizard import android.content.Intent -import android.content.pm.PackageManager import android.os.Bundle import android.view.View import android.widget.TextView -import androidx.core.app.ActivityCompat import dagger.android.HasAndroidInjector import info.nightscout.androidaps.MainActivity import info.nightscout.androidaps.R @@ -19,12 +17,9 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange import info.nightscout.androidaps.setupwizard.elements.SWItem import info.nightscout.androidaps.setupwizard.events.EventSWUpdate -import info.nightscout.androidaps.utils.AndroidPermission import info.nightscout.androidaps.utils.FabricPrivacy -import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show import info.nightscout.androidaps.utils.alertDialogs.OKDialog.showConfirmation import info.nightscout.androidaps.utils.locale.LocaleHelper.update -import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable @@ -39,7 +34,6 @@ class SetupWizardActivity : NoSplashAppCompatActivity() { @Inject lateinit var localProfilePlugin: LocalProfilePlugin @Inject lateinit var swDefinition: SWDefinition @Inject lateinit var rxBus: RxBusWrapper - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var sp: SP @Inject lateinit var fabricPrivacy: FabricPrivacy @@ -123,7 +117,7 @@ class SetupWizardActivity : NoSplashAppCompatActivity() { sw_scrollview?.smoothScrollTo(0, 0) } - private fun updateButtons() { + override fun updateButtons() { runOnUiThread { val currentScreen = screens[currentWizardPage] if (currentScreen.validator == null || currentScreen.validator!!.isValid || currentScreen.skippable) { @@ -198,25 +192,4 @@ class SetupWizardActivity : NoSplashAppCompatActivity() { } return max(currentWizardPage, 0) } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (permissions.isNotEmpty()) { - if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) { - when (requestCode) { - AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted - show(this, resourceHelper.gs(R.string.permission), resourceHelper.gs(R.string.alert_dialog_storage_permission_text)) - - AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY -> { - } - } - } - } - updateButtons() - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (requestCode == AndroidPermission.CASE_BATTERY) updateButtons() - } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt index a2afdb1c19..4ac9b7885f 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt @@ -10,11 +10,11 @@ import android.net.Uri import android.os.Build import android.os.PowerManager import android.provider.Settings -import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.fragment.app.FragmentActivity import dagger.android.HasAndroidInjector import info.nightscout.androidaps.R +import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification @@ -34,23 +34,13 @@ class AndroidPermission @Inject constructor( val injector: HasAndroidInjector ) { - companion object { - - const val CASE_STORAGE = 0x1 - const val CASE_SMS = 0x2 - const val CASE_LOCATION = 0x3 - const val CASE_BATTERY = 0x4 - const val CASE_PHONE_STATE = 0x5 - const val CASE_SYSTEM_WINDOW = 0x6 - } - - private var permission_battery_optimization_failed = false + private var permissionBatteryOptimizationFailed = false @SuppressLint("BatteryLife") - fun askForPermission(activity: FragmentActivity, permission: Array, requestCode: Int) { + fun askForPermission(activity: FragmentActivity, permissions: Array) { var test = false var testBattery = false - for (s in permission) { + for (s in permissions) { test = test || ContextCompat.checkSelfPermission(activity, s) != PackageManager.PERMISSION_GRANTED if (s == Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) { val powerManager = activity.getSystemService(Context.POWER_SERVICE) as PowerManager @@ -59,30 +49,26 @@ class AndroidPermission @Inject constructor( } } if (test) { - ActivityCompat.requestPermissions(activity, permission, requestCode) + if (activity is DaggerAppCompatActivityWithResult) + activity.requestMultiplePermissions.launch(permissions) } if (testBattery) { try { - val i = Intent() - i.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS - i.data = Uri.parse("package:" + activity.packageName) - activity.startActivityForResult(i, CASE_BATTERY) + if (activity is DaggerAppCompatActivityWithResult) + activity.callForBatteryOptimization.launch(null) } catch (e: ActivityNotFoundException) { - permission_battery_optimization_failed = true + permissionBatteryOptimizationFailed = true show(activity, resourceHelper.gs(R.string.permission), resourceHelper.gs(R.string.alert_dialog_permission_battery_optimization_failed), Runnable { activity.recreate() }) } } } - fun askForPermission(activity: FragmentActivity, permission: String, requestCode: Int) { - val permissions = arrayOf(permission) - askForPermission(activity, permissions, requestCode) - } + fun askForPermission(activity: FragmentActivity, permission: String) = askForPermission(activity, arrayOf(permission)) fun permissionNotGranted(context: Context, permission: String): Boolean { var selfCheck = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED if (permission == Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) { - if (!permission_battery_optimization_failed) { + if (!permissionBatteryOptimizationFailed) { val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager val packageName = context.packageName selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName) @@ -96,17 +82,17 @@ class AndroidPermission @Inject constructor( if (smsCommunicatorPlugin.isEnabled(PluginType.GENERAL)) { if (permissionNotGranted(activity, Manifest.permission.RECEIVE_SMS)) { val notification = NotificationWithAction(injector, Notification.PERMISSION_SMS, resourceHelper.gs(R.string.smscommunicator_missingsmspermission), Notification.URGENT) - notification.action(R.string.request, Runnable { + notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.SEND_SMS, - Manifest.permission.RECEIVE_MMS), CASE_SMS) - }) + Manifest.permission.RECEIVE_MMS)) + } rxBus.send(EventNewNotification(notification)) } else rxBus.send(EventDismissNotification(Notification.PERMISSION_SMS)) // Following is a bug in Android 8 if (permissionNotGranted(activity, Manifest.permission.READ_PHONE_STATE)) { val notification = NotificationWithAction(injector, Notification.PERMISSION_PHONESTATE, resourceHelper.gs(R.string.smscommunicator_missingphonestatepermission), Notification.URGENT) - notification.action(R.string.request, Runnable { askForPermission(activity, arrayOf(Manifest.permission.READ_PHONE_STATE), CASE_PHONE_STATE) }) + notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.READ_PHONE_STATE)) } rxBus.send(EventNewNotification(notification)) } else rxBus.send(EventDismissNotification(Notification.PERMISSION_PHONESTATE)) } @@ -116,7 +102,7 @@ class AndroidPermission @Inject constructor( fun notifyForBatteryOptimizationPermission(activity: FragmentActivity) { if (permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) { val notification = NotificationWithAction(injector, Notification.PERMISSION_BATTERY, String.format(resourceHelper.gs(R.string.needwhitelisting), resourceHelper.gs(R.string.app_name)), Notification.URGENT) - notification.action(R.string.request, Runnable { askForPermission(activity, arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS), CASE_BATTERY) }) + notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) } rxBus.send(EventNewNotification(notification)) } else rxBus.send(EventDismissNotification(Notification.PERMISSION_BATTERY)) } @@ -124,10 +110,10 @@ class AndroidPermission @Inject constructor( @Synchronized fun notifyForStoragePermission(activity: FragmentActivity) { if (permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { val notification = NotificationWithAction(injector, Notification.PERMISSION_STORAGE, resourceHelper.gs(R.string.needstoragepermission), Notification.URGENT) - notification.action(R.string.request, Runnable { + notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE), CASE_STORAGE) - }) + Manifest.permission.WRITE_EXTERNAL_STORAGE)) + } rxBus.send(EventNewNotification(notification)) } else rxBus.send(EventDismissNotification(Notification.PERMISSION_STORAGE)) } @@ -135,7 +121,7 @@ class AndroidPermission @Inject constructor( @Synchronized fun notifyForLocationPermissions(activity: FragmentActivity) { if (permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION)) { val notification = NotificationWithAction(injector, Notification.PERMISSION_LOCATION, resourceHelper.gs(R.string.needlocationpermission), Notification.URGENT) - notification.action(R.string.request, Runnable { askForPermission(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), CASE_LOCATION) }) + notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)) } rxBus.send(EventNewNotification(notification)) } else rxBus.send(EventDismissNotification(Notification.PERMISSION_LOCATION)) } @@ -145,7 +131,7 @@ class AndroidPermission @Inject constructor( if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { if (!Settings.canDrawOverlays(activity)) { val notification = NotificationWithAction(injector, Notification.PERMISSION_SYSTEM_WINDOW, resourceHelper.gs(R.string.needsystemwindowpermission), Notification.URGENT) - notification.action(R.string.request, Runnable { + notification.action(R.string.request) { // Check if Android Q or higher if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { // Show alert dialog to the user saying a separate permission is needed @@ -154,7 +140,7 @@ class AndroidPermission @Inject constructor( Uri.parse("package:" + activity.packageName)) activity.startActivity(intent) } - }) + } rxBus.send(EventNewNotification(notification)) } else rxBus.send(EventDismissNotification(Notification.PERMISSION_SYSTEM_WINDOW)) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e89fdb1795..b2ebe5de3f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -38,7 +38,6 @@ Do you really want to reset the databases? Exit Always use basal absolute values - Please reboot your phone or restart AndroidAPS from the System Settings \notherwise Android APS will not have logging (important to track and verify that the algorithms are working correctly)! This device does not appear to support battery optimization whitelisting - you may experience performance issues. Some buttons to quickly access common features diff --git a/core/core_dependencies.gradle b/core/core_dependencies.gradle index 2c2951a248..93beb08a79 100644 --- a/core/core_dependencies.gradle +++ b/core/core_dependencies.gradle @@ -17,6 +17,7 @@ dependencies { api 'androidx.recyclerview:recyclerview:1.1.0' api 'androidx.gridlayout:gridlayout:1.0.0' api 'androidx.percentlayout:percentlayout:1.0.0' + api 'androidx.activity:activity-ktx:1.2.0-rc01' api "com.google.android.material:material:$material_version" api "com.google.dagger:dagger-android:$dagger_version" diff --git a/core/src/main/java/info/nightscout/androidaps/activities/DaggerAppCompatActivityWithResult.kt b/core/src/main/java/info/nightscout/androidaps/activities/DaggerAppCompatActivityWithResult.kt index fb124926f3..f28a06d286 100644 --- a/core/src/main/java/info/nightscout/androidaps/activities/DaggerAppCompatActivityWithResult.kt +++ b/core/src/main/java/info/nightscout/androidaps/activities/DaggerAppCompatActivityWithResult.kt @@ -1,12 +1,21 @@ package info.nightscout.androidaps.activities +import android.Manifest +import android.content.pm.PackageManager +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.app.ActivityCompat import dagger.android.support.DaggerAppCompatActivity +import info.nightscout.androidaps.core.R import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract +import info.nightscout.androidaps.utils.alertDialogs.OKDialog +import info.nightscout.androidaps.utils.permissions.OptimizationPermissionContract +import info.nightscout.androidaps.utils.resources.ResourceHelperImplementation import javax.inject.Inject open class DaggerAppCompatActivityWithResult : DaggerAppCompatActivity() { + @Inject lateinit var resourceHelper: ResourceHelperImplementation @Inject lateinit var importExportPrefs: ImportExportPrefsInterface val callForPrefFile = registerForActivityResult(PrefsFileContract()) { @@ -14,4 +23,26 @@ open class DaggerAppCompatActivityWithResult : DaggerAppCompatActivity() { importExportPrefs.importSharedPreferences(this, it) } } + + val callForBatteryOptimization = registerForActivityResult(OptimizationPermissionContract()) { + updateButtons() + } + + val requestMultiplePermissions = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> + permissions.entries.forEach { + if (it.value) + if (ActivityCompat.checkSelfPermission(this, it.key) == PackageManager.PERMISSION_GRANTED) { + when (it.key) { + Manifest.permission.WRITE_EXTERNAL_STORAGE -> + //show dialog after permission is granted + OKDialog.show(this, "", resourceHelper.gs(R.string.alert_dialog_storage_permission_text)) + // ignore the rest + } + } + } + updateButtons() + } + + // Used for SetupWizardActivity + open fun updateButtons() {} } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/ConfigInterface.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/ConfigInterface.kt index 693dd64988..cc4ba86182 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/ConfigInterface.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/ConfigInterface.kt @@ -8,4 +8,5 @@ interface ConfigInterface { val PUMPDRIVERS: Boolean val FLAVOR: String val VERSION_NAME: String + val currentDeviceModelString : String } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt index 22784677ab..167446fd7e 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefFileListProvider.kt @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.general.maintenance -import android.os.Build import android.os.Environment import info.nightscout.androidaps.core.R import info.nightscout.androidaps.interfaces.ConfigInterface @@ -18,9 +17,6 @@ import javax.inject.Inject import javax.inject.Singleton import kotlin.math.abs -fun getCurrentDeviceModelString() = - Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")" - @Singleton class PrefFileListProvider @Inject constructor( private val resourceHelper: ResourceHelper, @@ -117,7 +113,7 @@ class PrefFileListProvider @Inject constructor( } meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model -> - if (model.value != getCurrentDeviceModelString()) { + if (model.value != config.currentDeviceModelString) { model.status = PrefsStatus.WARN model.info = resourceHelper.gs(R.string.metadata_warning_different_device) } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt index 2308c0f7a4..f4cbc1dc91 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/PrefImportListActivity.kt @@ -5,23 +5,23 @@ import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.MenuItem -import android.view.View import android.view.ViewGroup -import android.widget.TextView import androidx.fragment.app.FragmentActivity import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerAppCompatActivity import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.core.databinding.MaintenanceImportListActivityBinding +import info.nightscout.androidaps.core.databinding.MaintenanceImportListItemBinding import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider import info.nightscout.androidaps.plugins.general.maintenance.PrefsFile import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract import info.nightscout.androidaps.plugins.general.maintenance.PrefsFormatsHandler import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsStatus +import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.locale.LocaleHelper import info.nightscout.androidaps.utils.resources.ResourceHelper -import kotlinx.android.synthetic.main.maintenance_importlist_activity.* import javax.inject.Inject class PrefImportListActivity : DaggerAppCompatActivity() { @@ -29,50 +29,46 @@ class PrefImportListActivity : DaggerAppCompatActivity() { @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var prefFileListProvider: PrefFileListProvider + private lateinit var binding: MaintenanceImportListActivityBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setTheme(R.style.AppTheme) - setContentView(R.layout.maintenance_importlist_activity) + binding = MaintenanceImportListActivityBinding.inflate(layoutInflater) + val view = binding.root + setContentView(view) title = resourceHelper.gs(R.string.preferences_import_list_title) supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) supportActionBar?.setDisplayShowTitleEnabled(true) - importlist_recyclerview.layoutManager = LinearLayoutManager(this) - importlist_recyclerview.adapter = RecyclerViewAdapter(prefFileListProvider.listPreferenceFiles(loadMetadata = true)) + binding.recyclerview.layoutManager = LinearLayoutManager(this) + binding.recyclerview.adapter = RecyclerViewAdapter(prefFileListProvider.listPreferenceFiles(loadMetadata = true)) } inner class RecyclerViewAdapter internal constructor(private var prefFileList: List) : RecyclerView.Adapter() { - inner class PrefFileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - - var fileName: TextView = itemView.findViewById(R.id.filelist_name) - var fileDir: TextView = itemView.findViewById(R.id.filelist_dir) - var metaDateTime: TextView = itemView.findViewById(R.id.meta_date_time) - var metaDeviceName: TextView = itemView.findViewById(R.id.meta_device_name) - var metaAppVersion: TextView = itemView.findViewById(R.id.meta_app_version) - var metaVariantFormat: TextView = itemView.findViewById(R.id.meta_variant_format) - - var metalineName: View = itemView.findViewById(R.id.metaline_name) - var metaDateTimeIcon: View = itemView.findViewById(R.id.meta_date_time_icon) + inner class PrefFileViewHolder(val maintenanceImportListItemBinding: MaintenanceImportListItemBinding) : RecyclerView.ViewHolder(maintenanceImportListItemBinding.root) { init { - itemView.isClickable = true - itemView.setOnClickListener { - val prefFile = fileName.tag as PrefsFile - val i = Intent() + with(maintenanceImportListItemBinding) { + root.isClickable = true + maintenanceImportListItemBinding.root.setOnClickListener { + val prefFile = filelistName.tag as PrefsFile + val i = Intent() - i.putExtra(PrefsFileContract.OUTPUT_PARAM, prefFile) - setResult(FragmentActivity.RESULT_OK, i) - finish() + i.putExtra(PrefsFileContract.OUTPUT_PARAM, prefFile) + setResult(FragmentActivity.RESULT_OK, i) + finish() + } } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PrefFileViewHolder { - val v = LayoutInflater.from(parent.context).inflate(R.layout.maintenance_importlist_item, parent, false) - return PrefFileViewHolder(v) + val binding = MaintenanceImportListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return PrefFileViewHolder(binding) } override fun getItemCount(): Int { @@ -81,44 +77,45 @@ class PrefImportListActivity : DaggerAppCompatActivity() { override fun onBindViewHolder(holder: PrefFileViewHolder, position: Int) { val prefFile = prefFileList[position] - holder.fileName.text = prefFile.file.name - holder.fileName.tag = prefFile + with(holder.maintenanceImportListItemBinding) { + filelistName.text = prefFile.file.name + filelistName.tag = prefFile - holder.fileDir.text = resourceHelper.gs(R.string.in_directory, prefFile.file.parentFile.absolutePath) + filelistDir.text = resourceHelper.gs(R.string.in_directory, prefFile.file.parentFile.absolutePath) - val visible = if (prefFile.handler == PrefsFormatsHandler.CLASSIC) View.GONE else View.VISIBLE - holder.metalineName.visibility = visible - holder.metaDateTimeIcon.visibility = visible - holder.metaAppVersion.visibility = visible + val visible = (prefFile.handler != PrefsFormatsHandler.CLASSIC).toVisibility() + metalineName.visibility = visible + metaDateTimeIcon.visibility = visible + metaAppVersion.visibility = visible - if (prefFile.handler == PrefsFormatsHandler.CLASSIC) { - holder.metaVariantFormat.text = resourceHelper.gs(R.string.metadata_format_old) - holder.metaVariantFormat.setTextColor(resourceHelper.gc(R.color.metadataTextWarning)) - holder.metaDateTime.text = " " - } else { + if (prefFile.handler == PrefsFormatsHandler.CLASSIC) { + metaVariantFormat.text = resourceHelper.gs(R.string.metadata_format_old) + metaVariantFormat.setTextColor(resourceHelper.gc(R.color.metadataTextWarning)) + metaDateTime.text = " " + } else { + + prefFile.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.let { + metaVariantFormat.text = it.value + val color = if (it.status == PrefsStatus.OK) R.color.metadataOk else R.color.metadataTextWarning + metaVariantFormat.setTextColor(resourceHelper.gc(color)) + } + + prefFile.metadata[PrefsMetadataKey.CREATED_AT]?.let { + metaDateTime.text = prefFileListProvider.formatExportedAgo(it.value) + } + + prefFile.metadata[PrefsMetadataKey.AAPS_VERSION]?.let { + metaAppVersion.text = it.value + val color = if (it.status == PrefsStatus.OK) R.color.metadataOk else R.color.metadataTextWarning + metaAppVersion.setTextColor(resourceHelper.gc(color)) + } + + prefFile.metadata[PrefsMetadataKey.DEVICE_NAME]?.let { + metaDeviceName.text = it.value + } - prefFile.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.let { - holder.metaVariantFormat.text = it.value - val color = if (it.status == PrefsStatus.OK) R.color.metadataOk else R.color.metadataTextWarning - holder.metaVariantFormat.setTextColor(resourceHelper.gc(color)) } - - prefFile.metadata[PrefsMetadataKey.CREATED_AT]?.let { - holder.metaDateTime.text = prefFileListProvider.formatExportedAgo(it.value) - } - - prefFile.metadata[PrefsMetadataKey.AAPS_VERSION]?.let { - holder.metaAppVersion.text = it.value - val color = if (it.status == PrefsStatus.OK) R.color.metadataOk else R.color.metadataTextWarning - holder.metaAppVersion.setTextColor(resourceHelper.gc(color)) - } - - prefFile.metadata[PrefsMetadataKey.DEVICE_NAME]?.let { - holder.metaDeviceName.text = it.value - } - } - } } diff --git a/core/src/main/java/info/nightscout/androidaps/utils/permissions/OptimizationPermissionContract.kt b/core/src/main/java/info/nightscout/androidaps/utils/permissions/OptimizationPermissionContract.kt new file mode 100644 index 0000000000..34d6a1a36d --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/utils/permissions/OptimizationPermissionContract.kt @@ -0,0 +1,20 @@ +package info.nightscout.androidaps.utils.permissions + +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.provider.Settings +import androidx.activity.result.contract.ActivityResultContract + +class OptimizationPermissionContract : ActivityResultContract() { + + override fun parseResult(resultCode: Int, intent: Intent?): Unit? = null + + override fun createIntent(context: Context, input: Void?): Intent { + return Intent().also { + it.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + it.data = Uri.parse("package:" + context.packageName) + } + } +} + diff --git a/core/src/main/res/layout/maintenance_importlist_activity.xml b/core/src/main/res/layout/maintenance_import_list_activity.xml similarity index 94% rename from core/src/main/res/layout/maintenance_importlist_activity.xml rename to core/src/main/res/layout/maintenance_import_list_activity.xml index 0bdd43b927..896a3888f2 100644 --- a/core/src/main/res/layout/maintenance_importlist_activity.xml +++ b/core/src/main/res/layout/maintenance_import_list_activity.xml @@ -11,7 +11,7 @@ android:orientation="vertical"> We have detected that you are running an invalid version. Loop disabled! Version %1$s available + + Please reboot your phone or restart AndroidAPS from the System Settings \notherwise Android APS will not have logging (important to track and verify that the algorithms are working correctly)! + %1$d day %1$d days diff --git a/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaHistoryActivity.kt b/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaHistoryActivity.kt index 82cd99c1ab..9f9fd0e1a7 100644 --- a/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaHistoryActivity.kt +++ b/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaHistoryActivity.kt @@ -31,7 +31,6 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.extensions.plusAssign -import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import java.util.* @@ -41,7 +40,6 @@ class DanaHistoryActivity : NoSplashAppCompatActivity() { @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var aapsLogger: AAPSLogger - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var activePlugin: ActivePluginProvider diff --git a/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaUserOptionsActivity.kt b/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaUserOptionsActivity.kt index ba1c16bab6..70ff917df7 100644 --- a/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaUserOptionsActivity.kt +++ b/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaUserOptionsActivity.kt @@ -19,7 +19,6 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.extensions.plusAssign -import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import java.text.DecimalFormat @@ -32,7 +31,6 @@ class DanaUserOptionsActivity : NoSplashAppCompatActivity() { @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var fabricPrivacy: FabricPrivacy - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var context: Context @Inject lateinit var danaPump: DanaPump @Inject lateinit var activePlugin: ActivePluginProvider diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/activities/EnterPinActivity.kt b/danars/src/main/java/info/nightscout/androidaps/danars/activities/EnterPinActivity.kt index 5efdfbd757..a61c5e330a 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/activities/EnterPinActivity.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/activities/EnterPinActivity.kt @@ -12,7 +12,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.extensions.hexStringToByteArray -import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.textValidator.DefaultEditTextValidator import info.nightscout.androidaps.utils.textValidator.EditTextValidator @@ -25,7 +24,6 @@ class EnterPinActivity : NoSplashAppCompatActivity() { @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var fabricPrivacy: FabricPrivacy - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var danaRSPlugin: DanaRSPlugin @Inject lateinit var sp: SP @Inject lateinit var bleComm: BLEComm diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt index 43d032991d..12f3153a91 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt @@ -30,7 +30,6 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.extensions.plusAssign import info.nightscout.androidaps.utils.extensions.toVisibility -import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.ui.UIRunnable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable @@ -43,7 +42,6 @@ import javax.inject.Inject class PodManagementActivity : NoSplashAppCompatActivity() { @Inject lateinit var rxBus: RxBusWrapper - @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var podStateManager: PodStateManager From 9eaeafea3f5c7c0025b05b13a2e2b0a3c22e32fe Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 18 Jan 2021 23:59:01 +0100 Subject: [PATCH 25/61] jetpack bindings in core --- core/build.gradle | 2 +- .../androidaps/dialogs/BolusProgressDialog.kt | 46 ++++++--- .../androidaps/dialogs/NtpProgressDialog.kt | 52 ++++++---- .../androidaps/dialogs/ProfileViewerDialog.kt | 91 ++++++++++-------- .../plugins/general/maintenance/PrefsFile.kt | 4 +- .../maintenance/formats/PrefsFormat.kt | 2 +- .../main/res/layout/dialog_bolusprogress.xml | 30 +++--- .../main/res/layout/dialog_profileviewer.xml | 94 ++++++++++--------- 8 files changed, 183 insertions(+), 138 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index e5537cf13b..e0c69ddb78 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' +apply plugin: 'kotlin-parcelize' android { compileSdkVersion 28 diff --git a/core/src/main/java/info/nightscout/androidaps/dialogs/BolusProgressDialog.kt b/core/src/main/java/info/nightscout/androidaps/dialogs/BolusProgressDialog.kt index 06e99dc20a..22e5e0467f 100644 --- a/core/src/main/java/info/nightscout/androidaps/dialogs/BolusProgressDialog.kt +++ b/core/src/main/java/info/nightscout/androidaps/dialogs/BolusProgressDialog.kt @@ -10,6 +10,7 @@ import android.view.WindowManager import dagger.android.support.DaggerDialogFragment import info.nightscout.androidaps.activities.BolusProgressHelperActivity import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.core.databinding.DialogBolusprogressBinding import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.logging.AAPSLogger @@ -21,10 +22,10 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable -import kotlinx.android.synthetic.main.dialog_bolusprogress.* import javax.inject.Inject class BolusProgressDialog : DaggerDialogFragment() { + @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var resourceHelper: ResourceHelper @@ -34,6 +35,7 @@ class BolusProgressDialog : DaggerDialogFragment() { private val disposable = CompositeDisposable() companion object { + @JvmField var bolusEnded = false @@ -57,31 +59,39 @@ class BolusProgressDialog : DaggerDialogFragment() { return this } + private var _binding: DialogBolusprogressBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + savedInstanceState: Bundle?): View { dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE) dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) isCancelable = false dialog?.setCanceledOnTouchOutside(false) - return inflater.inflate(R.layout.dialog_bolusprogress, container, false) + + _binding = DialogBolusprogressBinding.inflate(inflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { savedInstanceState?.let { amount = it.getDouble("amount") } - overview_bolusprogress_title.text = resourceHelper.gs(R.string.goingtodeliver, amount) - overview_bolusprogress_stop.setOnClickListener { + binding.title.text = resourceHelper.gs(R.string.goingtodeliver, amount) + binding.stop.setOnClickListener { aapsLogger.debug(LTag.UI, "Stop bolus delivery button pressed") stopPressed = true - overview_bolusprogress_stoppressed.visibility = View.VISIBLE - overview_bolusprogress_stop.visibility = View.INVISIBLE + binding.stoppressed.visibility = View.VISIBLE + binding.stop.visibility = View.INVISIBLE commandQueue.cancelAllBoluses() } val defaultState = resourceHelper.gs(R.string.waitingforpump) - overview_bolusprogress_progressbar.max = 100 + binding.progressbar.max = 100 state = savedInstanceState?.getString("state", defaultState) ?: defaultState - overview_bolusprogress_status.text = state + binding.status.text = state stopPressed = false } @@ -102,7 +112,7 @@ class BolusProgressDialog : DaggerDialogFragment() { disposable.add(rxBus .toObservable(EventPumpStatusChanged::class.java) .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ overview_bolusprogress_status.text = it.getStatus(resourceHelper) }) { fabricPrivacy.logException(it) } + .subscribe({ binding.status.text = it.getStatus(resourceHelper) }) { fabricPrivacy.logException(it) } ) disposable.add(rxBus .toObservable(EventDismissBolusProgressIfRunning::class.java) @@ -114,10 +124,10 @@ class BolusProgressDialog : DaggerDialogFragment() { .observeOn(AndroidSchedulers.mainThread()) .subscribe({ aapsLogger.debug(LTag.UI, "Status: ${it.status} Percent: ${it.percent}") - overview_bolusprogress_status.text = it.status - overview_bolusprogress_progressbar.progress = it.percent + binding.status.text = it.status + binding.progressbar.progress = it.percent if (it.percent == 100) { - overview_bolusprogress_stop.visibility = View.INVISIBLE + binding.stop.visibility = View.INVISIBLE scheduleDismiss() } state = it.status @@ -151,9 +161,15 @@ class BolusProgressDialog : DaggerDialogFragment() { outState.putDouble("amount", amount) } + override fun onDestroyView() { + super.onDestroyView() + disposable.clear() + _binding = null + } + private fun scheduleDismiss() { aapsLogger.debug(LTag.UI, "scheduleDismiss") - Thread(Runnable { + Thread { SystemClock.sleep(5000) bolusEnded = true activity?.runOnUiThread { @@ -166,6 +182,6 @@ class BolusProgressDialog : DaggerDialogFragment() { } } } - }).start() + }.start() } } diff --git a/core/src/main/java/info/nightscout/androidaps/dialogs/NtpProgressDialog.kt b/core/src/main/java/info/nightscout/androidaps/dialogs/NtpProgressDialog.kt index 176e6fba88..927d8cf70c 100644 --- a/core/src/main/java/info/nightscout/androidaps/dialogs/NtpProgressDialog.kt +++ b/core/src/main/java/info/nightscout/androidaps/dialogs/NtpProgressDialog.kt @@ -7,6 +7,7 @@ import android.view.View import android.view.ViewGroup import dagger.android.support.DaggerDialogFragment import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.core.databinding.DialogBolusprogressBinding import info.nightscout.androidaps.events.EventNtpStatus import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag @@ -16,10 +17,10 @@ import info.nightscout.androidaps.utils.extensions.plusAssign import info.nightscout.androidaps.utils.resources.ResourceHelper import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable -import kotlinx.android.synthetic.main.dialog_bolusprogress.* import javax.inject.Inject class NtpProgressDialog : DaggerDialogFragment() { + @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var resourceHelper: ResourceHelper @@ -30,26 +31,33 @@ class NtpProgressDialog : DaggerDialogFragment() { private var state: String? = null private var percent = 0 + private var _binding: DialogBolusprogressBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + savedInstanceState: Bundle?): View { isCancelable = false state = savedInstanceState?.getString("state", null) percent = savedInstanceState?.getInt("percent", 0) ?: 0 - return inflater.inflate(R.layout.dialog_bolusprogress, container, false) + _binding = DialogBolusprogressBinding.inflate(inflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val defaultMessage = resourceHelper.gs(R.string.timedetection) dialog?.setTitle(resourceHelper.gs(R.string.objectives)) - overview_bolusprogress_stop.setOnClickListener { dismiss() } - overview_bolusprogress_status.text = state ?: defaultMessage - overview_bolusprogress_progressbar.max = 100 - overview_bolusprogress_progressbar.progress = percent - overview_bolusprogress_stop.text = resourceHelper.gs(R.string.close) - overview_bolusprogress_title.text = resourceHelper.gs(R.string.please_wait) + binding.stop.setOnClickListener { dismiss() } + binding.status.text = state ?: defaultMessage + binding.progressbar.max = 100 + binding.progressbar.progress = percent + binding.stop.text = resourceHelper.gs(R.string.close) + binding.title.text = resourceHelper.gs(R.string.please_wait) } override fun onResume() { @@ -65,16 +73,18 @@ class NtpProgressDialog : DaggerDialogFragment() { .toObservable(EventNtpStatus::class.java) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ event: EventNtpStatus -> - aapsLogger.debug(LTag.UI, "Status: " + event.status + " Percent: " + event.percent) - overview_bolusprogress_status?.text = event.status - overview_bolusprogress_progressbar?.progress = event.percent - if (event.percent == 100) { - SystemClock.sleep(100) - dismiss() + if (_binding != null) { + aapsLogger.debug(LTag.UI, "Status: " + event.status + " Percent: " + event.percent) + binding.status.text = event.status + binding.progressbar.progress = event.percent + if (event.percent == 100) { + SystemClock.sleep(100) + dismiss() + } + state = event.status + percent = event.percent } - state = event.status - percent = event.percent - }) { fabricPrivacy.logException(it) } + }, fabricPrivacy::logException) } override fun onPause() { @@ -83,6 +93,12 @@ class NtpProgressDialog : DaggerDialogFragment() { disposable.clear() } + override fun onDestroyView() { + super.onDestroyView() + disposable.clear() + _binding = null + } + override fun onSaveInstanceState(outState: Bundle) { outState.putString("state", state) outState.putInt("percent", percent) diff --git a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt index b9223dd1e0..f905d7b40d 100644 --- a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt +++ b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt @@ -11,21 +11,20 @@ import dagger.android.HasAndroidInjector import dagger.android.support.DaggerDialogFragment import info.nightscout.androidaps.Constants import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.core.databinding.DialogProfileviewerBinding import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.resources.ResourceHelper -import kotlinx.android.synthetic.main.close.* -import kotlinx.android.synthetic.main.dialog_profileviewer.* import org.json.JSONObject import java.text.DecimalFormat import javax.inject.Inject class ProfileViewerDialog : DaggerDialogFragment() { + @Inject lateinit var injector: HasAndroidInjector @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var activePlugin: ActivePluginProvider @@ -48,8 +47,14 @@ class ProfileViewerDialog : DaggerDialogFragment() { private var customProfileName: String = "" private var customProfileUnits: String = Constants.MGDL + private var _binding: DialogProfileviewerBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + savedInstanceState: Bundle?): View { // load data from bundle (savedInstanceState ?: arguments)?.let { bundle -> time = bundle.getLong("time", 0) @@ -66,13 +71,14 @@ class ProfileViewerDialog : DaggerDialogFragment() { isCancelable = true dialog?.setCanceledOnTouchOutside(false) - return inflater.inflate(R.layout.dialog_profileviewer, container, false) + _binding = DialogProfileviewerBinding.inflate(inflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - close.setOnClickListener { dismiss() } + binding.closeLayout.close.setOnClickListener { dismiss() } val profile: Profile? val profile2: Profile? @@ -85,7 +91,7 @@ class ProfileViewerDialog : DaggerDialogFragment() { profileName = activePlugin.activeTreatments.getProfileSwitchFromHistory(time)?.customizedName date = dateUtil.dateAndTimeString(activePlugin.activeTreatments.getProfileSwitchFromHistory(time)?.date ?: 0) - profileview_datelayout.visibility = View.VISIBLE + binding.datelayout.visibility = View.VISIBLE } Mode.CUSTOM_PROFILE -> { @@ -93,16 +99,16 @@ class ProfileViewerDialog : DaggerDialogFragment() { profile2 = null profileName = customProfileName date = "" - profileview_datelayout.visibility = View.GONE + binding.datelayout.visibility = View.GONE } Mode.PROFILE_COMPARE -> { profile = Profile(injector, JSONObject(customProfileJson), customProfileUnits) profile2 = Profile(injector, JSONObject(customProfileJson2), customProfileUnits) profileName = customProfileName - header_icon.setImageResource(R.drawable.ic_compare_profiles) + binding.headerIcon.setImageResource(R.drawable.ic_compare_profiles) date = "" - profileview_datelayout.visibility = View.GONE + binding.datelayout.visibility = View.GONE } Mode.DB_PROFILE -> { @@ -111,43 +117,43 @@ class ProfileViewerDialog : DaggerDialogFragment() { profile2 = null profileName = if (profileList.isNotEmpty()) profileList[0].customizedName else null date = if (profileList.isNotEmpty()) dateUtil.dateAndTimeString(profileList[0].date) else null - profileview_datelayout.visibility = View.VISIBLE + binding.datelayout.visibility = View.VISIBLE } } - profileview_noprofile.visibility = View.VISIBLE + binding.noprofile.visibility = View.VISIBLE if (mode == Mode.PROFILE_COMPARE) profile?.let { profile1 -> profile2?.let { profile2 -> - profileview_units.text = profileFunction.getUnits() - profileview_dia.text = HtmlHelper.fromHtml(formatColors("", profile1.dia, profile2.dia, DecimalFormat("0.00"), resourceHelper.gs(R.string.shorthour))) - val profileNames =profileName!!.split("\n").toTypedArray() - profileview_activeprofile.text = HtmlHelper.fromHtml(formatColors(profileNames[0], profileNames[1])) - profileview_date.text = date - profileview_ic.text = ics(profile1, profile2) - profileview_isf.text = isfs(profile1, profile2) - profileview_basal.text = basals(profile1, profile2) - profileview_target.text = targets(profile1, profile2) - basal_graph.show(profile1, profile2) + binding.units.text = profileFunction.getUnits() + binding.dia.text = HtmlHelper.fromHtml(formatColors("", profile1.dia, profile2.dia, DecimalFormat("0.00"), resourceHelper.gs(R.string.shorthour))) + val profileNames = profileName!!.split("\n").toTypedArray() + binding.activeprofile.text = HtmlHelper.fromHtml(formatColors(profileNames[0], profileNames[1])) + binding.date.text = date + binding.ic.text = ics(profile1, profile2) + binding.isf.text = isfs(profile1, profile2) + binding.basal.text = basals(profile1, profile2) + binding.target.text = targets(profile1, profile2) + binding.basalGraph.show(profile1, profile2) } - profileview_noprofile.visibility = View.GONE - profileview_invalidprofile.visibility = if (profile1.isValid("ProfileViewDialog")) View.GONE else View.VISIBLE + binding.noprofile.visibility = View.GONE + binding.invalidprofile.visibility = if (profile1.isValid("ProfileViewDialog")) View.GONE else View.VISIBLE } else profile?.let { - profileview_units.text = it.units - profileview_dia.text = resourceHelper.gs(R.string.format_hours, it.dia) - profileview_activeprofile.text = profileName - profileview_date.text = date - profileview_ic.text = it.icList - profileview_isf.text = it.isfList - profileview_basal.text = it.basalList - profileview_target.text = it.targetList - basal_graph.show(it) + binding.units.text = it.units + binding.dia.text = resourceHelper.gs(R.string.format_hours, it.dia) + binding.activeprofile.text = profileName + binding.date.text = date + binding.ic.text = it.icList + binding.isf.text = it.isfList + binding.basal.text = it.basalList + binding.target.text = it.targetList + binding.basalGraph.show(it) - profileview_noprofile.visibility = View.GONE - profileview_invalidprofile.visibility = if (it.isValid("ProfileViewDialog")) View.GONE else View.VISIBLE + binding.noprofile.visibility = View.GONE + binding.invalidprofile.visibility = if (it.isValid("ProfileViewDialog")) View.GONE else View.VISIBLE } } @@ -167,6 +173,11 @@ class ProfileViewerDialog : DaggerDialogFragment() { bundle.putString("customProfile2", customProfileJson2) } + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + private fun formatColors(label: String, value1: Double, value2: Double, format: DecimalFormat, units: String): String { return formatColors(label, format.format(value1), format.format(value2), units) } @@ -226,7 +237,7 @@ class ProfileViewerDialog : DaggerDialogFragment() { prev1 = val1 prev2 = val2 } - return HtmlHelper.fromHtml(s.delete(s.length-4, s.length).toString()) + return HtmlHelper.fromHtml(s.delete(s.length - 4, s.length).toString()) } private fun isfs(profile1: Profile, profile2: Profile): Spanned { @@ -244,10 +255,10 @@ class ProfileViewerDialog : DaggerDialogFragment() { prev1 = val1 prev2 = val2 } - return HtmlHelper.fromHtml(s.delete(s.length-4, s.length).toString()) + return HtmlHelper.fromHtml(s.delete(s.length - 4, s.length).toString()) } - private fun targets(profile1: Profile, profile2: Profile):Spanned { + private fun targets(profile1: Profile, profile2: Profile): Spanned { var prev1l = -1.0 var prev1h = -1.0 var prev2l = -1.0 @@ -261,7 +272,7 @@ class ProfileViewerDialog : DaggerDialogFragment() { val val2h = profile2.getTargetHighMgdlTimeFromMidnight(hour * 60 * 60) val txt1 = Profile.format_HH_MM(hour * 60 * 60) + " " + Profile.toUnitsString(val1l, val1l * Constants.MGDL_TO_MMOLL, units) + " - " + Profile.toUnitsString(val1h, val1h * Constants.MGDL_TO_MMOLL, units) + " " + units val txt2 = Profile.format_HH_MM(hour * 60 * 60) + " " + Profile.toUnitsString(val2l, val2l * Constants.MGDL_TO_MMOLL, units) + " - " + Profile.toUnitsString(val2h, val2h * Constants.MGDL_TO_MMOLL, units) + " " + units - if (val1l != prev1l || val1h != prev1h || val2l != prev2l || val2h != prev2h ) { + if (val1l != prev1l || val1h != prev1h || val2l != prev2l || val2h != prev2h) { s.append(formatColors(txt1, txt2)) s.append("
") } @@ -270,6 +281,6 @@ class ProfileViewerDialog : DaggerDialogFragment() { prev2l = val2l prev2h = val2h } - return HtmlHelper.fromHtml(s.delete(s.length-4, s.length).toString()) + return HtmlHelper.fromHtml(s.delete(s.length - 4, s.length).toString()) } } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFile.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFile.kt index 8efcbca36b..7caf7791f0 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFile.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/PrefsFile.kt @@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.general.maintenance import android.os.Parcelable import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefMetadata import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey -import kotlinx.android.parcel.Parcelize -import kotlinx.android.parcel.RawValue +import kotlinx.parcelize.RawValue +import kotlinx.parcelize.Parcelize import java.io.File @Parcelize diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt index 01a58461c7..42cfa18f1e 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/formats/PrefsFormat.kt @@ -5,7 +5,7 @@ import android.os.Parcelable import androidx.annotation.DrawableRes import androidx.annotation.StringRes import info.nightscout.androidaps.core.R -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize import java.io.File enum class PrefsMetadataKey(val key: String, @DrawableRes val icon: Int, @StringRes val label: Int) { diff --git a/core/src/main/res/layout/dialog_bolusprogress.xml b/core/src/main/res/layout/dialog_bolusprogress.xml index b20b64b8e5..cd080eec64 100644 --- a/core/src/main/res/layout/dialog_bolusprogress.xml +++ b/core/src/main/res/layout/dialog_bolusprogress.xml @@ -4,8 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - tools:context="info.nightscout.androidaps.dialogs.BolusProgressDialog" -> + tools:context="info.nightscout.androidaps.dialogs.BolusProgressDialog"> @@ -41,16 +40,17 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:padding="5dp" /> - + +