214 Commits

Author SHA1 Message Date
Timi
1d33cc3135 Updater: push-update: unroot on exit if zip exists
Change-Id: I10ccb345d02830337bc8aefa4f3d41e80e42d064
2024-12-17 18:19:02 +00:00
Giovanni Ricca
ed36157049 Updater: Set SYSTEM_UPDATE_SETTINGS priority higher than GMS
For whatever reason, when both SYSTEM_UPDATE_SETTINGS components have
the same priority and the first one is disabled (in this case, the GMS
one), it doesn't seem to fallback to the next enabled one and instead
shows a "No apps can perform this action" message. To avoid that, let's
just set higher priority.

9a6853 com.google.android.gms/.update.SystemUpdateActivity filter b9e590
  Action: "android.settings.SYSTEM_UPDATE_SETTINGS"
  Category: "android.intent.category.DEFAULT"
  mPriority=1, mOrder=0, mHasStaticPartialTypes=false, mHasDynamicPartialTypes=false

Change-Id: I886a714304fe6d1906af7e1702ecaf2238bd8cb0
2024-11-11 10:55:02 +01:00
LineageOS Infra
a72dadf7e3 Automatic translation import
Change-Id: I5740bd6f9c095b3e7d0a8207e7541f7506480931
2024-10-31 17:49:49 +00:00
Salvo Giangreco
3cb130d40a Updater: Fix broken download ETA/progress
Change-Id: I1d7b5ecf7779d08c5d617d8c0950b24fbe7d0733
2024-10-02 16:42:50 +00:00
LineageOS Infra
e6edfaab94 Automatic translation import
Change-Id: I82c651eefb62882cec8bb4ee914ee5d9b56264c9
2024-10-01 20:14:22 +00:00
LineageOS Infra
34535a83fb Automatic translation import
Change-Id: Ia65d6e242fa1cbcbec79755974bc5afd8c4afd0d
2024-09-15 16:02:37 +00:00
LineageOS Infra
8d0b616fec Automatic translation import
Change-Id: I7c5a0601e46bfe371c38b07cb2f432fede1d2647
2024-09-02 23:16:27 +00:00
LineageOS Infra
6ef2ee7a34 Automatic translation import
Change-Id: Ieec62f872ff664b0411247876cdb1fa858f7ccab
2024-08-15 20:24:22 +00:00
Michael W
7c5230326f Updater: Append trailing slash to upgrade url
* It gets appended after calling anyway
* Having the url at the end of a linkified message with a dot after it
  (end of sentence, e.g. russian), the dot is also linkified resulting
  in
  https://wiki.lineageos.org/devices/<device>/upgrade.
  which won't work, while the slash makes it work
  (with the linkified dot)

Fixes: https://gitlab.com/LineageOS/issues/android/-/issues/7248
Change-Id: Iaacd61267ad886c23393e34071a191a2e08d4009
2024-07-19 17:29:23 +00:00
Michael W
0d1c94fe5a Updater: Round dialogs
Change-Id: Icc5ea5a27e48ec74158588ba11a0277b6f0404cf
2024-06-28 20:18:38 +00:00
LineageOS Infra
8b6c6728ac Automatic translation import
Change-Id: Ib7cf69f228616a1e1d5fb4c9d17de6c233bc861a
2024-06-15 18:21:16 +00:00
LuK1337
4a536da4be Updater: Use https:// for wiki URL
Change-Id: I9b18ce7ea75d7248dd04a5603e80139afc8e6e09
2024-06-06 10:33:42 +02:00
LineageOS Infra
a6ce04aefc Automatic translation import
Change-Id: I4f9f0369ecff6df84e4f824f5e016663fcfe0a28
2024-06-01 22:14:29 +00:00
LuK1337
36c5333f2d Updater: Handle ErrorCode::kUpdateAlreadyInstalled more gracefully
If applyPayload() fails with kUpdateAlreadyInstalled, mark update as
already installed. While this is not ideal since this might not be the
update we actually installed, it's still better than outright dying.

Test: install update, unset needs_reboot_id, kill updater, install
      update again.
Change-Id: Iac264896cffd1db522d81fc2050eb71d62ca91bf
2024-05-17 14:33:12 +00:00
LineageOS Infra
93adf96d12 Automatic translation import
Change-Id: If6cce2f888b32a71567597822a39c2638d65cfca
2024-05-15 15:50:39 +00:00
LuK1337
ddbb843309 Updater: Add /mnt/scratch detection
Change-Id: Ie4d408791c24ce0b592882a0e6c5af12bd16addb
2024-05-02 18:58:57 +00:00
LineageOS Infra
d1d28de8e7 Automatic translation import
Change-Id: I52e976d00a3cf32fa248331d3026d844f03d84df
2024-05-01 16:33:52 +00:00
LineageOS Infra
c9eada5848 Automatic translation import
Change-Id: If4758d368b57157a6c5ec1de7a9dad0c9ae05113
2024-02-18 19:38:55 +00:00
LineageOS Infra
76c126c8af Automatic translation import
Change-Id: I855069d4b214900b32f88a6ec73cb7b2abb07b99
2024-02-10 19:04:56 +00:00
Bruno Martins
27af047c21 Updater: Override SystemUpdater
It is the "Local System Updates" seen in Automotive builds.

Change-Id: If81451e65f55445db000a3a92f3badce8f9ed8e2
2024-01-20 02:26:23 +00:00
Bartłomiej Rudecki
7d9b6c0c64 Updater: Define foregroundServiceType
Required since Android 14 [1].

11-16 14:05:45.363 20623 20623 E AndroidRuntime: FATAL EXCEPTION: main
11-16 14:05:45.363 20623 20623 E AndroidRuntime: Process: org.lineageos.updater, PID: 20623
11-16 14:05:45.363 20623 20623 E AndroidRuntime: android.app.MissingForegroundServiceTypeException: Starting FGS without a type  callerApp=ProcessRecord{6d14558 20623:org.lineageos.updater/u0a149} targetSDK=34

[1] https://developer.android.com/about/versions/14/changes/fgs-types-required

Change-Id: Id6217424177b94d37621062fb1a55778f1dabbab
2023-11-16 22:11:39 +01:00
LineageOS Infra
0b1821c9dc Automatic translation import
Change-Id: I8615afa7afd004f98d18b482f4fa2e946476bf99
2023-11-15 18:52:18 +00:00
LineageOS Infra
a804504378 Automatic translation import
Change-Id: I02c7f9741ab977fb62b0f652fa84e6011feb7dee
2023-11-01 17:29:18 +00:00
LineageOS Infra
7f43b5b628 Automatic translation import
Change-Id: I9f3ad5b2c365df52d808116fe30ee94ab19686f9
2023-10-15 20:43:22 +00:00
LineageOS Infra
3f365d5feb Automatic translation import
Change-Id: I881449a5def2e3e649cda736c10bd6bf119b84d9
2023-10-01 16:33:00 +00:00
LuK1337
64261f1321 Updater: Use generateBp plugin
Change-Id: Ic5431575b684ee2d416d5707e499f0cf538ce4c4
2023-09-18 13:12:06 +02:00
LineageOS Infra
5c17826dcd Automatic translation import
Change-Id: Icff4f920131242cf530f31231cd3ed9916159d11
2023-09-15 17:53:31 +00:00
LineageOS Infra
919a15e270 Automatic translation import
Change-Id: Idd77531a68e9f28c96dd08bf7beceefbb94d7b0a
2023-09-01 14:42:24 +00:00
Joey
5a212ca159 Updater: add support for local updates
Allow importing and installation of OTA files already
downloaded instead of requiring to reboot to recovery
to install them.

Squash of:
- Add support for importing local updates
  Signed-off-by: Joey <jbevilacqua@shiftphones.com>
  Change-Id: I64ca3a6af29bdf8b2c6023a502f23080a27fd79e
- OTA: read timestamp from imported zip metadata
  Signed-off-by: Joey <jbevilacqua@shiftphones.com>
  Change-Id: I93a5c0be81adab9ba8e50afde0e09839f059c9e0
- OTA: fix UI issues with local update
  Signed-off-by: Joey <jbevilacqua@shiftphones.com>
  Change-Id: I07c8f5507bc52c254c3dc1468fea495a073ae96c
- OTA: fix local updates not being shown in UI (pt.2)
  Signed-off-by: Joey <jbevilacqua@shiftphones.com>
  Change-Id: Ife40eea05099eca9e1ee84c6f87d2715e5981cab
- OTA: ignore download status changes for local updates
  Signed-off-by: Joey <jbevilacqua@shiftphones.com>
  Change-Id: I198f9b5462718f8a6e5687c891f3bfc6b1c645bd
- UpdaterService: fix crash with local install
  Change-Id: I27b187cf4adec986d516e3017d1b3877691029b2
  Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
- Local updates: do not remove local update from ui after installation
  Change-Id: I869e090f26273006f933ad99c42b7c6a2e963797
  Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
- Local updates: modify display version
  Change-Id: I8a39e0936040bb9546499754ab4a9ef60c56aca0
  Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
- Local updates: show build date in import dialog
  Change-Id: I9014358ea1cf941e76fdd80a5147e9d924fc1a8f
  Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>

Change-Id: I64ca3a6af29bdf8b2c6023a502f23080a27fd79e
Signed-off-by: Joey <joey@lineageos.org>
Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
2023-08-24 17:57:21 +02:00
LineageOS Infra
5ff552fa43 Automatic translation import
Change-Id: Id05d7c44e5cb5d560ff621ba9a91482925b568e2
2023-07-15 18:08:10 +00:00
Michael W
185b5de51d Updater: Don't show delete twice
* If an update exists and can be deleted, the action button AND the
  popup menu both show the delete action
* By checking wether the action already shows "Delete" we can hide
  that action from the submenu
* Additionally check for online availability to only hide it when it's
  not the last item - otherwise a click on the menu icon wouldn't do
  anything

Change-Id: Idc5da3962be4e0a69847f47b3c5f014b251bd438
2023-07-08 15:23:17 -04:00
Michael W
613fbacdbf Updater: Fix header margin
* Instead of hardcoding it to 86dp (which was probably fine
  when we didn't have cutouts, calculate the required top margin
  by adding top inset and status bar height and applying it dynamically
* Increase compile and min sdk versions to avoid warnings - we compile
  using the build sdk (33) when building inline anyway

Change-Id: I80444e5a2247730f06af461a1cce7ac36c6c9631
2023-07-08 15:23:11 -04:00
Michael W
c3093cb4cc Updater: Align with Settings / Materialize
* Better integrate with Settings by changing the background
  so it matches the Toolbar - one solid background
* Make updates distinct cards with rounded border and
  add spacing between them

Change-Id: If9c649f63e9bb3762f2ae272c96f5e62e0821e46
2023-07-08 15:23:03 -04:00
Michael W
bf1646fa93 Updater: Handle NumberFormatException
* For cases like local Updates (not yet merged) and probably
  others, the parsing might fail and take down the Updater
* Handle NFE properly

Change-Id: If9609c59d1048c9d37aa6de90855e02f28d96ce2
2023-07-08 15:22:56 -04:00
Sebastiano Barezzi
755560bbcd Updater: Redo project structure
* Let's be more Android Studio friendly
* While at it match AOSP deps with Gradle ones and update them

Change-Id: Ib8829e3d954ce43fbf19280d1db2bc43c6fc89e0
2023-07-08 15:22:49 -04:00
LineageOS Infra
ae11300ff0 Automatic translation import
Change-Id: I3609a2dc8eb68bb479f2f101231de03e2b0de9e0
2023-07-01 16:12:33 +00:00
LineageOS Infra
3852db1751 Automatic translation import
Change-Id: Ide309b43c89b7efc78579ccc303b539a90662749
2023-06-20 16:28:32 +00:00
Michael W
1ec0b8d1de Updater: 20 and up are integers!
Not 20.0 but 20!

Change-Id: Iccbcd765ce2be60cef413a73461563569bc7cdc6
2023-06-05 19:19:52 +02:00
LineageOS Infra
0b5e925013 Automatic translation import
Change-Id: Ia202063d4d134323f36a5b494b0019d9f97cffff
2023-06-01 12:49:42 +00:00
althafvly
cdcb51197b Updater: Drop usage of NetworkInfo
- NetworkInfo is deprecated

Change-Id: I433bd5e89080931e9a2fdf1253d8e5f493ea2cbe
2023-05-22 15:05:02 +02:00
Bruno Martins
e32b81fb3a Updater: Check if network is really metered
Instead of assuming so, based on whether user is connected over
a WiFi or Ethernet connection, simply use the proper API.

Use default value of PREF_MOBILE_DATA_WARNING, if it had been
already set.

Change-Id: Ie4fa0301df7f2cebf94c967fc188acc54b2ce71e
Signed-off-by: althafvly <althafvly@gmail.com>
2023-05-22 15:04:54 +02:00
LineageOS Infra
9ddb4f10e0 Automatic translation import
Change-Id: I929cbcac278eca6c2aefc04f3d6e08b75d797f72
2023-05-15 09:16:34 +00:00
LineageOS Infra
85347e77d1 Automatic translation import
Change-Id: Ieaa98bc4483ecafe190dc992667132a2b309ba6d
2023-04-24 08:41:49 +00:00
Tommaso Fonda
bfbc440118 Updater: Show the correct percentage during package installation
Fixes the mismatch between the progress bar's status and the percentage
displayed next to it.

Fixes: https://gitlab.com/LineageOS/issues/android/-/issues/4830
Change-Id: I5c243acda4f06561cbd5b3a73060205b32d8d41d
2023-04-13 17:31:46 +02:00
Michael Bestas
e83f74ace7 Automatic translation import
Change-Id: Id98f9cc0e305b0425364dbb62639b483ad221bf7
2023-03-23 16:39:02 +02:00
Michael Bestas
304b45b3eb Automatic translation import
Change-Id: Ie2fa01b2491be5bed23c1280ed24725fd4f4b4b5
2023-02-13 16:05:54 +02:00
Michael Bestas
468ff36885 Automatic translation import
Change-Id: I08d6cc588245610a901d55d38488b542722ea20a
2023-01-10 04:42:11 +02:00
Michael Bestas
dfe9efc180 Automatic translation import
Change-Id: I56665d5c1bb65b94ef79be87b891b218dffcbbdf
2022-12-16 20:58:10 +02:00
althafvly
79845a7f0b Updater: Move PreferenceManager to AndroidX
Change-Id: I18c1c64652036359adcb47a34a2e565223f59e53
2022-11-28 20:35:23 +05:30
Michael Bestas
baf2238f5b Automatic translation import
Change-Id: Icb46946c7cec9f77b372627a7e2e6d5ca1e1dfad
2022-11-25 15:04:01 +02:00
Dil3mm4
59c5c5ff21 Updater: Add POST_NOTIFICATIONS permission & pre-grant it
Without the permission, Updater can't spawn notifications on
downloads/install

Reference: https://developer.android.com/develop/ui/views/notifications/notification-permission
Test: boot, download an update via updater, check notification drawer
Co-authored-by: Michael Bestas <mkbestas@lineageos.org>
Change-Id: I131c62ae5033f56f8915426f68f7aea76dba78dd
2022-11-15 00:07:09 +01:00
Michael Bestas
cb6281e7f0 Automatic translation import
Change-Id: I9d30d9157184ddde3f1145cac0e4108cebd42008
2022-11-03 20:11:06 +01:00
Michael Bestas
9ff0a26243 Automatic translation import
Change-Id: Icb95ebb843b9f212877e277463ed6ed02e02b2b8
2022-10-05 20:08:46 +03:00
Michael Bestas
8c2d4337b8 Automatic translation import
Change-Id: I88933a49fd3bbfffc6c9c1c45ccaca2779bb75e2
2022-09-22 15:30:24 +03:00
Aaron Kling
257a80e351 Use -television instead of -large-notouch for atv resources
Mobile builds on devices with no touch panel are also getting these
settings applied, which is not intended.

Change-Id: I02fac65dc7042c04259d6f65a957185aac32a252
2022-09-14 05:45:15 +02:00
Michael W
c25d43a9ca Automatic translation import
Change-Id: Ia33b8622d3f16e6d139e6ca63e9f4cc305e427cc
2022-08-15 15:50:00 +02:00
Michael Bestas
580c7ec218 Automatic translation import
Change-Id: I317e8fbd026393a3808915ee5e8beaf81afaee4c
2022-08-04 20:42:39 +03:00
Michael Bestas
b5dca5271f Automatic translation import
Change-Id: I359623d2a73f6f310f277551dfd7716ddd464291
2022-06-20 23:59:13 +03:00
LuK1337
c6d2a1694a Updater: Unbreak "Export update" feature
Fixes: https://gitlab.com/LineageOS/issues/android/-/issues/4736
Change-Id: I186a27d2e99098cf8ebb3dd5c7348cdb528baa78
2022-05-26 00:12:28 +02:00
Aayush Gupta
418d464d14 Updater: Show update's version on AlertDialog and Notification
Currently at most of the places, build version is obtained from BuildInfoUtils.getBuildVersion()
method. This method obtains build version from the current running system's property.

However, in case there is a version bump on OTA, this logic results in wrong version
being shown to the user while updating/upgrading the system.

Get the version from the update itself to show the proper version in update notification
and pre-install warning.

Signed-off-by: Aayush Gupta <theimpulson@e.email>
Change-Id: Ia74085d8d7c067c408e7cfce1de90d49dcc68307
2022-05-23 11:20:45 +05:30
Michael Bestas
55a4e6eb97 Automatic translation import
Change-Id: I44333045e0168a795a1a1a0440c3df71f44c7c7c
2022-05-10 21:58:51 +03:00
Arian
16cb5c2f25 UpdateInstaller: Set file permissions on uncrypt ota package
-----

E RecoverySystemService: Failed to reserve space for compressed apex:
E RecoverySystemService: java.io.FileNotFoundException: /data/lineageos_updates/lineage-19.1-20220422-UNOFFICIAL-GMS-sagit.zip.uncrypt (Permission denied)
E RecoverySystemService: 	at java.util.zip.ZipFile.open(Native Method)
E RecoverySystemService: 	at java.util.zip.ZipFile.<init>(ZipFile.java:265)
E RecoverySystemService: 	at java.util.zip.ZipFile.<init>(ZipFile.java:187)
E RecoverySystemService: 	at java.util.zip.ZipFile.<init>(ZipFile.java:158)
E RecoverySystemService: 	at com.android.server.recoverysystem.RecoverySystemService.getCompressedApexInfoList(RecoverySystemService.java:921)
E RecoverySystemService: 	at com.android.server.recoverysystem.RecoverySystemService.allocateSpaceForUpdate(RecoverySystemService.java:972)
E RecoverySystemService: 	at android.os.IRecoverySystem$Stub.onTransact(IRecoverySystem.java:156)
E RecoverySystemService: 	at android.os.Binder.execTransactInternal(Binder.java:1179)
E RecoverySystemService: 	at android.os.Binder.execTransact(Binder.java:1143)
E UpdateInstaller: Could not install update
E UpdateInstaller: java.io.IOException: Failed to allocate space for update /data/lineageos_updates/lineage-19.1-20220422-UNOFFICIAL-GMS-sagit.zip.uncrypt
E UpdateInstaller: 	at android.os.RecoverySystem.installPackage(RecoverySystem.java:678)
E UpdateInstaller: 	at android.os.RecoverySystem.installPackage(RecoverySystem.java:596)
E UpdateInstaller: 	at org.lineageos.updater.controller.UpdateInstaller.installPackage(UpdateInstaller.java:100)
E UpdateInstaller: 	at org.lineageos.updater.controller.UpdateInstaller.access$400(UpdateInstaller.java:35)
E UpdateInstaller: 	at org.lineageos.updater.controller.UpdateInstaller$1.run(UpdateInstaller.java:144)
E UpdateInstaller: 	at java.lang.Thread.run(Thread.java:920)

Change-Id: I8250bf58709b92572cdffc8e5faca4bf243935aa
2022-04-23 14:46:28 +02:00
Asher Simonds
bbf2442ad4 Updater: Bring in the new icon
* Part of the new iconset made by Asher Simonds

Co-authored-by: Michael W <baddaemon87@gmail.com>
Change-Id: Iead4aaf8fce32418ad86ca58c03c7e86f1067d78
2022-04-06 23:14:45 +02:00
Michael Bestas
6fe0ac8682 Automatic translation import
Change-Id: I4c859e7e41fcbe1cc51fbb3b541e2f092a3d808b
2022-04-03 20:09:01 +03:00
Michael W
1ffe1a80ae Updater: Don't show thousands of days
* When pausing and resuming, the ETA calculation is off by a lot
  due to the time diff since the last calculation resulting in a
  big delta and therefore a very low speed
* By fixing this, we also need to set the last byte count to the total
  byte count there, otherwise the downloaded bytes since last calculation
  will be larger than in reality, resulting in too fast speeds calculated

Change-Id: Ica1053cc297ff59221ea2bc0014f20973a080c88
2022-03-07 14:08:16 +00:00
Michael W
9ad96eca85 Updater: Move progress next to progressbar
Author: Michael W <baddaemon87@gmail.com>
Date:   Fri Feb 11 18:16:02 2022 +0100

    Updater: Move progress next to progressbar

    * The progress text can get very long, resulting in jumping marquee text
    * In order to reduce the length, move the percentage out of the text
      and next to the progressbar
    * The behavior can be observed e.g. on pro1 in german, where the button
      is also wider due to the german text

    Change-Id: I0276182efed757c0929b31434edad9be548b841c

Author: Timi Rautamäki <timi.rautamaki@gmail.com>
Date:   Thu Mar 3 16:12:16 2022 +0000

    fixup! Updater: Move progress next to progressbar

    Fix crash on ATV devices by applying same layout changes to
    layout-large-notouch.

    Change-Id: Id6eabcf8b1960106eb63bd15bcf97f9b4cf0bbc8

Change-Id: I8aed4c35c6ac4261c0536a6b263d63f5b1fd11ba
2022-03-07 14:08:01 +00:00
Alexander Martinz
27f04e5b78 Updater: layout: activity_updates: add spacing between build info and last checked entry
Change-Id: Ie85fecb30ba12b056569049aac674dc1b8653942
Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
2022-02-10 20:53:39 +00:00
Alexander Martinz
75497ee48b Updater: Allow starting activities from background
-----

05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: FATAL EXCEPTION: main
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: Process: com.shiftos.updater, PID: 19707
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.shiftos.updater/org.lineageos.updater.controller.UpdaterService }: app is in background uid UidRecord{1463ce2 u0a63 TPSL bg:+47m50s26ms idle change:idle procs:1 seq(0,0,0)}
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1616)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.ContextImpl.startService(ContextImpl.java:1571)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.content.ContextWrapper.startService(ContextWrapper.java:669)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at org.lineageos.updater.UpdatesActivity.onStart(UpdatesActivity.java:181)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1433)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.Activity.performStart(Activity.java:7847)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3295)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2017)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:107)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:214)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:7397)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
05-06 17:21:58.988 10063 19707 19707 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)

-----

Change-Id: Ibc2d471b028c1d4e824b3ede4bbc336d76801f88
Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
2022-02-10 20:53:39 +00:00
Joey
9edea6468c Updater: use consistent format for file sizes
Change-Id: I9a17cf2df69e2e39e90de169ca108511c71d4e31
Signed-off-by: Joey <joey@lineageos.org>
2022-02-10 20:53:39 +00:00
Michael W
d54176ccf7 Updater: Show toast when starting export
* It's not immediately clear that an export is started since the
  notification isn't intrusive
* Show a toast - that will be clear enough

Change-Id: I78d78b23884df3ddb37bc486c1d6012f899c888d
2022-02-10 20:53:39 +00:00
Michael W
f27d50d640 Updater: Switch to destination selector
* Let the user decide where to store the file
* That way it's not located in /storage/emulated/0/Android/data/...
  ...org.lineageos.updater/files/LineageOS updates/*.zip
  -> The user knows where the file is stored
  -> We don't have to care about WRITE_EXTERNAL_STORAGE etc
* Remove the cancel button - after closing the file stream we loose
  permission to access it, therefore can't delete it anymore
  -> Let the user handle deletion manually
* Since we don't use WRITE_EXTERNAL_STORAGE anymore, remove it from
  Manifest and also remove PermissionUtils (+calls) - we can now export
  immediately.
  -> This also solves the
  "TODO: start exporting once the permission has been granted"

Change-Id: I50afa403f2803569aa9def807ea20ee72c582284
2022-02-10 20:53:39 +00:00
Michael W
811d050272 Updater: No need to install every update
* Apparently users are not aware that they don't have to install every
  update we ever released (weeklies) after they have skipped some due
  to various reasons
* Since we are providing full installation packages, remind the user that
  it's ok to only ever choose the newest one

Change-Id: I70f9acd70344f36aaae7e45b848f6bcb7a8b3c0f
2022-02-10 20:53:39 +00:00
Michael W
d2557b8c6c Updater: We don't do upgrades
* We are actually updating, but especially between translations and
  non native speakers, drawing a semantical difference is more harmful
  than helpful
* Use "install" instead

Change-Id: Icdf1ce45d6cd35334b5c8ac13af3ec6741d837b6
2022-02-10 20:53:39 +00:00
Michael W
964eb5a68e Updater: The great cleanup
* Make final where possible
* Remove unused casts, imports, methods, enums and constructors
* Add null checks

Change-Id: Idd1a16426dd1928e2ed9922f5a35ba32ce4f808b
2022-02-10 20:53:39 +00:00
Michael W
297668b3ef Updater: update dependencies
Change-Id: I0686b28e7f6754c1b11b219b9036ea372032070b
2022-02-10 20:53:39 +00:00
Michael W
9f814a9a32 Updater: Replace lintOptions with lint
* As per AS recommendation

Change-Id: Id3668f21f356f13dcce4576c528b8af06d77a95f
2022-02-10 20:53:39 +00:00
Michael W
755254e1e5 Updater: Compile with and target Sdk version 31
Change-Id: I976d7af04d2d8f75ae0353341fe61a3a0510d840
2022-02-10 20:53:36 +00:00
Michael W
7843198d27 Updater: Change gradle from 3.5 to 7.1
Change-Id: Ia70512a77cdb30c6315863dcb65233d38cb5c9b9
2022-02-10 15:49:45 +01:00
Michael W
1f4d0571db Updater: Replace jcenter with mavenCentral
Change-Id: I0b6ae6553f106eef4cb7d331e3b089b74a66abcb
2022-02-10 09:37:49 +00:00
SahilSonar
4626490513 Updater: Convert to blueprint
Drop "UpdaterStudio" module while at it, considering that aidegen
can be used to compile Lineage Updater with Android Studio.

Change-Id: I828338461d0277992bfb301c2f785116c12dfc8a
2022-02-08 19:36:47 +01:00
Michael Bestas
7f584e9c08 Automatic translation import
Change-Id: I9aab887dd19308e821c5ba034563d0279abebb96
2022-01-12 15:46:57 +02:00
Michael Bestas
706e2d0498 Updater: Move to /system_ext
Change-Id: Ib781432398da8550eeb75b9d40dab191ce9f81c0
2021-11-14 21:34:25 +02:00
Timi Rautamäki
61e71f0db0 Updater: update layout and colors for 12
* Updated toolbar layout and behaviour
* Changed colors to match AOSP settings

Change-Id: Ic8efa69f9ba06055bac1772e1d9f3eb5ada67d8d
2021-11-08 20:03:11 +01:00
Timi Rautamäki
c8ae33d9ba Updater: Add a 3-dot menu for update item
Author: Timi Rautamaki <timi.rautamaki@gmail.com>
Date:   Wed Oct 13 16:06:51 2021 +0000
    Updater: add a 3-dot menu for update item

    A menu opening with only a long press is not intuitive and often not
    found by user.

    Change-Id: I7f819b77e2cbc534cafe488edadc4d3dd9b87d01

Author: Luca Stefani <luca.stefani.ge1@gmail.com>
Date:   Mon Nov 1 21:01:11 2021 +0100
    fixup! Updater: add a 3-dot menu for update item

    Change-Id: I10fe453c5f14d1a0ca49b734df517047cb7ee802

Change-Id: I8abf95327906bd6d3fb98978b931418f15d3dd00
2021-11-04 13:42:59 -04:00
Michael Bestas
ad604c69e4 Add exported flags in manifest
Targeting S+ (version 31 and above) requires that an explicit value
for android:exported be defined when intent filters are present

Change-Id: I2ce2b2cd1dcd69e343ae8577587483b19d825fdc
2021-10-11 22:36:41 +03:00
Michael Bestas
aed99e306c Updater: Add FLAG_IMMUTABLE flag to PendingIntent
Fixes:
Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE
or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some
functionality depends on the PendingIntent being mutable,
e.g. if it needs to be used with inline replies or bubbles.

Change-Id: I63b25512d3bf6e0d3b0cc95d91295f4065175848
2021-10-11 22:36:40 +03:00
Michael Bestas
772843f3ce Add missing localbroadcastmanager dependency
Change-Id: I793f1c94fcbc6b7805558d35b6d35ee0696686df
2021-10-11 18:19:25 +03:00
Timi Rautamäki
81dc120f09 Updater: follow TwoPanelSettings styling
Change-Id: I8d0957288fca25f1584f5ddb35c994c7ac2575f7
2021-09-14 17:51:38 +00:00
Timi Rautamäki
a96d54f236 Updater: initial layout for TV
Change-Id: Ia4704f7a15d9c1179ec93c1cab28707ba8115e70
2021-09-14 17:51:36 +00:00
Michael Bestas
6e5bbdaae1 Automatic translation import
Change-Id: I2d7ce9569a264be7d739f96328948c45516ffa5c
2021-08-21 04:07:41 +03:00
LineageOS Builder
a5492459f9 Automatic translation import
Change-Id: Icf76cbc53dd4b000862d76f470f6ad737b96c829
2021-05-01 15:56:43 +00:00
Dhina17
a36be60f98 Updater: appbar: Set the collapsing animation duration to 0ms
- Fixes lately fading out title of the expanded bar when collapsing (parallax)

Change-Id: I86062153b84ca4f82649862e15baa30aba2e6995
2021-04-28 11:58:07 +05:30
Michael W
7cfeb81a45 Updater: Fix exporting updates
* getExternalStorageDirectory was deprecated in API level 29
* Use the proposed Context#getExternalFilesDirs(String) instead

The following message can be found in the logs, followed by a crash:
MediaProvider: Creating a non-default top level directory or
deleting an existing one is not allowed!

Fixes: https://gitlab.com/LineageOS/issues/android/-/issues/3358
Change-Id: I81412985abc0f64d0fccb0d3069ac57ef6b4ffef
2021-04-19 13:42:15 +02:00
Michael Bestas
5a9c7479e7 Automatic translation import
Change-Id: I13c96b381b0fcc17c127fe64c6fc7e3997b8f248
2021-02-28 02:41:28 +02:00
chrmhoffmann
29ca6e5f3f update push script: remove bashisms
* [[ and == are bash-only. /bin/sh does not necessarily default to bash

Change-Id: I2e47f514568fc8cc94f387c82a86bea141345ba5
2020-12-28 11:10:55 +01:00
Pavel Salomatov
ffe5b527f6 UpdatesDbHelper: Move identical code into helper method
Change-Id: I2e19d9756fab94d9fcd3352b0baef45300044d3a
2020-12-17 13:11:05 +01:00
Alessandro Astone
9689a6b8bb Updater: Retrieve recovery update setting using the prop itself
This makes it easier to share the setting with SetupWizard.

Change-Id: I9a69df99c1b9a198ef9d5a039a090721b0195064
2020-11-23 17:14:24 +01:00
Nolen Johnson
a3c6c19a5f Updater: Clarify explanation for why A/B can't disable recovery update
Change-Id: Ia8cd1ec8c1ed5b5c8c2b9761da6782d66d1f67cd
2020-11-14 07:28:51 +01:00
Bruno Martins
96626c2fde Updater: Add setting for updating recovery
When enabled, the recovery of the device will be updated with the
version of the installed system. This is only applicable to devices
with a dedicated recovery partition and not A/B.

Change-Id: I4c1701b09c000b4cdb044069fa9ba857500f9cb1
2020-11-12 16:47:30 +00:00
LuK1337
1f8b7d56b0 Updater: Sign with platform key
Change-Id: Ia54f30e697d82d522a8dbe8e157b8f9f9e15daa8
2020-09-29 12:28:27 +02:00
LineageOS Builder
e3b26100c5 Automatic translation import
Change-Id: I84df5f5257fc5ee97ad307d289f3f503100c4e70
2020-09-20 10:11:28 +00:00
LineageOS Builder
1de5ff5239 Automatic translation import
Change-Id: Ifdc568ca60c3c2892993296017cfbbe1341989ce
2020-09-11 11:11:55 +00:00
Michael Bestas
4f8f00148a Automatic translation import
Change-Id: If04e431e80d0d9cd7ca4753be5f9aeb454e1fd66
2020-05-23 18:21:58 +03:00
LuK1337
bb09c53d83 Updater: Use accent_device_default_{dark,light} for colorAccent values
* That way the accent color is synced with Settings.

Change-Id: I86473166c46f0c71ec6ae69decccb981f01c6a1d
2020-05-18 11:20:51 +02:00
Michael Bestas
618ecad81a Updater: Add privapp permissions xml
Change-Id: If1953e76859850359a63dc4a4ab50940d76fd59f
2020-05-06 20:48:18 +03:00
Michael Bestas
e944ca0661 Automatic translation import
Change-Id: I36e2f6bdc74c81f26c2fd281544a4f2b576bfb44
2020-04-23 16:50:00 +03:00
Luca Stefani
d1273f214e Only cancel notification if update isn't installed
* Even if the package is removed on A/B devices
  we still want to show the reboot notification

Change-Id: I980d36766a1427874b65b11674a8f0ae4ce1db88
2020-04-11 12:19:52 +02:00
Alexander Martinz
759d5510c8 UpdatesActivity: only set performance mode on A/B devices
If the preference dialog gets dismissed on a non-ab-device it still
tries to set performance mode.

Add a check to prevent that and only set performance mode on A/B devices.

Change-Id: I6290eb80550b4cfc8a012f94bdf228af7d4fc416
Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
2020-04-03 17:00:31 +02:00
Alexander Martinz
35abddd093 Updater: remove dialog before showing a new one and when detaching
2020-04-03 16:18:18.286 28742-28742/org.lineageos.updater E/WindowManager: android.view.WindowLeaked: Activity org.lineageos.updater.UpdatesActivity has leaked window DecorView@5dd12b3[UpdatesActivity] that was originally added here
        at android.view.ViewRootImpl.<init>(ViewRootImpl.java:621)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:377)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:96)
        at android.app.Dialog.show(Dialog.java:342)
        at androidx.appcompat.app.AlertDialog$Builder.show(AlertDialog.java:1009)
        at org.lineageos.updater.UpdatesListAdapter.showInfoDialog(UpdatesListAdapter.java:552)
        at org.lineageos.updater.UpdatesListAdapter.lambda$setButtonAction$5$UpdatesListAdapter(UpdatesListAdapter.java:375)
        at org.lineageos.updater.-$$Lambda$UpdatesListAdapter$xtQzmsol8pO3BlYZkbKcb5gVAq4.onClick(Unknown Source:2)
        at org.lineageos.updater.UpdatesListAdapter.lambda$setButtonAction$9(UpdatesListAdapter.java:408)
        at org.lineageos.updater.-$$Lambda$UpdatesListAdapter$M4hRQyNgJseuHrw6EfkhK_yrGK8.onClick(Unknown Source:2)
        at android.view.View.performClick(View.java:7259)
        at android.view.View.performClickInternal(View.java:7236)
        at android.view.View.access$3600(View.java:801)
        at android.view.View$PerformClick.run(View.java:27896)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7397)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)

Change-Id: I7877b02b8526c7c12331a660a7ac934d02656e6f
Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
2020-04-03 16:41:16 +02:00
Alexander Martinz
9cdc2f497b AndroidManifest: explicitly disable cleartext traffic
Change-Id: Ib7528a58f423f40af1bafa16acdc9a4538207433
Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
2020-04-03 16:41:16 +02:00
Alexander Martinz
d94231abea Updater: do not use hidden field
BatteryManager#BATTERY_PLUGGED_ANY is hidden and actually just
a combination of all public available plugged values.
Recreate the hidden field instead of using it directly.

This unbreaks Android Studio builds.

Change-Id: I4754ce7544dab22306eeac03c3e9f26b650094d2
Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
2020-04-03 16:38:39 +02:00
Michael Bestas
9290c48307 Automatic translation import
Change-Id: Ic3bd376cfd0870ca579c12fb5b0457f2d690cdc8
2020-04-03 07:45:00 +02:00
Michael W
e4822ff569 Updater: Delete updates only after refreshing the notification
* Looks like we first need to process the notification before we can delete
  an update

Change-Id: I49f6c03a109f908e8a7b01f02b821a68ab273af3
2020-04-02 13:44:32 +02:00
Mickey Knox
416401aa2c Updater: push-update.sh: Make it work on macOS
Change-Id: I2bb51e349961efb1738d1abac2eaad9d3b4b9ad0
2020-03-31 18:47:18 +02:00
jhenrique09
eabab0e94e Fix export of zip
Add requestLegacyExternalStorage permission to allow usage of legacy storage

Change-Id: Iae3f61c4b714c168feba7de665a46ebe4ac1ee77
2020-02-05 01:48:06 +01:00
Michael Bestas
1fa036ce68 Automatic translation import
Change-Id: Ief254bec7ea4d6334643e1d1093a09cbf0e75fb9
2020-01-27 16:44:03 +02:00
Luca Stefani
91f33aa03e Updater: Move to AndroidX
Change-Id: I7bd67915638db5330b854f66f9fc1adb864b64be
2019-09-07 19:11:27 +02:00
Michael Bestas
56349fabc5 Automatic translation import
Change-Id: Ibbab351981135e7f0c213a97f169d98b737aff27
2019-08-25 19:28:18 +03:00
Michael Bestas
a3332eca1f Automatic translation import
Change-Id: Ic00c496504fe3e3083dff55b70b660d8fa11f5e4
2019-08-04 16:24:50 +03:00
Michael Bestas
d9fe6ee908 Automatic translation import
Change-Id: I90864874a46a7e651ded45605cf3d99d7b37f400
2019-07-06 11:59:32 +03:00
Michael Bestas
44a35fca4d Automatic translation import
Change-Id: I406b8de8d199e2c230254787aa0a29924952e8de
2019-06-19 21:21:33 +03:00
Michael Bestas
22a41280f0 Automatic translation import
Change-Id: I5c475240409637bee28aafba6b752e96509a97d7
2019-06-08 18:59:02 +03:00
Michael W
5763bc9d38 Updater: Make upgrade-url device specific
* After moving from the generic /upgrade.html url to a device specific
  one, updater needs to display that instead

Change-Id: If9fc6bddfab206a97283f2080ea4df0cbb742a7d
2019-04-28 11:33:32 +02:00
Luca Stefani
50d0fd5291 Updater: Allow to suspend A/B updates
Change-Id: I0387fd491a07a2214e4331a2cfe25988e0016a61
2019-04-10 22:04:32 +02:00
Michael Bestas
6a012ef541 Automatic translation import
Change-Id: I887ce69c970d42e6026c41c54edd5160b53f00b2
2019-04-07 21:59:19 +03:00
Michael W
dc17539da6 Automatic translation import
Change-Id: Ice67efb943862bc160150a4b1424e6af4f9511d8
2019-03-11 00:22:30 +01:00
Han Wang
f4a3c575f4 Updater: Assume older Android version to be incompatible
* Issue happens when both 15.1 and 16.0 are built.

Change-Id: I0cb7c834824056f450129524a7aec8091c9d3dc7
2019-03-05 09:59:45 +01:00
Michael Bestas
2849967e61 Automatic translation import
Change-Id: I3d9d81c42c6e6465cd66a12054389bafe34ad192
2019-02-26 19:01:42 +02:00
LuK1337
2454a339a3 Updater: Implement auto update check interval preference
* This replaces auto update check switch with a dropdown with 4 options:
  * Never
  * Once a day
  * Once a week (default)
  * Once a month

Change-Id: I4bcae4c013a5d44958f9c54d641e64aac3062a8b
2019-02-10 10:45:35 +01:00
Michael Bestas
ee251456c3 Automatic translation import
Change-Id: I699982fe2506a85cf9cb05295fafef3e59467b8d
2019-01-12 20:04:46 +02:00
LuK1337
a08dcb6078 Updater: Grant FOREGROUND_SERVICE permission
* Required to be able to call startForeground()
  and stopForeground().

Change-Id: I7ac78cf450a60cc8985876ddcc42621e61aa5245
2018-09-27 19:50:55 +02:00
Luca Stefani
6c67e68d55 Updater: Add SYSTEM_UPDATE_SETTINGS intent filter
Change-Id: Ie3f32e91ff5d6dc1422783bdef403c023b519149
2018-08-30 18:07:11 +02:00
Nolen Johnson
3f16a3cafc Updater: Clarify A/B Performance mode string
Change-Id: I8891b94c4b44201e9a0d9184e435c8da6eba3d3b
2018-08-30 14:12:35 +02:00
Anton Hansson
832efc94ca Updater: Set LOCAL_PRIVATE_PLATFORM_APIS
This change sets LOCAL_SDK_VERSION for all packages where
this is possible without breaking the build, and
LOCAL_PRIVATE_PLATFORM_APIS := true otherwise.

Setting one of these two will be made required soon, and this
is a change in preparation for that. Not setting LOCAL_SDK_VERSION
makes the app implicitly depend on the bootclasspath, which is
often not required. This change effectively makes depending on
private apis opt-in rather than opt-out.

Bug: 73535841
Change-Id: Iabb0556dc1c80c7fc7f6c76d61d5e441b03cdce0
2018-08-26 15:28:08 +02:00
Michael Bestas
6ba5645d01 Automatic translation import
Change-Id: I500c131c176e7f511972bb0b1529e54f127b7306
2018-08-16 19:08:22 +03:00
LuK1337
7ad6b6153a Updater: Fix EXTRA_PLUGGED check in isBatteryLevelOk
* EXTRA_PLUGGED is not a boolean.

Change-Id: I3c2869cc4e08b48e396e5bae5ef22383fcbf7260
2018-08-08 15:27:27 +02:00
Michael Bestas
c548bdf138 Automatic translation import
Change-Id: I641ddf4c5fa3061d8316be990c1332dc6000e34d
2018-08-05 17:33:19 +03:00
Rashed Abdel-Tawab
1022c6bcd1 push-update: Don't leave adb in root mode
Change-Id: I90d5a86bb943f137a44e70be508ee6efb0c77ed8
2018-07-26 16:47:12 -04:00
LuK1337
09e6fcab06 Updater: Use PowerManager instead of Intent.ACTION_REBOOT broadcast
* We are getting permission denial when sending Intent.ACTION_REBOOT
  broadcast, using pm.reboot() instead works just fine.

Change-Id: I38d0ad8cc5f4c9362fd5baf7476e14bff56616dd
2018-07-24 11:45:52 +02:00
LuK1337
e46f532c8c Updater: Fix 'REBOOT' button not showing up after A/B update
* After update is complete button is being handled in
  handleNotActiveStatus instead of handleActiveStatus.

Change-Id: I6a4df580f93b71fd12e902801125acae668ec991
2018-07-24 11:45:52 +02:00
Michael Bestas
412810e0b7 Automatic translation import
Change-Id: I7e73d20b38b6d9b743ef278c39057d558121e883
2018-07-15 21:47:00 +03:00
Gabriele M
5648b3cd27 Don't use one shot PendingIntents for the notification actions
FLAG_ONE_SHOT doesn't make so much sense here, the intents are generic
and can be repeated.

Change-Id: Ib457d975387dfd838372639e2aaa40a3df6f4d15
2018-07-14 18:47:12 +02:00
Luca Stefani
4ec02fd780 Updater: Improve battery check
* Lower default value by 10%
* Decrease the level by another 10% if charging
* Always allow installation in case device doesn't have a battery
* Show the requirements in the alert dialog

Change-Id: Iebb10220612006fbd096eb474cf3034ef52144b3
2018-07-14 18:47:12 +02:00
Gabriele M
74d7a3e78b Don't treat the current build as compatible
Even if technically it is compatible.

Change-Id: I72d39c761ad02b851c5ec7cfae664e886931f852
2018-07-14 18:33:07 +02:00
LuK1337
460cb87510 Updater: Add property that allows us to downgrade
Change-Id: I6916639f05c52ae198f0d1656deb23ee5186907f
2018-07-14 18:31:33 +02:00
TheScarastic
608789ff36 Updater: Allow toggling A/B perf mode
Change-Id: I380a39bf6008b341c8005ac548d42d2413d0d643
2018-07-11 22:27:33 +02:00
Michael Bestas
5a93f3f91a Automatic translation import
Change-Id: Icf78471c3fea2d0c67e63ce155e92748787e7a9c
2018-07-09 22:03:42 +03:00
Michael Bestas
599ed80201 Automatic translation import
Change-Id: Ie3bbaadd470b5d1fc22683b9f7280d912b644e53
2018-06-18 23:28:29 +03:00
LuK1337
67cb2626a9 Updater: Move battery level check to UpdatesListAdapter
* We cannot create dialog from service level without
  hardcoding theme resource and granting SYSTEM_ALERT_WINDOW
  permission therefore we got to move it here.

Change-Id: I70ee5d6c8ef4af4f5c6f29e593b1c20797781017
2018-06-15 21:26:36 +02:00
Gabriele M
f9463c3770 Requre a minimum remaining battery capacity to install updates
The recovery doesn't install the update if the remaining battery
capacity isn't at least 20% (or 15% if charging). Require at least
40%, just to be safe.

Change-Id: I5cd7c40f029141cde2b0922b25fece2b55989710
2018-06-13 23:30:08 +02:00
Gabriele M
0332be5ec7 Minor app notification improvements
- Don't use BigTextStyle if we only need to show a single line of
  text, but keep using it if the progressbar is visible.
- Change the icon to reflect the currrent state.
- Use android.R.drawable instead of com.android.internal.R.drawable

Change-Id: I0f69fe5f4fa63cdec180e89afa098d27819f33fd
2018-06-13 23:30:08 +02:00
Gabriele M
ce4b02697f Show in app reboot button
Change-Id: I8d65746b58c16a7cf4a430ea29bb7b0fba1802d5
2018-06-13 23:30:08 +02:00
Gabriele M
f4b3729426 Turn UpdateInstaller into a singleton
For symmetry with ABUpdateInstaller.

Change-Id: I9b61ed286c91f10140705e7b3e24b0eab0c75f49
2018-06-13 23:30:08 +02:00
Gabriele M
4bacd24da4 Remove Controller interface
This is just useless as is.

Change-Id: I957ea3bda4097ccb8d730943639cd5e74b1b2440
2018-06-13 23:30:08 +02:00
Gabriele M
78e69c05d8 Remove LegacySupport class
This was meant to provide an upgrade path from the old app. It's
been almost a year now, this class is no longer needed.

Change-Id: I17c82e5877b275c5ceb3caefa28066abc170f095
2018-06-13 23:30:08 +02:00
Michael Bestas
9285b1c1a6 Automatic translation import
Change-Id: I27a25d23f5bffb328cce4dab3b440ad20d3a00bc
2018-06-03 14:10:09 +03:00
Gabriele M
8b300f0d05 Prevent null pointer exceptions
The main activity connects to the service after setting up the local
broadcast. This allows the service to send notification before the
activity is ready, causing null pointer exceptions. This happens for
example rotating the screen while an update is being installed.

Also, replace the existing check on mUpdaterController with a check
on mDownloadsId since the latter depends on the former and both are
required.

Change-Id: I620fd7aa1e90468ab40dfedaa06c23f96f3e6807
2018-05-16 22:46:10 +02:00
Gabriele M
4f7db45fa6 Use Content-Length if greater than current size
The server may temporarily report an incorrect size that is smaller
than the actual size. Content-Length is expected to always be
accurate, but its value does not correspond to the full file size
when resuming downloads. Use Content-Length only if it's bigger
than the currently known size.

Change-Id: I2cc06bfbd2349f21528047b4840f549fbe84964e
2018-05-16 22:46:10 +02:00
Michael Bestas
907486ad4f Automatic translation import
Change-Id: I7197b0358cd9e9e94260cee425390fa7deb6fe2d
2018-05-08 19:47:25 +03:00
Michael Bestas
8a8f1d98f0 Fix eta_hours quantity="one" string
* Fixes fd096a564a

Change-Id: I19633ead80b690e1c22655bcac842a901e450f8a
2018-05-04 22:36:25 +03:00
Gabriele M
fd096a564a Allow to properly translate the download ETA string
Change-Id: Ie6bbbddbbd9fd7adbc16472ad9c42c1d257413a1
2018-04-21 16:31:28 +02:00
Gabriele M
cc1ad0e827 Append random ID to temporary json file names
Multiple update list downloads can happen simultaneously. Use
unique file names for the temporary jsons to avoid conflicts.

Change-Id: I751c9838394e1f5aebbe359f61532947b429f39b
2018-04-20 21:26:30 +02:00
Gabriele M
dc9890f09c Use a determinate progressbar while installing A/B updates
This needs to be done explicitly after the recent UI changes.

Change-Id: Ie333a51d7c679c17998872071b2bd84c1f47ca48
2018-04-20 21:26:07 +02:00
Michael Bestas
75c31f3274 Automatic translation import
Change-Id: I593d19fa09ae2605d05aa0a38029691d3653821b
2018-04-20 00:56:08 +03:00
Bruno Martins
569d9a2c51 Updater: Build with AAPT2
Change-Id: I45553984269bd2375311047b053e01f67349c695
2018-04-17 15:39:42 +02:00
Gabriele M
6aa0a04fbb Replace some paddings with margings in the preferences
This ensures that each Switch is always fully visible independently
of the size of system font.

Change-Id: I1e56a9537dbbb124d86ea0da76d48b7b53172e47
2018-04-12 00:19:41 +02:00
Gabriele M
e198389bd5 Add a script to push updates
Useful to test OTA updates without setting up a server.

Change-Id: Ic4c2dc1ea9ce6bd6ec6750d1c4250079a5be7580
2018-04-11 00:33:05 +02:00
Gabriele M
6c0aa8118e gen-keystore.sh: Don't pass the passwords as args
Also mention that the password is saved in clear text.

Change-Id: Ia7bf8b1b85193aa76b541dc5c6ee99a471d12f92
2018-04-11 00:33:05 +02:00
Gabriele M
d5f4c1bcec Detect update failures
This allows to delete the update only if the installation succeeded
and to notify the user in case the installation failed.

Since we now need the file in case of failure, create a copy for
uncrypt even if the user chose to delete installed updates.

Change-Id: I80b0f499663bbf50bcbca5f643c01ffdb4cd3957
2018-04-08 22:48:19 +02:00
Joey
af9b4adbe0 Updater: show settings in a proper preferences dialog
Menu is not a good place to store preferences that have long strings

Change-Id: I84e782af33b2452c15998f7266c57d681dc8a377
Signed-off-by: Joey <joey@lineageos.org>
2018-04-08 18:21:57 +02:00
Gabriele M
17db209f13 Always show the size of the updates
This is now possible since the size is included in the JSON.

Change-Id: Ie38ccfbdc7abb0e4b86e8e625ed8d131376402e7
2018-04-08 14:26:19 +02:00
Joey
ec4f3146d6 Updater: Minor UI improvements
Change-Id: I5028aaa154991806ab911be0119fed0836e6851b
2018-04-08 14:26:12 +02:00
Joey
862e913590 Updater: Support Dark mode and update colors
Change-Id: I3503311e9e94663c4b708fc744962ce97690d6e1
2018-04-08 14:26:07 +02:00
Joey
6d24b010f7 Updater: Use popup menu instead of ActionMode
Change-Id: I707682708711679a7cbe1b0058cea9b1ed003cb6
2018-04-08 14:25:59 +02:00
Gabriele M
a64eae5fc0 Simplify code syntax using Java 8 features
Change-Id: I3e59f0c38e4047595374a951619c9b43a46901df
2018-04-08 14:25:56 +02:00
Gabriele M
a72b78c31e Get file size from JSON
The server now reports the size of the file, so use it and
require it.

Change-Id: I2248347431b65ae54dd7295872d70aba456ed8d8
2018-04-08 14:25:53 +02:00
Gabriele M
6fd45962c1 Print stack trace if the JSON could not be parsed
This helps to identify errors in the response.

Change-Id: Icda0919378ebf1deba3a4c7d6d6d010a09eed3ce
2018-04-08 14:25:45 +02:00
Gabriele M
bf2e25d400 Updater: Fix Android Studio build
Increase the min API level to support notification channels
without compat libraries.

Change-Id: Ia2f383a108dbb4fc38b3d923ac7c5e3d173fcf71
2018-04-05 23:49:51 +02:00
Gabriele M
548f515a48 Add README to document the communication with the server
While at it, move README-STUDIO.txt into the newly created file.

Change-Id: I3e853a32d57f2d2bea3c41f7e8ec6fb22859e5f5
2018-04-05 16:37:50 +02:00
Gabriele M
5252d60671 Define the entire server URL as resource
Currently the URL is only partially customizable, part of
it is hard-coded and there's no clear indication of it.
Define the entire URL as resource string and use placeholders
for runtime variables.

Also, invalidate old overrides by changing the name of the
resource.

Warning: lineage.updater.uri must be updated accordingly

Change-Id: Iecfdaf9d422d08a707c7319bafea5befc6b757d2
2018-04-05 16:37:49 +02:00
Gabriele M
4fa7ba910a Replace refresh dialog with icon animation
Change-Id: I6d2cc649b9fa8883a7256d8ecb62cb56bbf5dd59
2018-04-05 16:37:49 +02:00
Gabriele M
4d5e82b885 Handle install errors from onPayloadApplicationComplete()
When the installation terminates because of an error, update_engine
sets the status to IDLE and sends a notification. Thus, we might
miss the error report and never update the status of the update.

Change-Id: Ic1536b1c157c4dab0128f039f9512f2fb734287d
2018-04-05 16:37:49 +02:00
Gabriele M
8d0471effc Make updates world readable
This should allow update_engine to access the file without
granting the dac_override capability.

Change-Id: I5d0c8792fd47e5571dbaf802b2725f99ee2dc150
2018-04-05 16:37:49 +02:00
Gabriele M
3aabbc7ed5 Use single return statement in onStartCommand()
This should prevent future changes from accidentally turning a
sticky service into a not sticky one.

Change-Id: I89f172626a98635149441a63536e0aa5a27f8280
2018-04-05 16:37:49 +02:00
Gabriele M
2ec8fc6cec Prevent NPE on A/B devices
The NPE shouldn't happen as we get a null intent only when the
service is sticky (i.e., isInstallingUpdate() is true), so this
is currently not a problem.

Change-Id: I8647498d9a1022f5c7207a2da3e42cf57d9ee030
2018-04-05 16:37:49 +02:00
Gabriele M
a409a4a03d Clear NEEDS_REBOOT preference on reboot
UpdateEngine doesn't send an initial notification to bound client
if the last status is not known, so clear the preference when we
detect that the device has been rebooted.

Change-Id: Ib15dff5fa8ac9ec07a68018a83683cc561fd3e85
2018-04-05 16:37:49 +02:00
Gabriele M
eecdf389ef Set status to INSTALLING when reconnecting to the service
Otherwise the service won't run in foreground after restarting
the app while an update is being installed.

Change-Id: I8a75d206ead2945e7326c144b0b4354fbb2accb4
2018-04-05 16:37:49 +02:00
Gabriele M
28644b3491 Don't register multiple UpdateEngine callbacks
We are loosely tied to UpdateEngine and have no way to know whether
we are bound or not without keeping track of the connection manually.
Since UpdaterService is for both A/B and legacy updates, turn
ABUpdateInstaller into a singleton to keep the code simple while
ensuring that a single callback is registered.

Change-Id: Ib4e9ad1413ba96bf5ed59cc3383741b5c9bac427
2018-04-05 16:37:49 +02:00
Gabriele M
69e65ca4bf Remove duplicate INSTALLING notification
Change-Id: Ia1515aef1a24a5d54143e1423ae96f09163625bc
2018-04-05 16:37:46 +02:00
Michael Bestas
a0bdd6abba Automatic translation import
Change-Id: I0cd872bbd27613db1203a0538eff765379316ecb
2018-04-01 22:32:42 +03:00
Dan Pasanen
37524ad0fa Updater: explicitly include android-support-transition
* Fixes non-jack build

Change-Id: I44d470daa36f9ef5f06e5307297fa4c01fb078e5
2018-03-21 22:51:08 +00:00
Michael Bestas
14d522818c Automatic translation import
Change-Id: I5265394cac0bdd174c3cec21a11a1d0e6d35597d
2018-03-09 00:35:54 +02:00
Roman Birg
31057295dc Updater: fix wrong preference key in A/B installer
We are referencing the wrong key for deciding whether to delete the
update on reboot.

Change-Id: If83d278259291b61c26302bdd59c2774901b18ca
Signed-off-by: Roman Birg <romanbirg@gmail.com>
2018-03-07 02:55:32 +00:00
Michael Bestas
f183b58b09 Automatic translation import
Change-Id: I2923971e3477640a67a241762d1dc164f1e0c462
2018-02-25 22:04:16 +02:00
Michael Bestas
d44eb7c414 Automatic translation import
Change-Id: I47e08290ebdb11c3d05d0614560dc2847884928d
2018-02-22 03:49:55 +02:00
meganukebmp
76b9f49684 Updater: add changelog button
Add a changelog button in the menu toolbar throwing the user in
the recent changes page

Change-Id: I16609825c0662fc22b95189cbdf324a8c0b94f81
2018-02-17 17:46:45 +00:00
Joey
f62a57c463 Updater: gradle: target api27
Change-Id: I83aae173b4e885368737ac94f5d6d018708d642b
Signed-off-by: Joey <joey@lineageos.org>
2018-02-17 12:54:17 +00:00
Joey
2a9c85e675 Updater: adaptive icon
Change-Id: Ifee7b51f48b204b646935d9470d31f6e9519124d
Signed-off-by: Joey <joey@lineageos.org>
2018-02-15 13:43:40 +00:00
Harry Youd
ff53035537 Updater: Add notification channels
Change-Id: I2f538fb47fe90e1008bf286739d33c829123353a
2018-01-23 23:47:18 +01:00
Gabriele M
0e79b791f0 Add support for duplicate links
Support duplicate links [1] to handle better temporarily unavailable
mirrors.

[1] https://tools.ietf.org/html/rfc6249

Change-Id: If78fb4a90da68ef221294eed2c59063a14cf1f43
2018-01-23 22:41:40 +01:00
Gabriele M
3fc17494eb Updater: Android Studio support
See README-STUDIO.txt for more info.

Change-Id: Ie673bba5618b0f00a585049cd85687a64db2b420
2018-01-23 22:41:40 +01:00
Gabriele M
7005b005d9 Updater: Set version code explicitly
In this way apks built with gradle/Android Studio will have the
same versionCode, allowing to update the one in /system.

Change-Id: I020cc623dd7c1c5085fec4e6f5978b6ee46468a2
2018-01-23 22:41:40 +01:00
Gabriele M
e50edf0811 Remove progress from notification when done
Change-Id: If49c8d0ca2270f22dcc5350379f1bb1f34f02041
2018-01-23 22:41:40 +01:00
Gabriele M
63f6fd1a70 Report installation failures
Change-Id: I5e11db1e6e338a510b3c1c7d16f8c085d874a9db
2018-01-23 22:41:40 +01:00
Gabriele M
e02b8a0b00 Copy the updates for uncrypt using a Service
Same as change I488018d01c0baf74660362a384e53bfe5d85de2b
("Use a service to export the updates"). While at it, move the code
out of UpdaterService to better separate the code that deal with AB
updates and regular updates.

Change-Id: I2bc3e78e80f5e63c57303cbbcdc0353dbab0f67f
2018-01-23 22:41:40 +01:00
Gabriele M
e66a8fa53a Keep track of the installation status of AB updates
This allows to show the correct labels.

Change-Id: I52f42e042af0df2d091d786c03102cec352b3a5b
2018-01-23 22:41:40 +01:00
Gabriele M
c5f36ee047 Don't allow any operation if a reboot is needed
Change-Id: I175525071faa44f30b8f2bbf36da56a2e6f2dd1b
2018-01-23 22:41:40 +01:00
Gabriele M
8e369117bf Allow to cancel ongoing installations
Change-Id: I46884b42b6e3f87fbee99a23f538cec990b3b873
2018-01-23 22:41:40 +01:00
Gabriele M
f3d9b3f1b2 Allow service restarts while installing AB updates
The update engine service is independent and once started doesn't need
our service to install updates. Therefore we can't assume that our
service will stay up as long as the installation is being performed.
If the service gets terminated while an update is being installed, we
simply lose our connection to the update engine service and stop
receiving notifications, the installation itself won't stop. Keep
track of ongoing installations using a shared preference and use a
sticky service when installing updates. The service will try to
re-connect to the update engine service and determine if the
installation is still ongoing.

Change-Id: Id2fc11cab51610d04bf41a0927824bb8c0c94d71
2018-01-23 22:41:40 +01:00
Gabriele M
6088f26f53 Wait for the UPDATED_NEED_REBOOT status
Consider an update as installed only when update engine reports that
the device needs to be rebooted. This change also move the entire
logic in onStatusUpdate(), which reports all we need to properly
track the progress of the installation.

Change-Id: Ic8db00cccdd19fd62ba4dee31fd1dccc9037193d
2018-01-23 22:41:40 +01:00
Gabriele M
02f52108d9 Show progress when installing AB updates
Change-Id: If8cd2e2da1f15a4af415aa35ccf61052c318333f
2018-01-23 22:41:40 +01:00
Gabriele M
2c41ae392c Use a service to export the updates
AsyncTasks are not suitable for long lasting operations and can easily
cause memory leaks. The use of ProgressDialogs is also discouraged, so
move to a foreground service to export the updates.

Change-Id: I488018d01c0baf74660362a384e53bfe5d85de2b
2018-01-23 22:41:40 +01:00
Gabriele M
d4a65e455e Stop service when pausing downloads
Change-Id: Ibb77c7f0d4309874fcfa591d12b5e6ce4a6d6abc
2018-01-23 22:41:34 +01:00
Gabriele M
cbe6bd69fd Use the right preference for the auto-delete option
Change-Id: Iac7e838e8ecf1e5ed27bb0c9587442aa2ec8ffec
(cherry picked from commit 8ff6f57e7b)
2018-01-18 19:27:20 +00:00
254 changed files with 11508 additions and 7170 deletions

13
.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
*.iml
.gradle
/local.properties
/.idea
.DS_Store
/build
/captures
/system_libs/*.jar
/keystore.properties
.externalNativeBuild
.cxx
*.jks
local.properties

View File

@@ -1,37 +0,0 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-design \
android-support-v4 \
android-support-v7-appcompat \
android-support-v7-cardview \
android-support-v7-preference \
android-support-v7-recyclerview
LOCAL_RESOURCE_DIR := \
$(TOP)/frameworks/support/design/res \
$(TOP)/frameworks/support/v7/appcompat/res \
$(TOP)/frameworks/support/v7/cardview/res \
$(TOP)/frameworks/support/v7/preference/res \
$(TOP)/frameworks/support/v7/recyclerview/res \
$(LOCAL_PATH)/res
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
--extra-packages android.support.design \
--extra-packages android.support.v7.appcompat \
--extra-packages android.support.v7.cardview \
--extra-packages android.support.v7.preference \
--extra-packages android.support.v7.recyclerview
LOCAL_PACKAGE_NAME := Updater
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)

View File

@@ -1,46 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lineageos.updater">
<uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REBOOT" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECOVERY" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".UpdatesActivity"
android:excludeFromRecents="true"
android:label="@string/display_name"
android:theme="@style/AppTheme.NoActionBar"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service android:name=".controller.UpdaterService" />
<receiver android:name=".UpdaterReceiver" android:exported="false" />
<receiver android:name=".UpdatesCheckReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>

52
README.md Normal file
View File

@@ -0,0 +1,52 @@
Updater
=======
Simple application to download and apply OTA packages.
Server requirements
-------------------
The app sends `GET` requests to the URL defined by the `updater_server_url`
resource (or the `lineage.updater.uri` system property) and expects as response
a JSON with the following structure:
```json
{
"response": [
{
"datetime": 1230764400,
"filename": "ota-package.zip",
"id": "5eb63bbbe01eeed093cb22bb8f5acdc3",
"romtype": "nightly",
"size": 314572800,
"url": "https://example.com/ota-package.zip",
"version": "15.1"
}
]
}
```
The `datetime` attribute is the build date expressed as UNIX timestamp.
The `filename` attribute is the name of the file to be downloaded.
The `id` attribute is a string that uniquely identifies the update.
The `romtype` attribute is the string to be compared with the `ro.lineage.releasetype` property.
The `size` attribute is the size of the update expressed in bytes.
The `url` attribute is the URL of the file to be downloaded.
The `version` attribute is the string to be compared with the `ro.lineage.build.version` property.
Additional attributes are ignored.
Build with Android Studio
-------------------------
Updater needs access to the system API, therefore it can't be built only using
the public SDK. You first need to generate the libraries with all the needed
classes. The application also needs elevated privileges, so you need to sign
it with the right key to update the one in the system partition. To do this:
- Place this directory anywhere in the Android source tree
- Generate a keystore and keystore.properties using `gen-keystore.sh`
- Build the dependencies running `make UpdaterStudio` from the root of the
Android source tree. This command will add the needed libraries in
`system_libraries/`.
You need to do the above once, unless Android Studio can't find some symbol.
In this case, rebuild the system libraries with `make UpdaterStudio`.

1
app/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

62
app/Android.bp Normal file
View File

@@ -0,0 +1,62 @@
//
// Copyright (C) 2022-2024 The LineageOS Project
//
// SPDX-License-Identifier: Apache-2.0
//
android_app {
name: "Updater",
// Include SettingsLib and its dependencies
defaults: ["SettingsLibDefaults"],
srcs: ["src/main/java/**/*.java"],
resource_dirs: ["src/main/res"],
manifest: "src/main/AndroidManifest.xml",
platform_apis: true,
privileged: true,
certificate: "platform",
system_ext_specific: true,
overrides: [
"SystemUpdater",
],
static_libs: [
// DO NOT EDIT THIS SECTION MANUALLY
"androidx.core_core-ktx",
"androidx.appcompat_appcompat",
"androidx.cardview_cardview",
"androidx.lifecycle_lifecycle-viewmodel-ktx",
"androidx.localbroadcastmanager_localbroadcastmanager",
"androidx.preference_preference",
"androidx.recyclerview_recyclerview",
"com.google.android.material_material",
],
optimize: {
proguard_flags_files: ["proguard.flags"],
},
required: [
"privapp_whitelist_org.lineageos.updater",
"default-permissions_org.lineageos.updater"
],
}
prebuilt_etc {
name: "privapp_whitelist_org.lineageos.updater",
system_ext_specific: true,
sub_dir: "permissions",
src: "privapp_whitelist_org.lineageos.updater.xml",
filename_from_src: true,
}
prebuilt_etc {
name: "default-permissions_org.lineageos.updater",
system_ext_specific: true,
sub_dir: "default-permissions",
src: "default-permissions_org.lineageos.updater.xml",
filename_from_src: true,
}

112
app/build.gradle.kts Normal file
View File

@@ -0,0 +1,112 @@
import java.util.Properties
import org.lineageos.generatebp.GenerateBpPlugin
import org.lineageos.generatebp.GenerateBpPluginExtension
import org.lineageos.generatebp.models.Module
plugins {
id("com.android.application")
id("kotlin-android")
}
apply {
plugin<GenerateBpPlugin>()
}
buildscript {
repositories {
maven("https://raw.githubusercontent.com/lineage-next/gradle-generatebp/v1.2/.m2")
}
dependencies {
classpath("org.lineageos:gradle-generatebp:+")
}
}
val keystorePropertiesFile = rootProject.file("keystore.properties")
val keystoreProperties = Properties().apply {
if (keystorePropertiesFile.exists()) {
load(keystorePropertiesFile.inputStream())
}
}
android {
compileSdk = 33
defaultConfig {
applicationId = "org.lineageos.updater"
minSdk = 30
targetSdk = 33
versionCode = 1
versionName = "1.0"
}
buildTypes {
getByName("release") {
// Includes the default ProGuard rules files.
setProguardFiles(
listOf(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
)
}
getByName("debug") {
// Append .dev to package name so we won't conflict with AOSP build.
applicationIdSuffix = ".dev"
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
signingConfigs {
create("release") {
(keystoreProperties["keyAlias"] as String?)?.let {
keyAlias = it
}
(keystoreProperties["keyPassword"] as String?)?.let {
keyPassword = it
}
(keystoreProperties["storeFile"] as String?)?.let {
storeFile = file(it)
}
(keystoreProperties["storePassword"] as String?)?.let {
storePassword = it
}
}
}
}
dependencies {
compileOnly(fileTree(mapOf("dir" to "../system_libs", "include" to listOf("*.jar"))))
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.cardview:cardview:1.0.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1")
implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0")
implementation("androidx.preference:preference:1.2.0")
implementation("androidx.recyclerview:recyclerview:1.2.1")
implementation("com.google.android.material:material:1.9.0-alpha01")
}
configure<GenerateBpPluginExtension> {
targetSdk.set(android.defaultConfig.targetSdk!!)
availableInAOSP.set { module: Module ->
when {
module.group.startsWith("androidx") -> true
module.group.startsWith("org.jetbrains") -> true
module.group == "com.google.android.material" -> true
module.group == "com.google.errorprone" -> true
module.group == "com.google.guava" -> true
module.group == "junit" -> true
else -> false
}
}
}

View File

@@ -0,0 +1,22 @@
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<!--
Copyright (C) 2022 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<exceptions>
<exception package="org.lineageos.updater">
<!-- Notifications -->
<permission name="android.permission.POST_NOTIFICATIONS" fixed="false"/>
</exception>
</exceptions>

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<!--
Copyright (C) 2017 The LineageOS Project
Copyright (C) 2017-2020 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -15,9 +14,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Directory where the update files will be downloaded and stored.
WARNING: The application can and will delete any unknown file. -->
<!-- Directory where the downloads will be exported to.
The path is relative to the root of the external storage.-->
</resources>
<permissions>
<privapp-permissions package="org.lineageos.updater">
<permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/>
<permission name="android.permission.REBOOT"/>
<permission name="android.permission.RECOVERY"/>
<permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
</privapp-permissions>
</permissions>

1
app/proguard.flags Normal file
View File

@@ -0,0 +1 @@
-keep class org.lineageos.updater.ui.FlingBehavior { *; }

View File

@@ -0,0 +1,73 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lineageos.updater"
android:versionCode="1">
<uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.REBOOT" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECOVERY" />
<uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="false">
<activity
android:name=".UpdatesActivity"
android:excludeFromRecents="true"
android:label="@string/display_name"
android:exported="true"
android:theme="@style/AppTheme.NoActionBar"
android:launchMode="singleTop">
<intent-filter android:priority="2">
<action android:name="android.settings.SYSTEM_UPDATE_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service
android:name=".controller.UpdaterService"
android:foregroundServiceType="specialUse">
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="updater"/>
</service>
<service
android:name=".ExportUpdateService"
android:foregroundServiceType="specialUse">
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="updater"/>
</service>
<receiver android:name=".UpdaterReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<receiver android:name=".UpdatesCheckReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -0,0 +1,193 @@
/*
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.updater;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;
import androidx.core.app.NotificationCompat;
import org.lineageos.updater.misc.FileUtils;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
public class ExportUpdateService extends Service {
private static final String TAG = "ExportUpdateService";
private static final int NOTIFICATION_ID = 16;
public static final String ACTION_START_EXPORTING = "start_exporting";
public static final String EXTRA_SOURCE_FILE = "source_file";
public static final String EXTRA_DEST_URI = "dest_uri";
private static final String EXPORT_NOTIFICATION_CHANNEL =
"export_notification_channel";
private volatile boolean mIsExporting = false;
private Thread mExportThread;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_START_EXPORTING.equals(intent.getAction())) {
if (mIsExporting) {
Log.e(TAG, "Already exporting an update");
Toast.makeText(this, R.string.toast_already_exporting, Toast.LENGTH_SHORT).show();
return START_NOT_STICKY;
}
mIsExporting = true;
File source = (File) intent.getSerializableExtra(EXTRA_SOURCE_FILE);
Uri destination = intent.getParcelableExtra(EXTRA_DEST_URI);
startExporting(source, destination);
Toast.makeText(this, R.string.toast_export_started, Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "No action specified");
}
if (!mIsExporting) {
stopSelf();
}
return START_NOT_STICKY;
}
private class ExportRunnable implements Runnable {
private final ContentResolver mContentResolver;
private final File mSource;
private final Uri mDestination;
private final FileUtils.ProgressCallBack mProgressCallBack;
private final Runnable mRunnableComplete;
private final Runnable mRunnableFailed;
private ExportRunnable(ContentResolver cr, File source, Uri destination,
FileUtils.ProgressCallBack progressCallBack,
Runnable runnableComplete, Runnable runnableFailed) {
mContentResolver = cr;
mSource = source;
mDestination = destination;
mProgressCallBack = progressCallBack;
mRunnableComplete = runnableComplete;
mRunnableFailed = runnableFailed;
}
@Override
public void run() {
try {
FileUtils.copyFile(mContentResolver, mSource, mDestination, mProgressCallBack);
mIsExporting = false;
if (!mExportThread.isInterrupted()) {
Log.d(TAG, "Completed");
mRunnableComplete.run();
} else {
Log.d(TAG, "Aborted");
}
} catch (IOException e) {
mIsExporting = false;
Log.e(TAG, "Could not copy file", e);
mRunnableFailed.run();
} finally {
stopSelf();
}
}
}
private void startExporting(File source, Uri destination) {
final String fileName = FileUtils.queryName(getContentResolver(), destination);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
NotificationChannel notificationChannel = new NotificationChannel(
EXPORT_NOTIFICATION_CHANNEL,
getString(R.string.export_channel_title),
NotificationManager.IMPORTANCE_LOW);
notificationManager.createNotificationChannel(notificationChannel);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,
EXPORT_NOTIFICATION_CHANNEL);
NotificationCompat.BigTextStyle notificationStyle = new NotificationCompat.BigTextStyle();
notificationBuilder.setContentTitle(getString(R.string.dialog_export_title));
notificationStyle.setBigContentTitle(getString(R.string.dialog_export_title));
notificationStyle.bigText(fileName);
notificationBuilder.setStyle(notificationStyle);
notificationBuilder.setSmallIcon(R.drawable.ic_system_update);
FileUtils.ProgressCallBack progressCallBack = new FileUtils.ProgressCallBack() {
private long mLastUpdate = -1;
@Override
public void update(int progress) {
long now = SystemClock.elapsedRealtime();
if (mLastUpdate < 0 || now - mLastUpdate > 500) {
String percent = NumberFormat.getPercentInstance().format(progress / 100.f);
notificationStyle.setSummaryText(percent);
notificationBuilder.setProgress(100, progress, false);
notificationManager.notify(NOTIFICATION_ID,
notificationBuilder.build());
mLastUpdate = now;
}
}
};
startForeground(NOTIFICATION_ID, notificationBuilder.build(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
Runnable runnableComplete = () -> {
notificationStyle.setSummaryText(null);
notificationStyle.setBigContentTitle(
getString(R.string.notification_export_success));
notificationBuilder.setContentTitle(
getString(R.string.notification_export_success));
notificationBuilder.setProgress(0, 0, false);
notificationBuilder.setContentText(fileName);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
stopForeground(STOP_FOREGROUND_DETACH);
};
Runnable runnableFailed = () -> {
notificationStyle.setSummaryText(null);
notificationStyle.setBigContentTitle(
getString(R.string.notification_export_fail));
notificationBuilder.setContentTitle(
getString(R.string.notification_export_fail));
notificationBuilder.setProgress(0, 0, false);
notificationBuilder.setContentText(null);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
stopForeground(STOP_FOREGROUND_DETACH);
};
ExportRunnable exportRunnable = new ExportRunnable(getContentResolver(), source,
destination, progressCallBack, runnableComplete, runnableFailed);
mExportThread = new Thread(exportRunnable);
mExportThread.start();
}
}

View File

@@ -0,0 +1,249 @@
/*
* Copyright (C) 2017-2022 The LineageOS Project
* Copyright (C) 2020-2022 SHIFT GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.updater;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import org.json.JSONException;
import org.lineageos.updater.controller.UpdaterController;
import org.lineageos.updater.controller.UpdaterService;
import org.lineageos.updater.misc.StringGenerator;
import org.lineageos.updater.misc.Utils;
import org.lineageos.updater.model.Update;
import org.lineageos.updater.model.UpdateInfo;
import org.lineageos.updater.model.UpdateStatus;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class UpdateImporter {
private static final int REQUEST_PICK = 9061;
private static final String TAG = "UpdateImporter";
private static final String MIME_ZIP = "application/zip";
private static final String FILE_NAME = "localUpdate.zip";
private static final String METADATA_PATH = "META-INF/com/android/metadata";
private static final String METADATA_TIMESTAMP_KEY = "post-timestamp=";
private final Activity activity;
private final Callbacks callbacks;
private Thread workingThread;
public UpdateImporter(Activity activity, Callbacks callbacks) {
this.activity = activity;
this.callbacks = callbacks;
}
public void stopImport() {
if (workingThread != null && workingThread.isAlive()) {
workingThread.interrupt();
workingThread = null;
}
}
public void openImportPicker() {
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType(MIME_ZIP);
activity.startActivityForResult(intent, REQUEST_PICK);
}
public boolean onResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK || requestCode != REQUEST_PICK) {
return false;
}
return onPicked(data.getData());
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private boolean onPicked(Uri uri) {
callbacks.onImportStarted();
workingThread = new Thread(() -> {
File importedFile = null;
try {
importedFile = importFile(uri);
verifyPackage(importedFile);
final Update update = buildLocalUpdate(importedFile);
addUpdate(update);
activity.runOnUiThread(() -> callbacks.onImportCompleted(update));
} catch (Exception e) {
Log.e(TAG, "Failed to import update package", e);
// Do not store invalid update
if (importedFile != null) {
importedFile.delete();
}
activity.runOnUiThread(() -> callbacks.onImportCompleted(null));
}
});
workingThread.start();
return true;
}
@SuppressLint("SetWorldReadable")
@SuppressWarnings("ResultOfMethodCallIgnored")
private File importFile(Uri uri) throws IOException {
final ParcelFileDescriptor parcelDescriptor = activity.getContentResolver()
.openFileDescriptor(uri, "r");
if (parcelDescriptor == null) {
throw new IOException("Failed to obtain fileDescriptor");
}
final FileInputStream iStream = new FileInputStream(parcelDescriptor
.getFileDescriptor());
final File downloadDir = Utils.getDownloadPath(activity);
final File outFile = new File(downloadDir, FILE_NAME);
if (outFile.exists()) {
outFile.delete();
}
final FileOutputStream oStream = new FileOutputStream(outFile);
int read;
final byte[] buffer = new byte[4096];
while ((read = iStream.read(buffer)) > 0) {
oStream.write(buffer, 0, read);
}
oStream.flush();
oStream.close();
iStream.close();
parcelDescriptor.close();
outFile.setReadable(true, false);
return outFile;
}
private Update buildLocalUpdate(File file) {
final long timeStamp = getTimeStamp(file);
final String buildDate = StringGenerator.getDateLocalizedUTC(
activity, DateFormat.MEDIUM, timeStamp);
final String name = activity.getString(R.string.local_update_name);
final Update update = new Update();
update.setAvailableOnline(false);
update.setName(name);
update.setFile(file);
update.setFileSize(file.length());
update.setDownloadId(Update.LOCAL_ID);
update.setTimestamp(timeStamp);
update.setStatus(UpdateStatus.VERIFIED);
update.setPersistentStatus(UpdateStatus.Persistent.VERIFIED);
update.setVersion(String.format("%s (%s)", name, buildDate));
return update;
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private void verifyPackage(File file) throws Exception {
try {
android.os.RecoverySystem.verifyPackage(file, null, null);
} catch (Exception e) {
if (file.exists()) {
file.delete();
throw new Exception("Verification failed, file has been deleted");
} else {
throw e;
}
}
}
private void addUpdate(Update update) {
UpdaterController controller = UpdaterController.getInstance(activity);
controller.addUpdate(update, false);
}
private long getTimeStamp(File file) {
try {
final String metadataContent = readZippedFile(file, METADATA_PATH);
final String[] lines = metadataContent.split("\n");
for (String line : lines) {
if (!line.startsWith(METADATA_TIMESTAMP_KEY)) {
continue;
}
final String timeStampStr = line.replace(METADATA_TIMESTAMP_KEY, "");
return Long.parseLong(timeStampStr);
}
} catch (IOException e) {
Log.e(TAG, "Failed to read date from local update zip package", e);
} catch (NumberFormatException e) {
Log.e(TAG, "Failed to parse timestamp number from zip metadata file", e);
}
Log.e(TAG, "Couldn't find timestamp in zip file, falling back to $now");
return System.currentTimeMillis();
}
private String readZippedFile(File file, String path) throws IOException {
final StringBuilder sb = new StringBuilder();
InputStream iStream = null;
try (final ZipFile zip = new ZipFile(file)) {
final Enumeration<? extends ZipEntry> iterator = zip.entries();
while (iterator.hasMoreElements()) {
final ZipEntry entry = iterator.nextElement();
if (!METADATA_PATH.equals(entry.getName())) {
continue;
}
iStream = zip.getInputStream(entry);
break;
}
if (iStream == null) {
throw new FileNotFoundException("Couldn't find " + path + " in " + file.getName());
}
final byte[] buffer = new byte[1024];
int read;
while ((read = iStream.read(buffer)) > 0) {
sb.append(new String(buffer, 0, read, StandardCharsets.UTF_8));
}
} catch (IOException e) {
Log.e(TAG, "Failed to read file from zip package", e);
throw e;
} finally {
if (iStream != null) {
iStream.close();
}
}
return sb.toString();
}
public interface Callbacks {
void onImportStarted();
void onImportCompleted(Update update);
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.updater;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.PowerManager;
import android.os.SystemProperties;
import androidx.core.app.NotificationCompat;
import androidx.preference.PreferenceManager;
import org.lineageos.updater.misc.BuildInfoUtils;
import org.lineageos.updater.misc.Constants;
import org.lineageos.updater.misc.StringGenerator;
import org.lineageos.updater.misc.Utils;
import java.text.DateFormat;
public class UpdaterReceiver extends BroadcastReceiver {
public static final String ACTION_INSTALL_REBOOT =
"org.lineageos.updater.action.INSTALL_REBOOT";
private static final String INSTALL_ERROR_NOTIFICATION_CHANNEL =
"install_error_notification_channel";
private static boolean shouldShowUpdateFailedNotification(Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
// We can't easily detect failed re-installations
if (preferences.getBoolean(Constants.PREF_INSTALL_AGAIN, false) ||
preferences.getBoolean(Constants.PREF_INSTALL_NOTIFIED, false)) {
return false;
}
long buildTimestamp = SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0);
long lastBuildTimestamp = preferences.getLong(Constants.PREF_INSTALL_OLD_TIMESTAMP, -1);
return buildTimestamp == lastBuildTimestamp;
}
private static void showUpdateFailedNotification(Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String buildDate = StringGenerator.getDateLocalizedUTC(context,
DateFormat.MEDIUM, preferences.getLong(Constants.PREF_INSTALL_NEW_TIMESTAMP, 0));
String buildInfo = context.getString(R.string.list_build_version_date,
Utils.getDisplayVersion(BuildInfoUtils.getBuildVersion()), buildDate);
Intent notificationIntent = new Intent(context, UpdatesActivity.class);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
NotificationChannel notificationChannel = new NotificationChannel(
INSTALL_ERROR_NOTIFICATION_CHANNEL,
context.getString(R.string.update_failed_channel_title),
NotificationManager.IMPORTANCE_LOW);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,
INSTALL_ERROR_NOTIFICATION_CHANNEL)
.setContentIntent(intent)
.setSmallIcon(R.drawable.ic_system_update)
.setContentTitle(context.getString(R.string.update_failed_notification))
.setStyle(new NotificationCompat.BigTextStyle().bigText(buildInfo))
.setContentText(buildInfo);
NotificationManager nm = context.getSystemService(NotificationManager.class);
nm.createNotificationChannel(notificationChannel);
nm.notify(0, builder.build());
}
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_INSTALL_REBOOT.equals(intent.getAction())) {
PowerManager pm = context.getSystemService(PowerManager.class);
pm.reboot(null);
} else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
pref.edit().remove(Constants.PREF_NEEDS_REBOOT_ID).apply();
if (shouldShowUpdateFailedNotification(context)) {
pref.edit().putBoolean(Constants.PREF_INSTALL_NOTIFIED, true).apply();
showUpdateFailedNotification(context);
}
}
}
}

View File

@@ -0,0 +1,660 @@
/*
* Copyright (C) 2017-2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.updater;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.app.UiModeManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.icu.text.DateFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemProperties;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SwitchCompat;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.WindowInsetsCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.snackbar.Snackbar;
import org.json.JSONException;
import org.lineageos.updater.controller.UpdaterController;
import org.lineageos.updater.controller.UpdaterService;
import org.lineageos.updater.download.DownloadClient;
import org.lineageos.updater.misc.BuildInfoUtils;
import org.lineageos.updater.misc.Constants;
import org.lineageos.updater.misc.StringGenerator;
import org.lineageos.updater.misc.Utils;
import org.lineageos.updater.model.Update;
import org.lineageos.updater.model.UpdateInfo;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class UpdatesActivity extends UpdatesListActivity implements UpdateImporter.Callbacks {
private static final String TAG = "UpdatesActivity";
private UpdaterService mUpdaterService;
private BroadcastReceiver mBroadcastReceiver;
private UpdatesListAdapter mAdapter;
private View mRefreshIconView;
private RotateAnimation mRefreshAnimation;
private boolean mIsTV;
private UpdateInfo mToBeExported = null;
private final ActivityResultLauncher<Intent> mExportUpdate = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent intent = result.getData();
if (intent != null) {
Uri uri = intent.getData();
exportUpdate(uri);
}
}
});
private UpdateImporter mUpdateImporter;
@SuppressWarnings("deprecation")
private ProgressDialog importDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_updates);
mUpdateImporter = new UpdateImporter(this, this);
UiModeManager uiModeManager = getSystemService(UiModeManager.class);
mIsTV = uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
RecyclerView recyclerView = findViewById(R.id.recycler_view);
mAdapter = new UpdatesListAdapter(this);
recyclerView.setAdapter(mAdapter);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}
mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (UpdaterController.ACTION_UPDATE_STATUS.equals(intent.getAction())) {
String downloadId = intent.getStringExtra(UpdaterController.EXTRA_DOWNLOAD_ID);
handleDownloadStatusChange(downloadId);
mAdapter.notifyItemChanged(downloadId);
} else if (UpdaterController.ACTION_DOWNLOAD_PROGRESS.equals(intent.getAction()) ||
UpdaterController.ACTION_INSTALL_PROGRESS.equals(intent.getAction())) {
String downloadId = intent.getStringExtra(UpdaterController.EXTRA_DOWNLOAD_ID);
mAdapter.notifyItemChanged(downloadId);
} else if (UpdaterController.ACTION_UPDATE_REMOVED.equals(intent.getAction())) {
String downloadId = intent.getStringExtra(UpdaterController.EXTRA_DOWNLOAD_ID);
mAdapter.removeItem(downloadId);
}
}
};
if (!mIsTV) {
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(true);
final int statusBarHeight;
TypedValue tv = new TypedValue();
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
statusBarHeight = TypedValue.complexToDimensionPixelSize(
tv.data, getResources().getDisplayMetrics());
} else {
statusBarHeight = 0;
}
RelativeLayout headerContainer = findViewById(R.id.header_container);
recyclerView.setOnApplyWindowInsetsListener((view, insets) -> {
int top = insets.getInsets(WindowInsetsCompat.Type.statusBars()).top;
CollapsingToolbarLayout.LayoutParams lp =
(CollapsingToolbarLayout.LayoutParams)
headerContainer.getLayoutParams();
lp.topMargin = top + statusBarHeight;
headerContainer.setLayoutParams(lp);
return insets;
});
}
}
TextView headerTitle = findViewById(R.id.header_title);
headerTitle.setText(getString(R.string.header_title_text,
Utils.getDisplayVersion(BuildInfoUtils.getBuildVersion())));
updateLastCheckedString();
TextView headerBuildVersion = findViewById(R.id.header_build_version);
headerBuildVersion.setText(
getString(R.string.header_android_version, Build.VERSION.RELEASE));
TextView headerBuildDate = findViewById(R.id.header_build_date);
headerBuildDate.setText(StringGenerator.getDateLocalizedUTC(this,
DateFormat.LONG, BuildInfoUtils.getBuildDateTimestamp()));
if (!mIsTV) {
// Switch between header title and appbar title minimizing overlaps
final CollapsingToolbarLayout collapsingToolbar = findViewById(R.id.collapsing_toolbar);
final AppBarLayout appBar = findViewById(R.id.app_bar);
appBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean mIsShown = false;
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
int scrollRange = appBarLayout.getTotalScrollRange();
if (!mIsShown && scrollRange + verticalOffset < 10) {
collapsingToolbar.setTitle(getString(R.string.display_name));
mIsShown = true;
} else if (mIsShown && scrollRange + verticalOffset > 100) {
collapsingToolbar.setTitle(null);
mIsShown = false;
}
}
});
mRefreshAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
mRefreshAnimation.setInterpolator(new LinearInterpolator());
mRefreshAnimation.setDuration(1000);
if (!Utils.hasTouchscreen(this)) {
// This can't be collapsed without a touchscreen
appBar.setExpanded(false);
}
} else {
findViewById(R.id.refresh).setOnClickListener(v -> downloadUpdatesList(true));
findViewById(R.id.preferences).setOnClickListener(v -> showPreferencesDialog());
}
}
@Override
public void onStart() {
super.onStart();
Intent intent = new Intent(this, UpdaterService.class);
startService(intent);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(UpdaterController.ACTION_UPDATE_STATUS);
intentFilter.addAction(UpdaterController.ACTION_DOWNLOAD_PROGRESS);
intentFilter.addAction(UpdaterController.ACTION_INSTALL_PROGRESS);
intentFilter.addAction(UpdaterController.ACTION_UPDATE_REMOVED);
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, intentFilter);
}
@Override
protected void onPause() {
if (importDialog != null) {
importDialog.dismiss();
importDialog = null;
mUpdateImporter.stopImport();
}
super.onPause();
}
@Override
public void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
if (mUpdaterService != null) {
unbindService(mConnection);
}
super.onStop();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_toolbar, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.menu_refresh) {
downloadUpdatesList(true);
return true;
} else if (itemId == R.id.menu_preferences) {
showPreferencesDialog();
return true;
} else if (itemId == R.id.menu_show_changelog) {
Intent openUrl = new Intent(Intent.ACTION_VIEW,
Uri.parse(Utils.getChangelogURL(this)));
startActivity(openUrl);
return true;
} else if (itemId == R.id.menu_local_update) {
mUpdateImporter.openImportPicker();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (!mUpdateImporter.onResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
@SuppressWarnings("deprecation")
public void onImportStarted() {
if (importDialog != null && importDialog.isShowing()) {
importDialog.dismiss();
}
importDialog = ProgressDialog.show(this, getString(R.string.local_update_import),
getString(R.string.local_update_import_progress), true, false);
}
@Override
public void onImportCompleted(Update update) {
if (importDialog != null) {
importDialog.dismiss();
importDialog = null;
}
if (update == null) {
new AlertDialog.Builder(this)
.setTitle(R.string.local_update_import)
.setMessage(R.string.local_update_import_failure)
.setPositiveButton(android.R.string.ok, null)
.show();
return;
}
mAdapter.notifyDataSetChanged();
final Runnable deleteUpdate = () -> UpdaterController.getInstance(this)
.deleteUpdate(update.getDownloadId());
new AlertDialog.Builder(this)
.setTitle(R.string.local_update_import)
.setMessage(getString(R.string.local_update_import_success, update.getVersion()))
.setPositiveButton(R.string.local_update_import_install, (dialog, which) -> {
mAdapter.addItem(update.getDownloadId());
// Update UI
getUpdatesList();
Utils.triggerUpdate(this, update.getDownloadId());
})
.setNegativeButton(android.R.string.cancel, (dialog, which) -> deleteUpdate.run())
.setOnCancelListener((dialog) -> deleteUpdate.run())
.show();
}
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
UpdaterService.LocalBinder binder = (UpdaterService.LocalBinder) service;
mUpdaterService = binder.getService();
mAdapter.setUpdaterController(mUpdaterService.getUpdaterController());
getUpdatesList();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mAdapter.setUpdaterController(null);
mUpdaterService = null;
mAdapter.notifyDataSetChanged();
}
};
private void loadUpdatesList(File jsonFile, boolean manualRefresh)
throws IOException, JSONException {
Log.d(TAG, "Adding remote updates");
UpdaterController controller = mUpdaterService.getUpdaterController();
boolean newUpdates = false;
List<UpdateInfo> updates = Utils.parseJson(jsonFile, true);
List<String> updatesOnline = new ArrayList<>();
for (UpdateInfo update : updates) {
newUpdates |= controller.addUpdate(update);
updatesOnline.add(update.getDownloadId());
}
controller.setUpdatesAvailableOnline(updatesOnline, true);
if (manualRefresh) {
showSnackbar(
newUpdates ? R.string.snack_updates_found : R.string.snack_no_updates_found,
Snackbar.LENGTH_SHORT);
}
List<String> updateIds = new ArrayList<>();
List<UpdateInfo> sortedUpdates = controller.getUpdates();
if (sortedUpdates.isEmpty()) {
findViewById(R.id.no_new_updates_view).setVisibility(View.VISIBLE);
findViewById(R.id.recycler_view).setVisibility(View.GONE);
} else {
findViewById(R.id.no_new_updates_view).setVisibility(View.GONE);
findViewById(R.id.recycler_view).setVisibility(View.VISIBLE);
sortedUpdates.sort((u1, u2) -> Long.compare(u2.getTimestamp(), u1.getTimestamp()));
for (UpdateInfo update : sortedUpdates) {
updateIds.add(update.getDownloadId());
}
mAdapter.setData(updateIds);
mAdapter.notifyDataSetChanged();
}
}
private void getUpdatesList() {
File jsonFile = Utils.getCachedUpdateList(this);
if (jsonFile.exists()) {
try {
loadUpdatesList(jsonFile, false);
Log.d(TAG, "Cached list parsed");
} catch (IOException | JSONException e) {
Log.e(TAG, "Error while parsing json list", e);
}
} else {
downloadUpdatesList(false);
}
}
private void processNewJson(File json, File jsonNew, boolean manualRefresh) {
try {
loadUpdatesList(jsonNew, manualRefresh);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
long millis = System.currentTimeMillis();
preferences.edit().putLong(Constants.PREF_LAST_UPDATE_CHECK, millis).apply();
updateLastCheckedString();
if (json.exists() && Utils.isUpdateCheckEnabled(this) &&
Utils.checkForNewUpdates(json, jsonNew)) {
UpdatesCheckReceiver.updateRepeatingUpdatesCheck(this);
}
// In case we set a one-shot check because of a previous failure
UpdatesCheckReceiver.cancelUpdatesCheck(this);
//noinspection ResultOfMethodCallIgnored
jsonNew.renameTo(json);
} catch (IOException | JSONException e) {
Log.e(TAG, "Could not read json", e);
showSnackbar(R.string.snack_updates_check_failed, Snackbar.LENGTH_LONG);
}
}
private void downloadUpdatesList(final boolean manualRefresh) {
final File jsonFile = Utils.getCachedUpdateList(this);
final File jsonFileTmp = new File(jsonFile.getAbsolutePath() + UUID.randomUUID());
String url = Utils.getServerURL(this);
Log.d(TAG, "Checking " + url);
DownloadClient.DownloadCallback callback = new DownloadClient.DownloadCallback() {
@Override
public void onFailure(final boolean cancelled) {
Log.e(TAG, "Could not download updates list");
runOnUiThread(() -> {
if (!cancelled) {
showSnackbar(R.string.snack_updates_check_failed, Snackbar.LENGTH_LONG);
}
refreshAnimationStop();
});
}
@Override
public void onResponse(DownloadClient.Headers headers) {
}
@Override
public void onSuccess() {
runOnUiThread(() -> {
Log.d(TAG, "List downloaded");
processNewJson(jsonFile, jsonFileTmp, manualRefresh);
refreshAnimationStop();
});
}
};
final DownloadClient downloadClient;
try {
downloadClient = new DownloadClient.Builder()
.setUrl(url)
.setDestination(jsonFileTmp)
.setDownloadCallback(callback)
.build();
} catch (IOException exception) {
Log.e(TAG, "Could not build download client");
showSnackbar(R.string.snack_updates_check_failed, Snackbar.LENGTH_LONG);
return;
}
refreshAnimationStart();
downloadClient.start();
}
private void updateLastCheckedString() {
final SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(this);
long lastCheck = preferences.getLong(Constants.PREF_LAST_UPDATE_CHECK, -1) / 1000;
String lastCheckString = getString(R.string.header_last_updates_check,
StringGenerator.getDateLocalized(this, DateFormat.LONG, lastCheck),
StringGenerator.getTimeLocalized(this, lastCheck));
TextView headerLastCheck = findViewById(R.id.header_last_check);
headerLastCheck.setText(lastCheckString);
}
private void handleDownloadStatusChange(String downloadId) {
if (Update.LOCAL_ID.equals(downloadId)) {
return;
}
UpdateInfo update = mUpdaterService.getUpdaterController().getUpdate(downloadId);
switch (update.getStatus()) {
case PAUSED_ERROR:
showSnackbar(R.string.snack_download_failed, Snackbar.LENGTH_LONG);
break;
case VERIFICATION_FAILED:
showSnackbar(R.string.snack_download_verification_failed, Snackbar.LENGTH_LONG);
break;
case VERIFIED:
showSnackbar(R.string.snack_download_verified, Snackbar.LENGTH_LONG);
break;
}
}
@Override
public void exportUpdate(UpdateInfo update) {
mToBeExported = update;
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/zip");
intent.putExtra(Intent.EXTRA_TITLE, update.getName());
mExportUpdate.launch(intent);
}
private void exportUpdate(Uri uri) {
Intent intent = new Intent(this, ExportUpdateService.class);
intent.setAction(ExportUpdateService.ACTION_START_EXPORTING);
intent.putExtra(ExportUpdateService.EXTRA_SOURCE_FILE, mToBeExported.getFile());
intent.putExtra(ExportUpdateService.EXTRA_DEST_URI, uri);
startService(intent);
}
@Override
public void showSnackbar(int stringId, int duration) {
Snackbar.make(findViewById(R.id.main_container), stringId, duration).show();
}
private void refreshAnimationStart() {
if (!mIsTV) {
if (mRefreshIconView == null) {
mRefreshIconView = findViewById(R.id.menu_refresh);
}
if (mRefreshIconView != null) {
mRefreshAnimation.setRepeatCount(Animation.INFINITE);
mRefreshIconView.startAnimation(mRefreshAnimation);
mRefreshIconView.setEnabled(false);
}
} else {
findViewById(R.id.recycler_view).setVisibility(View.GONE);
findViewById(R.id.no_new_updates_view).setVisibility(View.GONE);
findViewById(R.id.refresh_progress).setVisibility(View.VISIBLE);
}
}
private void refreshAnimationStop() {
if (!mIsTV) {
if (mRefreshIconView != null) {
mRefreshAnimation.setRepeatCount(0);
mRefreshIconView.setEnabled(true);
}
} else {
findViewById(R.id.refresh_progress).setVisibility(View.GONE);
if (mAdapter.getItemCount() > 0) {
findViewById(R.id.recycler_view).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.no_new_updates_view).setVisibility(View.VISIBLE);
}
}
}
@SuppressLint("ClickableViewAccessibility")
private void showPreferencesDialog() {
View view = LayoutInflater.from(this).inflate(R.layout.preferences_dialog, null);
Spinner autoCheckInterval = view.findViewById(R.id.preferences_auto_updates_check_interval);
SwitchCompat autoDelete = view.findViewById(R.id.preferences_auto_delete_updates);
SwitchCompat meteredNetworkWarning = view.findViewById(
R.id.preferences_metered_network_warning);
SwitchCompat abPerfMode = view.findViewById(R.id.preferences_ab_perf_mode);
SwitchCompat updateRecovery = view.findViewById(R.id.preferences_update_recovery);
if (!Utils.isABDevice()) {
abPerfMode.setVisibility(View.GONE);
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
autoCheckInterval.setSelection(Utils.getUpdateCheckSetting(this));
autoDelete.setChecked(prefs.getBoolean(Constants.PREF_AUTO_DELETE_UPDATES, false));
meteredNetworkWarning.setChecked(prefs.getBoolean(Constants.PREF_METERED_NETWORK_WARNING,
prefs.getBoolean(Constants.PREF_MOBILE_DATA_WARNING, true)));
abPerfMode.setChecked(prefs.getBoolean(Constants.PREF_AB_PERF_MODE, false));
if (getResources().getBoolean(R.bool.config_hideRecoveryUpdate)) {
// Hide the update feature if explicitly requested.
// Might be the case of A-only devices using prebuilt vendor images.
updateRecovery.setVisibility(View.GONE);
} else if (Utils.isRecoveryUpdateExecPresent()) {
updateRecovery.setChecked(
SystemProperties.getBoolean(Constants.UPDATE_RECOVERY_PROPERTY, false));
} else {
// There is no recovery updater script in the device, so the feature is considered
// forcefully enabled, just to avoid users to be confused and complain that
// recovery gets overwritten. That's the case of A/B and recovery-in-boot devices.
updateRecovery.setChecked(true);
updateRecovery.setOnTouchListener(new View.OnTouchListener() {
private Toast forcedUpdateToast = null;
@Override
public boolean onTouch(View v, MotionEvent event) {
if (forcedUpdateToast != null) {
forcedUpdateToast.cancel();
}
forcedUpdateToast = Toast.makeText(getApplicationContext(),
getString(R.string.toast_forced_update_recovery), Toast.LENGTH_SHORT);
forcedUpdateToast.show();
return true;
}
});
}
new AlertDialog.Builder(this)
.setTitle(R.string.menu_preferences)
.setView(view)
.setOnDismissListener(dialogInterface -> {
prefs.edit()
.putInt(Constants.PREF_AUTO_UPDATES_CHECK_INTERVAL,
autoCheckInterval.getSelectedItemPosition())
.putBoolean(Constants.PREF_AUTO_DELETE_UPDATES, autoDelete.isChecked())
.putBoolean(Constants.PREF_METERED_NETWORK_WARNING,
meteredNetworkWarning.isChecked())
.putBoolean(Constants.PREF_AB_PERF_MODE, abPerfMode.isChecked())
.apply();
if (Utils.isUpdateCheckEnabled(this)) {
UpdatesCheckReceiver.scheduleRepeatingUpdatesCheck(this);
} else {
UpdatesCheckReceiver.cancelRepeatingUpdatesCheck(this);
UpdatesCheckReceiver.cancelUpdatesCheck(this);
}
if (Utils.isABDevice()) {
boolean enableABPerfMode = abPerfMode.isChecked();
mUpdaterService.getUpdaterController().setPerformanceMode(enableABPerfMode);
}
if (Utils.isRecoveryUpdateExecPresent()) {
boolean enableRecoveryUpdate = updateRecovery.isChecked();
SystemProperties.set(Constants.UPDATE_RECOVERY_PROPERTY,
String.valueOf(enableRecoveryUpdate));
}
})
.show();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.lineageos.updater;
import android.app.AlarmManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -23,21 +24,20 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v7.app.NotificationCompat;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import androidx.preference.PreferenceManager;
import org.json.JSONException;
import org.lineageos.updater.download.DownloadClient;
import org.lineageos.updater.misc.Constants;
import org.lineageos.updater.misc.Utils;
import org.lineageos.updater.model.UpdateInfo;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;
public class UpdatesCheckReceiver extends BroadcastReceiver {
@@ -46,6 +46,9 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
private static final String DAILY_CHECK_ACTION = "daily_check_action";
private static final String ONESHOT_CHECK_ACTION = "oneshot_check_action";
private static final String NEW_UPDATES_NOTIFICATION_CHANNEL =
"new_updates_notification_channel";
@Override
public void onReceive(final Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
@@ -54,7 +57,8 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
final SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(context);
if (!preferences.getBoolean(Constants.PREF_AUTO_UPDATES_CHECK, true)) {
if (!Utils.isUpdateCheckEnabled(context)) {
return;
}
@@ -70,7 +74,7 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
}
final File json = Utils.getCachedUpdateList(context);
final File jsonNew = new File(json.getAbsolutePath() + ".tmp");
final File jsonNew = new File(json.getAbsolutePath() + UUID.randomUUID());
String url = Utils.getServerURL(context);
DownloadClient.DownloadCallback callback = new DownloadClient.DownloadCallback() {
@Override
@@ -80,17 +84,17 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
}
@Override
public void onResponse(int statusCode, String url,
DownloadClient.Headers headers) {
public void onResponse(DownloadClient.Headers headers) {
}
@Override
public void onSuccess(File destination) {
public void onSuccess() {
try {
if (json.exists() && Utils.checkForNewUpdates(json, jsonNew)) {
showNotification(context);
updateRepeatingUpdatesCheck(context);
}
//noinspection ResultOfMethodCallIgnored
jsonNew.renameTo(json);
long currentMillis = System.currentTimeMillis();
preferences.edit()
@@ -119,23 +123,29 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
}
private static void showNotification(Context context) {
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context);
NotificationManager notificationManager = context.getSystemService(
NotificationManager.class);
NotificationChannel notificationChannel = new NotificationChannel(
NEW_UPDATES_NOTIFICATION_CHANNEL,
context.getString(R.string.new_updates_channel_title),
NotificationManager.IMPORTANCE_LOW);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context,
NEW_UPDATES_NOTIFICATION_CHANNEL);
notificationBuilder.setSmallIcon(R.drawable.ic_system_update);
Intent notificationIntent = new Intent(context, UpdatesActivity.class);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
notificationBuilder.setContentIntent(intent);
notificationBuilder.setContentTitle(context.getString(R.string.new_updates_found_title));
notificationBuilder.setAutoCancel(true);
notificationManager.createNotificationChannel(notificationChannel);
notificationManager.notify(0, notificationBuilder.build());
}
private static PendingIntent getRepeatingUpdatesCheckIntent(Context context) {
Intent intent = new Intent(context, UpdatesCheckReceiver.class);
intent.setAction(DAILY_CHECK_ACTION);
return PendingIntent.getBroadcast(context, 0, intent, 0);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
}
public static void updateRepeatingUpdatesCheck(Context context) {
@@ -144,32 +154,36 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
}
public static void scheduleRepeatingUpdatesCheck(Context context) {
long millisToNextRelease = millisToNextRelease(context);
PendingIntent updateCheckIntent = getRepeatingUpdatesCheckIntent(context);
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + millisToNextRelease,
AlarmManager.INTERVAL_DAY, updateCheckIntent);
if (!Utils.isUpdateCheckEnabled(context)) {
return;
}
Date nextCheckDate = new Date(System.currentTimeMillis() + millisToNextRelease);
Log.d(TAG, "Setting daily updates check: " + nextCheckDate);
PendingIntent updateCheckIntent = getRepeatingUpdatesCheckIntent(context);
AlarmManager alarmMgr = context.getSystemService(AlarmManager.class);
alarmMgr.setRepeating(AlarmManager.RTC, System.currentTimeMillis() +
Utils.getUpdateCheckInterval(context), Utils.getUpdateCheckInterval(context),
updateCheckIntent);
Date nextCheckDate = new Date(System.currentTimeMillis() +
Utils.getUpdateCheckInterval(context));
Log.d(TAG, "Setting automatic updates check: " + nextCheckDate);
}
public static void cancelRepeatingUpdatesCheck(Context context) {
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
AlarmManager alarmMgr = context.getSystemService(AlarmManager.class);
alarmMgr.cancel(getRepeatingUpdatesCheckIntent(context));
}
private static PendingIntent getUpdatesCheckIntent(Context context) {
Intent intent = new Intent(context, UpdatesCheckReceiver.class);
intent.setAction(ONESHOT_CHECK_ACTION);
return PendingIntent.getBroadcast(context, 0, intent, 0);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
}
public static void scheduleUpdatesCheck(Context context) {
long millisToNextCheck = AlarmManager.INTERVAL_HOUR * 2;
PendingIntent updateCheckIntent = getUpdatesCheckIntent(context);
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
AlarmManager alarmMgr = context.getSystemService(AlarmManager.class);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + millisToNextCheck,
updateCheckIntent);
@@ -179,55 +193,8 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
}
public static void cancelUpdatesCheck(Context context) {
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
AlarmManager alarmMgr = context.getSystemService(AlarmManager.class);
alarmMgr.cancel(getUpdatesCheckIntent(context));
Log.d(TAG, "Cancelling pending one-shot check");
}
private static long millisToNextRelease(Context context) {
final long extraMillis = 3 * AlarmManager.INTERVAL_HOUR;
List<UpdateInfo> updates = null;
try {
updates = Utils.parseJson(Utils.getCachedUpdateList(context), false);
} catch (IOException | JSONException ignored) {
}
if (updates == null || updates.size() == 0) {
return SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY;
}
long buildTimestamp = 0;
for (UpdateInfo update : updates) {
if (update.getTimestamp() > buildTimestamp) {
buildTimestamp = update.getTimestamp();
}
}
buildTimestamp *= 1000;
Calendar c = Calendar.getInstance();
long now = c.getTimeInMillis();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
c.setTimeInMillis(c.getTimeInMillis() + millisSinceMidnight(buildTimestamp));
long millisToNextRelease = (c.getTimeInMillis() - now);
millisToNextRelease += extraMillis;
if (c.getTimeInMillis() < now) {
millisToNextRelease += AlarmManager.INTERVAL_DAY;
}
return millisToNextRelease;
}
private static long millisSinceMidnight(long millis) {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(millis);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
return millis - c.getTimeInMillis();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -75,9 +75,14 @@ public class UpdatesDbHelper extends SQLiteOpenHelper {
onUpgrade(db, oldVersion, newVersion);
}
public long addUpdate(Update update) {
public void addUpdateWithOnConflict(Update update, int conflictAlgorithm) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
fillContentValues(update, values);
db.insertWithOnConflict(UpdateEntry.TABLE_NAME, null, values, conflictAlgorithm);
}
private static void fillContentValues(Update update, ContentValues values) {
values.put(UpdateEntry.COLUMN_NAME_STATUS, update.getPersistentStatus());
values.put(UpdateEntry.COLUMN_NAME_PATH, update.getFile().getAbsolutePath());
values.put(UpdateEntry.COLUMN_NAME_DOWNLOAD_ID, update.getDownloadId());
@@ -85,68 +90,27 @@ public class UpdatesDbHelper extends SQLiteOpenHelper {
values.put(UpdateEntry.COLUMN_NAME_TYPE, update.getType());
values.put(UpdateEntry.COLUMN_NAME_VERSION, update.getVersion());
values.put(UpdateEntry.COLUMN_NAME_SIZE, update.getFileSize());
return db.insert(UpdateEntry.TABLE_NAME, null, values);
}
public long addUpdateWithOnConflict(Update update, int conflictAlgorithm) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put(UpdateEntry.COLUMN_NAME_STATUS, update.getPersistentStatus());
values.put(UpdateEntry.COLUMN_NAME_PATH, update.getFile().getAbsolutePath());
values.put(UpdateEntry.COLUMN_NAME_DOWNLOAD_ID, update.getDownloadId());
values.put(UpdateEntry.COLUMN_NAME_TIMESTAMP, update.getTimestamp());
values.put(UpdateEntry.COLUMN_NAME_TYPE, update.getType());
values.put(UpdateEntry.COLUMN_NAME_VERSION, update.getVersion());
values.put(UpdateEntry.COLUMN_NAME_SIZE, update.getFileSize());
return db.insertWithOnConflict(UpdateEntry.TABLE_NAME, null, values, conflictAlgorithm);
}
public boolean removeUpdate(String downloadId) {
public void removeUpdate(String downloadId) {
SQLiteDatabase db = getWritableDatabase();
String selection = UpdateEntry.COLUMN_NAME_DOWNLOAD_ID + " = ?";
String[] selectionArgs = {downloadId};
return db.delete(UpdateEntry.TABLE_NAME, selection, selectionArgs) != 0;
db.delete(UpdateEntry.TABLE_NAME, selection, selectionArgs);
}
public boolean removeUpdate(long rowId) {
SQLiteDatabase db = getWritableDatabase();
String selection = UpdateEntry._ID + " = " + rowId;
return db.delete(UpdateEntry.TABLE_NAME, selection, null) != 0;
}
public boolean changeUpdateStatus(Update update) {
public void changeUpdateStatus(Update update) {
String selection = UpdateEntry.COLUMN_NAME_DOWNLOAD_ID + " = ?";
String[] selectionArgs = {update.getDownloadId()};
return changeUpdateStatus(selection, selectionArgs, update.getPersistentStatus());
changeUpdateStatus(selection, selectionArgs, update.getPersistentStatus());
}
public boolean changeUpdateStatus(long rowId, int status) {
String selection = UpdateEntry._ID + " = " + rowId;
return changeUpdateStatus(selection, null, status);
}
private boolean changeUpdateStatus(String selection, String[] selectionArgs,
private void changeUpdateStatus(String selection, String[] selectionArgs,
int status) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put(UpdateEntry.COLUMN_NAME_STATUS, status);
return db.update(UpdateEntry.TABLE_NAME, values, selection, selectionArgs) != 0;
}
public Update getUpdate(long rowId) {
String selection = UpdateEntry._ID + " = " + rowId;
return getUpdate(selection, null);
}
public Update getUpdate(String downloadId) {
String selection = UpdateEntry.COLUMN_NAME_DOWNLOAD_ID + " = ?";
String[] selectionArgs = {downloadId};
return getUpdate(selection, selectionArgs);
}
private Update getUpdate(String selection, String[] selectionArgs) {
List<Update> updates = getUpdates(selection, selectionArgs);
return updates != null ? updates.get(0) : null;
db.update(UpdateEntry.TABLE_NAME, values, selection, selectionArgs);
}
public List<Update> getUpdates() {

View File

@@ -15,8 +15,11 @@
*/
package org.lineageos.updater;
import android.support.v7.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
import org.lineageos.updater.model.UpdateInfo;
public abstract class UpdatesListActivity extends AppCompatActivity {
public abstract void exportUpdate(UpdateInfo update);
public abstract void showSnackbar(int stringId, int duration);
}

View File

@@ -0,0 +1,629 @@
/*
* Copyright (C) 2017-2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.updater;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.PowerManager;
import android.text.SpannableString;
import android.text.format.Formatter;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.view.menu.MenuBuilder;
import androidx.appcompat.view.menu.MenuPopupHelper;
import androidx.appcompat.widget.PopupMenu;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.snackbar.Snackbar;
import org.lineageos.updater.controller.UpdaterController;
import org.lineageos.updater.controller.UpdaterService;
import org.lineageos.updater.misc.BuildInfoUtils;
import org.lineageos.updater.misc.Constants;
import org.lineageos.updater.misc.StringGenerator;
import org.lineageos.updater.misc.Utils;
import org.lineageos.updater.model.UpdateInfo;
import org.lineageos.updater.model.UpdateStatus;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.ViewHolder> {
private static final String TAG = "UpdateListAdapter";
private static final int BATTERY_PLUGGED_ANY = BatteryManager.BATTERY_PLUGGED_AC
| BatteryManager.BATTERY_PLUGGED_USB
| BatteryManager.BATTERY_PLUGGED_WIRELESS;
private final float mAlphaDisabledValue;
private List<String> mDownloadIds;
private String mSelectedDownload;
private UpdaterController mUpdaterController;
private final UpdatesListActivity mActivity;
private AlertDialog infoDialog;
private enum Action {
DOWNLOAD,
PAUSE,
RESUME,
INSTALL,
INFO,
DELETE,
CANCEL_INSTALLATION,
REBOOT,
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private final Button mAction;
private final ImageButton mMenu;
private final TextView mBuildDate;
private final TextView mBuildVersion;
private final TextView mBuildSize;
private final LinearLayout mProgress;
private final ProgressBar mProgressBar;
private final TextView mProgressText;
private final TextView mPercentage;
public ViewHolder(final View view) {
super(view);
mAction = view.findViewById(R.id.update_action);
mMenu = view.findViewById(R.id.update_menu);
mBuildDate = view.findViewById(R.id.build_date);
mBuildVersion = view.findViewById(R.id.build_version);
mBuildSize = view.findViewById(R.id.build_size);
mProgress = view.findViewById(R.id.progress);
mProgressBar = view.findViewById(R.id.progress_bar);
mProgressText = view.findViewById(R.id.progress_text);
mPercentage = view.findViewById(R.id.progress_percent);
}
}
public UpdatesListAdapter(UpdatesListActivity activity) {
mActivity = activity;
TypedValue tv = new TypedValue();
mActivity.getTheme().resolveAttribute(android.R.attr.disabledAlpha, tv, true);
mAlphaDisabledValue = tv.getFloat();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.update_item_view, viewGroup, false);
return new ViewHolder(view);
}
@Override
public void onViewDetachedFromWindow(@NonNull ViewHolder holder) {
super.onViewDetachedFromWindow(holder);
if (infoDialog != null) {
infoDialog.dismiss();
}
}
public void setUpdaterController(UpdaterController updaterController) {
mUpdaterController = updaterController;
notifyDataSetChanged();
}
private void handleActiveStatus(ViewHolder viewHolder, UpdateInfo update) {
boolean canDelete = false;
final String downloadId = update.getDownloadId();
if (mUpdaterController.isDownloading(downloadId)) {
canDelete = true;
String downloaded = Formatter.formatShortFileSize(mActivity,
update.getFile().length());
String total = Formatter.formatShortFileSize(mActivity, update.getFileSize());
String percentage = NumberFormat.getPercentInstance().format(
update.getProgress() / 100.f);
viewHolder.mPercentage.setText(percentage);
long eta = update.getEta();
if (eta > 0) {
CharSequence etaString = StringGenerator.formatETA(mActivity, eta * 1000);
viewHolder.mProgressText.setText(mActivity.getString(
R.string.list_download_progress_eta_newer, downloaded, total, etaString));
} else {
viewHolder.mProgressText.setText(mActivity.getString(
R.string.list_download_progress_newer, downloaded, total));
}
setButtonAction(viewHolder.mAction, Action.PAUSE, downloadId, true);
viewHolder.mProgressBar.setIndeterminate(update.getStatus() == UpdateStatus.STARTING);
viewHolder.mProgressBar.setProgress(update.getProgress());
} else if (mUpdaterController.isInstallingUpdate(downloadId)) {
setButtonAction(viewHolder.mAction, Action.CANCEL_INSTALLATION, downloadId, true);
boolean notAB = !mUpdaterController.isInstallingABUpdate();
viewHolder.mProgressText.setText(notAB ? R.string.dialog_prepare_zip_message :
update.getFinalizing() ?
R.string.finalizing_package :
R.string.preparing_ota_first_boot);
String percentage = NumberFormat.getPercentInstance().format(
update.getInstallProgress() / 100.f);
viewHolder.mPercentage.setText(percentage);
viewHolder.mProgressBar.setIndeterminate(false);
viewHolder.mProgressBar.setProgress(update.getInstallProgress());
} else if (mUpdaterController.isVerifyingUpdate(downloadId)) {
setButtonAction(viewHolder.mAction, Action.INSTALL, downloadId, false);
viewHolder.mProgressText.setText(R.string.list_verifying_update);
viewHolder.mProgressBar.setIndeterminate(true);
} else {
canDelete = true;
setButtonAction(viewHolder.mAction, Action.RESUME, downloadId, !isBusy());
String downloaded = Formatter.formatShortFileSize(mActivity,
update.getFile().length());
String total = Formatter.formatShortFileSize(mActivity, update.getFileSize());
String percentage = NumberFormat.getPercentInstance().format(
update.getProgress() / 100.f);
viewHolder.mPercentage.setText(percentage);
viewHolder.mProgressText.setText(mActivity.getString(
R.string.list_download_progress_newer, downloaded, total));
viewHolder.mProgressBar.setIndeterminate(false);
viewHolder.mProgressBar.setProgress(update.getProgress());
}
viewHolder.mMenu.setOnClickListener(getClickListener(update, canDelete, viewHolder.mMenu));
viewHolder.mProgress.setVisibility(View.VISIBLE);
viewHolder.mProgressText.setVisibility(View.VISIBLE);
viewHolder.mBuildSize.setVisibility(View.INVISIBLE);
}
private void handleNotActiveStatus(ViewHolder viewHolder, UpdateInfo update) {
final String downloadId = update.getDownloadId();
if (mUpdaterController.isWaitingForReboot(downloadId)) {
viewHolder.mMenu.setOnClickListener(getClickListener(update, false, viewHolder.mMenu));
setButtonAction(viewHolder.mAction, Action.REBOOT, downloadId, true);
} else if (update.getPersistentStatus() == UpdateStatus.Persistent.VERIFIED) {
viewHolder.mMenu.setOnClickListener(getClickListener(update, true, viewHolder.mMenu));
setButtonAction(viewHolder.mAction,
Utils.canInstall(update) ? Action.INSTALL : Action.DELETE,
downloadId, !isBusy());
} else if (!Utils.canInstall(update)) {
viewHolder.mMenu.setOnClickListener(getClickListener(update, false, viewHolder.mMenu));
setButtonAction(viewHolder.mAction, Action.INFO, downloadId, !isBusy());
} else {
viewHolder.mMenu.setOnClickListener(getClickListener(update, false, viewHolder.mMenu));
setButtonAction(viewHolder.mAction, Action.DOWNLOAD, downloadId, !isBusy());
}
String fileSize = Formatter.formatShortFileSize(mActivity, update.getFileSize());
viewHolder.mBuildSize.setText(fileSize);
viewHolder.mProgress.setVisibility(View.INVISIBLE);
viewHolder.mProgressText.setVisibility(View.INVISIBLE);
viewHolder.mBuildSize.setVisibility(View.VISIBLE);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int i) {
if (mDownloadIds == null) {
viewHolder.mAction.setEnabled(false);
return;
}
final String downloadId = mDownloadIds.get(i);
UpdateInfo update = mUpdaterController.getUpdate(downloadId);
if (update == null) {
// The update was deleted
viewHolder.mAction.setEnabled(false);
viewHolder.mAction.setText(R.string.action_download);
return;
}
viewHolder.itemView.setSelected(downloadId.equals(mSelectedDownload));
boolean activeLayout;
switch (update.getPersistentStatus()) {
case UpdateStatus.Persistent.UNKNOWN:
activeLayout = update.getStatus() == UpdateStatus.STARTING;
break;
case UpdateStatus.Persistent.VERIFIED:
activeLayout = update.getStatus() == UpdateStatus.INSTALLING;
break;
case UpdateStatus.Persistent.INCOMPLETE:
activeLayout = true;
break;
default:
throw new RuntimeException("Unknown update status");
}
String buildDate = StringGenerator.getDateLocalizedUTC(mActivity,
DateFormat.LONG, update.getTimestamp());
String buildVersion = mActivity.getString(R.string.list_build_version,
Utils.getDisplayVersion(update.getVersion()));
viewHolder.mBuildDate.setText(buildDate);
viewHolder.mBuildVersion.setText(buildVersion);
viewHolder.mBuildVersion.setCompoundDrawables(null, null, null, null);
if (activeLayout) {
handleActiveStatus(viewHolder, update);
} else {
handleNotActiveStatus(viewHolder, update);
}
}
@Override
public int getItemCount() {
return mDownloadIds == null ? 0 : mDownloadIds.size();
}
public void setData(List<String> downloadIds) {
mDownloadIds = downloadIds;
}
public void addItem(String downloadId) {
if (mDownloadIds == null) {
mDownloadIds = new ArrayList<>();
}
mDownloadIds.add(0, downloadId);
notifyItemInserted(0);
}
public void notifyItemChanged(String downloadId) {
if (mDownloadIds == null) {
return;
}
notifyItemChanged(mDownloadIds.indexOf(downloadId));
}
public void removeItem(String downloadId) {
if (mDownloadIds == null) {
return;
}
int position = mDownloadIds.indexOf(downloadId);
mDownloadIds.remove(downloadId);
notifyItemRemoved(position);
notifyItemRangeChanged(position, getItemCount());
}
private void startDownloadWithWarning(final String downloadId) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mActivity);
boolean warn = preferences.getBoolean(Constants.PREF_METERED_NETWORK_WARNING, true);
if (!(Utils.isNetworkMetered(mActivity) && warn)) {
mUpdaterController.startDownload(downloadId);
return;
}
View checkboxView = LayoutInflater.from(mActivity).inflate(R.layout.checkbox_view, null);
CheckBox checkbox = checkboxView.findViewById(R.id.checkbox);
checkbox.setText(R.string.checkbox_metered_network_warning);
new AlertDialog.Builder(mActivity)
.setTitle(R.string.update_over_metered_network_title)
.setMessage(R.string.update_over_metered_network_message)
.setView(checkboxView)
.setPositiveButton(R.string.action_download,
(dialog, which) -> {
if (checkbox.isChecked()) {
preferences.edit()
.putBoolean(Constants.PREF_METERED_NETWORK_WARNING, false)
.apply();
mActivity.supportInvalidateOptionsMenu();
}
mUpdaterController.startDownload(downloadId);
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
private void setButtonAction(Button button, Action action, final String downloadId,
boolean enabled) {
final View.OnClickListener clickListener;
switch (action) {
case DOWNLOAD:
button.setText(R.string.action_download);
button.setEnabled(enabled);
clickListener = enabled ? view -> startDownloadWithWarning(downloadId) : null;
break;
case PAUSE:
button.setText(R.string.action_pause);
button.setEnabled(enabled);
clickListener = enabled ? view -> mUpdaterController.pauseDownload(downloadId)
: null;
break;
case RESUME: {
button.setText(R.string.action_resume);
button.setEnabled(enabled);
UpdateInfo update = mUpdaterController.getUpdate(downloadId);
final boolean canInstall = Utils.canInstall(update) ||
update.getFile().length() == update.getFileSize();
clickListener = enabled ? view -> {
if (canInstall) {
mUpdaterController.resumeDownload(downloadId);
} else {
mActivity.showSnackbar(R.string.snack_update_not_installable,
Snackbar.LENGTH_LONG);
}
} : null;
}
break;
case INSTALL: {
button.setText(R.string.action_install);
button.setEnabled(enabled);
UpdateInfo update = mUpdaterController.getUpdate(downloadId);
final boolean canInstall = Utils.canInstall(update);
clickListener = enabled ? view -> {
if (canInstall) {
AlertDialog.Builder installDialog = getInstallDialog(downloadId);
if (installDialog != null) {
installDialog.show();
}
} else {
mActivity.showSnackbar(R.string.snack_update_not_installable,
Snackbar.LENGTH_LONG);
}
} : null;
}
break;
case INFO: {
button.setText(R.string.action_info);
button.setEnabled(enabled);
clickListener = enabled ? view -> showInfoDialog() : null;
}
break;
case DELETE: {
button.setText(R.string.action_delete);
button.setEnabled(enabled);
clickListener = enabled ? view -> getDeleteDialog(downloadId).show() : null;
}
break;
case CANCEL_INSTALLATION: {
button.setText(R.string.action_cancel);
button.setEnabled(enabled);
clickListener = enabled ? view -> getCancelInstallationDialog().show() : null;
}
break;
case REBOOT: {
button.setText(R.string.reboot);
button.setEnabled(enabled);
clickListener = enabled ? view -> {
PowerManager pm = mActivity.getSystemService(PowerManager.class);
pm.reboot(null);
} : null;
}
break;
default:
clickListener = null;
}
button.setAlpha(enabled ? 1.f : mAlphaDisabledValue);
// Disable action mode when a button is clicked
button.setOnClickListener(v -> {
if (clickListener != null) {
clickListener.onClick(v);
}
});
}
private boolean isBusy() {
return mUpdaterController.hasActiveDownloads() || mUpdaterController.isVerifyingUpdate()
|| mUpdaterController.isInstallingUpdate();
}
private AlertDialog.Builder getDeleteDialog(final String downloadId) {
return new AlertDialog.Builder(mActivity)
.setTitle(R.string.confirm_delete_dialog_title)
.setMessage(R.string.confirm_delete_dialog_message)
.setPositiveButton(android.R.string.ok,
(dialog, which) -> {
mUpdaterController.pauseDownload(downloadId);
mUpdaterController.deleteUpdate(downloadId);
})
.setNegativeButton(android.R.string.cancel, null);
}
private View.OnClickListener getClickListener(final UpdateInfo update,
final boolean canDelete, View anchor) {
return view -> startActionMode(update, canDelete, anchor);
}
private AlertDialog.Builder getInstallDialog(final String downloadId) {
if (!isBatteryLevelOk()) {
Resources resources = mActivity.getResources();
String message = resources.getString(R.string.dialog_battery_low_message_pct,
resources.getInteger(R.integer.battery_ok_percentage_discharging),
resources.getInteger(R.integer.battery_ok_percentage_charging));
return new AlertDialog.Builder(mActivity)
.setTitle(R.string.dialog_battery_low_title)
.setMessage(message)
.setPositiveButton(android.R.string.ok, null);
}
if (isScratchMounted()) {
return new AlertDialog.Builder(mActivity)
.setTitle(R.string.dialog_scratch_mounted_title)
.setMessage(R.string.dialog_scratch_mounted_message)
.setPositiveButton(android.R.string.ok, null);
}
UpdateInfo update = mUpdaterController.getUpdate(downloadId);
int resId;
try {
if (Utils.isABUpdate(update.getFile())) {
resId = R.string.apply_update_dialog_message_ab;
} else {
resId = R.string.apply_update_dialog_message;
}
} catch (IOException e) {
Log.e(TAG, "Could not determine the type of the update");
return null;
}
String buildDate = StringGenerator.getDateLocalizedUTC(mActivity,
DateFormat.MEDIUM, update.getTimestamp());
String buildInfoText = mActivity.getString(R.string.list_build_version_date,
update.getVersion(), buildDate);
return new AlertDialog.Builder(mActivity)
.setTitle(R.string.apply_update_dialog_title)
.setMessage(mActivity.getString(resId, buildInfoText,
mActivity.getString(android.R.string.ok)))
.setPositiveButton(android.R.string.ok,
(dialog, which) -> {
Utils.triggerUpdate(mActivity, downloadId);
maybeShowInfoDialog();
})
.setNegativeButton(android.R.string.cancel, null);
}
private AlertDialog.Builder getCancelInstallationDialog() {
return new AlertDialog.Builder(mActivity)
.setMessage(R.string.cancel_installation_dialog_message)
.setPositiveButton(android.R.string.ok,
(dialog, which) -> {
Intent intent = new Intent(mActivity, UpdaterService.class);
intent.setAction(UpdaterService.ACTION_INSTALL_STOP);
mActivity.startService(intent);
})
.setNegativeButton(android.R.string.cancel, null);
}
private void maybeShowInfoDialog() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mActivity);
boolean alreadySeen = preferences.getBoolean(Constants.HAS_SEEN_INFO_DIALOG, false);
if (alreadySeen) {
return;
}
new AlertDialog.Builder(mActivity)
.setTitle(R.string.info_dialog_title)
.setMessage(R.string.info_dialog_message)
.setPositiveButton(R.string.info_dialog_ok, (dialog, which) -> preferences.edit()
.putBoolean(Constants.HAS_SEEN_INFO_DIALOG, true)
.apply())
.show();
}
private void startActionMode(final UpdateInfo update, final boolean canDelete, View anchor) {
mSelectedDownload = update.getDownloadId();
notifyItemChanged(update.getDownloadId());
ContextThemeWrapper wrapper = new ContextThemeWrapper(mActivity,
R.style.AppTheme_PopupMenuOverlapAnchor);
PopupMenu popupMenu = new PopupMenu(wrapper, anchor, Gravity.NO_GRAVITY,
R.attr.actionOverflowMenuStyle, 0);
popupMenu.inflate(R.menu.menu_action_mode);
boolean shouldShowDelete = canDelete;
boolean isVerified = update.getPersistentStatus() == UpdateStatus.Persistent.VERIFIED;
if (isVerified && !Utils.canInstall(update) && !update.getAvailableOnline()) {
shouldShowDelete = false;
}
MenuBuilder menu = (MenuBuilder) popupMenu.getMenu();
menu.findItem(R.id.menu_delete_action).setVisible(shouldShowDelete);
menu.findItem(R.id.menu_copy_url).setVisible(update.getAvailableOnline());
menu.findItem(R.id.menu_export_update).setVisible(isVerified);
popupMenu.setOnMenuItemClickListener(item -> {
int itemId = item.getItemId();
if (itemId == R.id.menu_delete_action) {
getDeleteDialog(update.getDownloadId()).show();
return true;
} else if (itemId == R.id.menu_copy_url) {
Utils.addToClipboard(mActivity,
mActivity.getString(R.string.label_download_url),
update.getDownloadUrl(),
mActivity.getString(R.string.toast_download_url_copied));
return true;
} else if (itemId == R.id.menu_export_update) {
if (mActivity != null) {
mActivity.exportUpdate(update);
}
return true;
}
return false;
});
MenuPopupHelper helper = new MenuPopupHelper(wrapper, menu, anchor);
helper.show();
}
private void showInfoDialog() {
String messageString = String.format(StringGenerator.getCurrentLocale(mActivity),
mActivity.getString(R.string.blocked_update_dialog_message),
Utils.getUpgradeBlockedURL(mActivity));
SpannableString message = new SpannableString(messageString);
Linkify.addLinks(message, Linkify.WEB_URLS);
if (infoDialog != null) {
infoDialog.dismiss();
}
infoDialog = new AlertDialog.Builder(mActivity)
.setTitle(R.string.blocked_update_dialog_title)
.setPositiveButton(android.R.string.ok, null)
.setMessage(message)
.show();
TextView textView = infoDialog.findViewById(android.R.id.message);
if (textView != null) {
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
}
private boolean isBatteryLevelOk() {
Intent intent = mActivity.registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
if (!intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false)) {
return true;
}
int percent = Math.round(100.f * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100) /
intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
int required = (plugged & BATTERY_PLUGGED_ANY) != 0 ?
mActivity.getResources().getInteger(R.integer.battery_ok_percentage_charging) :
mActivity.getResources().getInteger(R.integer.battery_ok_percentage_discharging);
return percent >= required;
}
private static boolean isScratchMounted() {
try (Stream<String> lines = Files.lines(Path.of("/proc/mounts"))) {
return lines.anyMatch(x -> x.split(" ")[1].equals("/mnt/scratch"));
} catch (IOException e) {
return false;
}
}
}

View File

@@ -0,0 +1,338 @@
/*
* Copyright (C) 2017-2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.updater.controller;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.ServiceSpecificException;
import android.os.UpdateEngine;
import android.os.UpdateEngineCallback;
import android.text.TextUtils;
import android.util.Log;
import androidx.preference.PreferenceManager;
import org.lineageos.updater.misc.Constants;
import org.lineageos.updater.misc.Utils;
import org.lineageos.updater.model.Update;
import org.lineageos.updater.model.UpdateStatus;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
class ABUpdateInstaller {
private static final String TAG = "ABUpdateInstaller";
private static final String PREF_INSTALLING_AB_ID = "installing_ab_id";
private static final String PREF_INSTALLING_SUSPENDED_AB_ID = "installing_suspended_ab_id";
private static ABUpdateInstaller sInstance = null;
private final UpdaterController mUpdaterController;
private final Context mContext;
private String mDownloadId;
private final UpdateEngine mUpdateEngine;
private boolean mBound;
private boolean mFinalizing;
private int mProgress;
private final UpdateEngineCallback mUpdateEngineCallback = new UpdateEngineCallback() {
@Override
public void onStatusUpdate(int status, float percent) {
Update update = mUpdaterController.getActualUpdate(mDownloadId);
if (update == null) {
// We read the id from a preference, the update could no longer exist
installationDone(status == UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT);
return;
}
switch (status) {
case UpdateEngine.UpdateStatusConstants.DOWNLOADING:
case UpdateEngine.UpdateStatusConstants.FINALIZING: {
if (update.getStatus() != UpdateStatus.INSTALLING) {
update.setStatus(UpdateStatus.INSTALLING);
mUpdaterController.notifyUpdateChange(mDownloadId);
}
mProgress = Math.round(percent * 100);
mUpdaterController.getActualUpdate(mDownloadId).setInstallProgress(mProgress);
mFinalizing = status == UpdateEngine.UpdateStatusConstants.FINALIZING;
mUpdaterController.getActualUpdate(mDownloadId).setFinalizing(mFinalizing);
mUpdaterController.notifyInstallProgress(mDownloadId);
}
break;
case UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT: {
installationDone(true);
update.setInstallProgress(0);
update.setStatus(UpdateStatus.INSTALLED);
mUpdaterController.notifyUpdateChange(mDownloadId);
}
break;
case UpdateEngine.UpdateStatusConstants.IDLE: {
// The service was restarted because we thought we were installing an
// update, but we aren't, so clear everything.
installationDone(false);
}
break;
}
}
@Override
public void onPayloadApplicationComplete(int errorCode) {
if (errorCode != UpdateEngine.ErrorCodeConstants.SUCCESS) {
installationDone(false);
Update update = mUpdaterController.getActualUpdate(mDownloadId);
update.setInstallProgress(0);
update.setStatus(UpdateStatus.INSTALLATION_FAILED);
mUpdaterController.notifyUpdateChange(mDownloadId);
}
}
};
static synchronized boolean isInstallingUpdate(Context context) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
return pref.getString(ABUpdateInstaller.PREF_INSTALLING_AB_ID, null) != null ||
pref.getString(Constants.PREF_NEEDS_REBOOT_ID, null) != null;
}
static synchronized boolean isInstallingUpdate(Context context, String downloadId) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
return downloadId.equals(pref.getString(ABUpdateInstaller.PREF_INSTALLING_AB_ID, null)) ||
TextUtils.equals(pref.getString(Constants.PREF_NEEDS_REBOOT_ID, null), downloadId);
}
static synchronized boolean isInstallingUpdateSuspended(Context context) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
return pref.getString(ABUpdateInstaller.PREF_INSTALLING_SUSPENDED_AB_ID, null) != null;
}
static synchronized boolean isWaitingForReboot(Context context, String downloadId) {
String waitingId = PreferenceManager.getDefaultSharedPreferences(context)
.getString(Constants.PREF_NEEDS_REBOOT_ID, null);
return TextUtils.equals(waitingId, downloadId);
}
private ABUpdateInstaller(Context context, UpdaterController updaterController) {
mUpdaterController = updaterController;
mContext = context.getApplicationContext();
mUpdateEngine = new UpdateEngine();
}
static synchronized ABUpdateInstaller getInstance(Context context,
UpdaterController updaterController) {
if (sInstance == null) {
sInstance = new ABUpdateInstaller(context, updaterController);
}
return sInstance;
}
public void install(String downloadId) {
if (isInstallingUpdate(mContext)) {
Log.e(TAG, "Already installing an update");
return;
}
mDownloadId = downloadId;
File file = mUpdaterController.getActualUpdate(mDownloadId).getFile();
install(file, downloadId);
}
public void install(File file, String downloadId) {
if (!file.exists()) {
Log.e(TAG, "The given update doesn't exist");
mUpdaterController.getActualUpdate(downloadId)
.setStatus(UpdateStatus.INSTALLATION_FAILED);
mUpdaterController.notifyUpdateChange(downloadId);
return;
}
long offset;
String[] headerKeyValuePairs;
try {
ZipFile zipFile = new ZipFile(file);
offset = Utils.getZipEntryOffset(zipFile, Constants.AB_PAYLOAD_BIN_PATH);
ZipEntry payloadPropEntry = zipFile.getEntry(Constants.AB_PAYLOAD_PROPERTIES_PATH);
try (InputStream is = zipFile.getInputStream(payloadPropEntry);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr)) {
List<String> lines = new ArrayList<>();
for (String line; (line = br.readLine()) != null;) {
lines.add(line);
}
headerKeyValuePairs = new String[lines.size()];
headerKeyValuePairs = lines.toArray(headerKeyValuePairs);
}
zipFile.close();
} catch (IOException | IllegalArgumentException e) {
Log.e(TAG, "Could not prepare " + file, e);
mUpdaterController.getActualUpdate(mDownloadId)
.setStatus(UpdateStatus.INSTALLATION_FAILED);
mUpdaterController.notifyUpdateChange(mDownloadId);
return;
}
if (!mBound) {
mBound = mUpdateEngine.bind(mUpdateEngineCallback);
if (!mBound) {
Log.e(TAG, "Could not bind");
mUpdaterController.getActualUpdate(downloadId)
.setStatus(UpdateStatus.INSTALLATION_FAILED);
mUpdaterController.notifyUpdateChange(downloadId);
return;
}
}
boolean enableABPerfMode = PreferenceManager.getDefaultSharedPreferences(mContext)
.getBoolean(Constants.PREF_AB_PERF_MODE, false);
mUpdateEngine.setPerformanceMode(enableABPerfMode);
String zipFileUri = "file://" + file.getAbsolutePath();
try {
mUpdateEngine.applyPayload(zipFileUri, offset, 0, headerKeyValuePairs);
} catch (ServiceSpecificException e) {
if (e.errorCode == 66 /* kUpdateAlreadyInstalled */) {
installationDone(true);
mUpdaterController.getActualUpdate(mDownloadId).setStatus(UpdateStatus.INSTALLED);
mUpdaterController.notifyUpdateChange(mDownloadId);
return;
}
throw e;
}
mUpdaterController.getActualUpdate(mDownloadId).setStatus(UpdateStatus.INSTALLING);
mUpdaterController.notifyUpdateChange(mDownloadId);
PreferenceManager.getDefaultSharedPreferences(mContext).edit()
.putString(PREF_INSTALLING_AB_ID, mDownloadId)
.apply();
}
public void reconnect() {
if (!isInstallingUpdate(mContext)) {
Log.e(TAG, "reconnect: Not installing any update");
return;
}
if (mBound) {
return;
}
mDownloadId = PreferenceManager.getDefaultSharedPreferences(mContext)
.getString(PREF_INSTALLING_AB_ID, null);
// We will get a status notification as soon as we are connected
mBound = mUpdateEngine.bind(mUpdateEngineCallback);
if (!mBound) {
Log.e(TAG, "Could not bind");
}
}
private void installationDone(boolean needsReboot) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
String id = needsReboot ? mDownloadId : null;
PreferenceManager.getDefaultSharedPreferences(mContext).edit()
.putString(Constants.PREF_NEEDS_REBOOT_ID, id)
.remove(PREF_INSTALLING_AB_ID)
.apply();
}
public void cancel() {
if (!isInstallingUpdate(mContext)) {
Log.e(TAG, "cancel: Not installing any update");
return;
}
if (!mBound) {
Log.e(TAG, "Not connected to update engine");
return;
}
mUpdateEngine.cancel();
installationDone(false);
mUpdaterController.getActualUpdate(mDownloadId)
.setStatus(UpdateStatus.INSTALLATION_CANCELLED);
mUpdaterController.notifyUpdateChange(mDownloadId);
}
public void setPerformanceMode(boolean enable) {
mUpdateEngine.setPerformanceMode(enable);
}
public void suspend() {
if (!isInstallingUpdate(mContext)) {
Log.e(TAG, "cancel: Not installing any update");
return;
}
if (!mBound) {
Log.e(TAG, "Not connected to update engine");
return;
}
mUpdateEngine.suspend();
mUpdaterController.getActualUpdate(mDownloadId)
.setStatus(UpdateStatus.INSTALLATION_SUSPENDED);
mUpdaterController.notifyUpdateChange(mDownloadId);
PreferenceManager.getDefaultSharedPreferences(mContext).edit()
.putString(PREF_INSTALLING_SUSPENDED_AB_ID, mDownloadId)
.apply();
}
public void resume() {
if (!isInstallingUpdateSuspended(mContext)) {
Log.e(TAG, "cancel: No update is suspended");
return;
}
if (!mBound) {
Log.e(TAG, "Not connected to update engine");
return;
}
mUpdateEngine.resume();
mUpdaterController.getActualUpdate(mDownloadId).setStatus(UpdateStatus.INSTALLING);
mUpdaterController.notifyUpdateChange(mDownloadId);
mUpdaterController.getActualUpdate(mDownloadId).setInstallProgress(mProgress);
mUpdaterController.getActualUpdate(mDownloadId).setFinalizing(mFinalizing);
mUpdaterController.notifyInstallProgress(mDownloadId);
PreferenceManager.getDefaultSharedPreferences(mContext).edit()
.remove(PREF_INSTALLING_SUSPENDED_AB_ID)
.apply();
}
}

View File

@@ -0,0 +1,192 @@
/*
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.updater.controller;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;
import androidx.preference.PreferenceManager;
import org.lineageos.updater.misc.Constants;
import org.lineageos.updater.misc.FileUtils;
import org.lineageos.updater.misc.Utils;
import org.lineageos.updater.model.UpdateInfo;
import org.lineageos.updater.model.UpdateStatus;
import java.io.File;
import java.io.IOException;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.Files;
import java.util.HashSet;
import java.util.Set;
class UpdateInstaller {
private static final String TAG = "UpdateInstaller";
private static UpdateInstaller sInstance = null;
private static String sInstallingUpdate = null;
private Thread mPrepareUpdateThread;
private volatile boolean mCanCancel;
private final Context mContext;
private final UpdaterController mUpdaterController;
private UpdateInstaller(Context context, UpdaterController controller) {
mContext = context.getApplicationContext();
mUpdaterController = controller;
}
static synchronized UpdateInstaller getInstance(Context context,
UpdaterController updaterController) {
if (sInstance == null) {
sInstance = new UpdateInstaller(context, updaterController);
}
return sInstance;
}
static synchronized boolean isInstalling() {
return sInstallingUpdate != null;
}
static synchronized boolean isInstalling(String downloadId) {
return sInstallingUpdate != null && sInstallingUpdate.equals(downloadId);
}
void install(String downloadId) {
if (isInstalling()) {
Log.e(TAG, "Already installing an update");
return;
}
UpdateInfo update = mUpdaterController.getUpdate(downloadId);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
long buildTimestamp = SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0);
long lastBuildTimestamp = preferences.getLong(Constants.PREF_INSTALL_OLD_TIMESTAMP,
buildTimestamp);
boolean isReinstalling = buildTimestamp == lastBuildTimestamp;
preferences.edit()
.putLong(Constants.PREF_INSTALL_OLD_TIMESTAMP, buildTimestamp)
.putLong(Constants.PREF_INSTALL_NEW_TIMESTAMP, update.getTimestamp())
.putString(Constants.PREF_INSTALL_PACKAGE_PATH, update.getFile().getAbsolutePath())
.putBoolean(Constants.PREF_INSTALL_AGAIN, isReinstalling)
.putBoolean(Constants.PREF_INSTALL_NOTIFIED, false)
.apply();
if (Utils.isEncrypted(mContext, update.getFile())) {
// uncrypt rewrites the file so that it can be read without mounting
// the filesystem, so create a copy of it.
prepareForUncryptAndInstall(update);
} else {
installPackage(update.getFile(), downloadId);
}
}
private void installPackage(File update, String downloadId) {
try {
android.os.RecoverySystem.installPackage(mContext, update);
} catch (IOException e) {
Log.e(TAG, "Could not install update", e);
mUpdaterController.getActualUpdate(downloadId)
.setStatus(UpdateStatus.INSTALLATION_FAILED);
mUpdaterController.notifyUpdateChange(downloadId);
}
}
private synchronized void prepareForUncryptAndInstall(UpdateInfo update) {
String uncryptFilePath = update.getFile().getAbsolutePath() + Constants.UNCRYPT_FILE_EXT;
File uncryptFile = new File(uncryptFilePath);
Runnable copyUpdateRunnable = new Runnable() {
private long mLastUpdate = -1;
final FileUtils.ProgressCallBack mProgressCallBack = new FileUtils.ProgressCallBack() {
@Override
public void update(int progress) {
long now = SystemClock.elapsedRealtime();
if (mLastUpdate < 0 || now - mLastUpdate > 500) {
mUpdaterController.getActualUpdate(update.getDownloadId())
.setInstallProgress(progress);
mUpdaterController.notifyInstallProgress(update.getDownloadId());
mLastUpdate = now;
}
}
};
@Override
public void run() {
try {
mCanCancel = true;
FileUtils.copyFile(update.getFile(), uncryptFile, mProgressCallBack);
try {
Set<PosixFilePermission> perms = new HashSet<>();
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_WRITE);
perms.add(PosixFilePermission.OTHERS_READ);
perms.add(PosixFilePermission.GROUP_READ);
Files.setPosixFilePermissions(uncryptFile.toPath(), perms);
} catch (IOException exception) {}
mCanCancel = false;
if (mPrepareUpdateThread.isInterrupted()) {
mUpdaterController.getActualUpdate(update.getDownloadId())
.setStatus(UpdateStatus.INSTALLATION_CANCELLED);
mUpdaterController.getActualUpdate(update.getDownloadId())
.setInstallProgress(0);
//noinspection ResultOfMethodCallIgnored
uncryptFile.delete();
} else {
installPackage(uncryptFile, update.getDownloadId());
}
} catch (IOException e) {
Log.e(TAG, "Could not copy update", e);
//noinspection ResultOfMethodCallIgnored
uncryptFile.delete();
mUpdaterController.getActualUpdate(update.getDownloadId())
.setStatus(UpdateStatus.INSTALLATION_FAILED);
} finally {
synchronized (UpdateInstaller.this) {
mCanCancel = false;
mPrepareUpdateThread = null;
sInstallingUpdate = null;
}
mUpdaterController.notifyUpdateChange(update.getDownloadId());
}
}
};
mPrepareUpdateThread = new Thread(copyUpdateRunnable);
mPrepareUpdateThread.start();
sInstallingUpdate = update.getDownloadId();
mCanCancel = false;
mUpdaterController.getActualUpdate(update.getDownloadId())
.setStatus(UpdateStatus.INSTALLING);
mUpdaterController.notifyUpdateChange(update.getDownloadId());
}
public synchronized void cancel() {
if (!mCanCancel) {
Log.d(TAG, "Nothing to cancel");
return;
}
mPrepareUpdateThread.interrupt();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +15,16 @@
*/
package org.lineageos.updater.controller;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.PowerManager;
import android.os.SystemClock;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.lineageos.updater.UpdatesDbHelper;
import org.lineageos.updater.download.DownloadClient;
import org.lineageos.updater.misc.Utils;
@@ -39,7 +41,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
public class UpdaterController implements Controller {
public class UpdaterController {
public static final String ACTION_DOWNLOAD_PROGRESS = "action_download_progress";
public static final String ACTION_INSTALL_PROGRESS = "action_install_progress";
@@ -53,6 +55,7 @@ public class UpdaterController implements Controller {
private static final int MAX_REPORT_INTERVAL_MS = 1000;
private final Context mContext;
private final LocalBroadcastManager mBroadcastManager;
private final UpdatesDbHelper mUpdatesDbHelper;
@@ -61,13 +64,9 @@ public class UpdaterController implements Controller {
private final File mDownloadRoot;
private int mActiveDownloads = 0;
private Set<String> mVerifyingUpdates = new HashSet<>();
private final Set<String> mVerifyingUpdates = new HashSet<>();
public static synchronized UpdaterController getInstance() {
return sUpdaterController;
}
protected static synchronized UpdaterController getInstance(Context context) {
public static synchronized UpdaterController getInstance(Context context) {
if (sUpdaterController == null) {
sUpdaterController = new UpdaterController(context);
}
@@ -78,9 +77,10 @@ public class UpdaterController implements Controller {
mBroadcastManager = LocalBroadcastManager.getInstance(context);
mUpdatesDbHelper = new UpdatesDbHelper(context);
mDownloadRoot = Utils.getDownloadPath(context);
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Updater");
PowerManager powerManager = context.getSystemService(PowerManager.class);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Updater:wakelock");
mWakeLock.setReferenceCounted(false);
mContext = context.getApplicationContext();
Utils.cleanupDownloadsDir(context);
@@ -89,7 +89,7 @@ public class UpdaterController implements Controller {
}
}
private class DownloadEntry {
private static class DownloadEntry {
final Update mUpdate;
DownloadClient mDownloadClient;
private DownloadEntry(Update update) {
@@ -97,7 +97,7 @@ public class UpdaterController implements Controller {
}
}
private Map<String, DownloadEntry> mDownloads = new HashMap<>();
private final Map<String, DownloadEntry> mDownloads = new HashMap<>();
void notifyUpdateChange(String downloadId) {
Intent intent = new Intent();
@@ -153,56 +153,59 @@ public class UpdaterController implements Controller {
return new DownloadClient.DownloadCallback() {
@Override
public void onResponse(int statusCode, String url, DownloadClient.Headers headers) {
final Update update = mDownloads.get(downloadId).mUpdate;
if (update.getFileSize() <= 0) {
public void onResponse(DownloadClient.Headers headers) {
final DownloadEntry entry = mDownloads.get(downloadId);
if (entry == null) {
return;
}
final Update update = entry.mUpdate;
String contentLength = headers.get("Content-Length");
if (contentLength != null) {
try {
long size = Long.parseLong(contentLength);
if (size > 0) {
if (update.getFileSize() < size) {
update.setFileSize(size);
}
} catch (NumberFormatException e) {
Log.e(TAG, "Could not get content-length");
}
}
}
update.setStatus(UpdateStatus.DOWNLOADING);
update.setPersistentStatus(UpdateStatus.Persistent.INCOMPLETE);
new Thread(new Runnable() {
@Override
public void run() {
mUpdatesDbHelper.addUpdateWithOnConflict(update,
SQLiteDatabase.CONFLICT_REPLACE);
}
}).start();
new Thread(() -> mUpdatesDbHelper.addUpdateWithOnConflict(update,
SQLiteDatabase.CONFLICT_REPLACE)).start();
notifyUpdateChange(downloadId);
}
@Override
public void onSuccess(File destination) {
public void onSuccess() {
Log.d(TAG, "Download complete");
Update update = mDownloads.get(downloadId).mUpdate;
DownloadEntry entry = mDownloads.get(downloadId);
if (entry != null) {
Update update = entry.mUpdate;
update.setStatus(UpdateStatus.VERIFYING);
removeDownloadClient(mDownloads.get(downloadId));
removeDownloadClient(entry);
verifyUpdateAsync(downloadId);
notifyUpdateChange(downloadId);
tryReleaseWakelock();
}
}
@Override
public void onFailure(boolean cancelled) {
Update update = mDownloads.get(downloadId).mUpdate;
if (cancelled) {
Log.d(TAG, "Download cancelled");
// Already notified
} else {
DownloadEntry entry = mDownloads.get(downloadId);
if (entry != null) {
Update update = entry.mUpdate;
Log.e(TAG, "Download failed");
removeDownloadClient(mDownloads.get(downloadId));
removeDownloadClient(entry);
update.setStatus(UpdateStatus.PAUSED_ERROR);
notifyUpdateChange(downloadId);
}
}
tryReleaseWakelock();
}
};
@@ -214,9 +217,12 @@ public class UpdaterController implements Controller {
private int mProgress = 0;
@Override
public void update(long bytesRead, long contentLength, long speed, long eta,
boolean done) {
Update update = mDownloads.get(downloadId).mUpdate;
public void update(long bytesRead, long contentLength, long speed, long eta) {
DownloadEntry entry = mDownloads.get(downloadId);
if (entry == null) {
return;
}
Update update = entry.mUpdate;
if (contentLength <= 0) {
if (update.getFileSize() <= 0) {
return;
@@ -228,7 +234,7 @@ public class UpdaterController implements Controller {
return;
}
final long now = SystemClock.elapsedRealtime();
int progress = Math.round(bytesRead * 100 / contentLength);
int progress = Math.round(bytesRead * 100f / contentLength);
if (progress != mProgress || mLastUpdate - now > MAX_REPORT_INTERVAL_MS) {
mProgress = progress;
mLastUpdate = now;
@@ -241,14 +247,17 @@ public class UpdaterController implements Controller {
};
}
@SuppressLint("SetWorldReadable")
private void verifyUpdateAsync(final String downloadId) {
mVerifyingUpdates.add(downloadId);
new Thread(new Runnable() {
@Override
public void run() {
Update update = mDownloads.get(downloadId).mUpdate;
new Thread(() -> {
DownloadEntry entry = mDownloads.get(downloadId);
if (entry != null) {
Update update = entry.mUpdate;
File file = update.getFile();
if (file.exists() && verifyPackage(file)) {
//noinspection ResultOfMethodCallIgnored
file.setReadable(true, false);
update.setPersistentStatus(UpdateStatus.Persistent.VERIFIED);
mUpdatesDbHelper.changeUpdateStatus(update);
update.setStatus(UpdateStatus.VERIFIED);
@@ -272,6 +281,7 @@ public class UpdaterController implements Controller {
} catch (Exception e) {
Log.e(TAG, "Verification failed", e);
if (file.exists()) {
//noinspection ResultOfMethodCallIgnored
file.delete();
} else {
// The download was probably stopped. Exit silently
@@ -291,7 +301,7 @@ public class UpdaterController implements Controller {
} else if (update.getFileSize() > 0) {
update.setStatus(UpdateStatus.PAUSED);
int progress = Math.round(
update.getFile().length() * 100 / update.getFileSize());
update.getFile().length() * 100f / update.getFileSize());
update.setProgress(progress);
}
break;
@@ -299,17 +309,6 @@ public class UpdaterController implements Controller {
return true;
}
@Override
public void setUpdatesNotAvailableOnline(List<String> downloadIds) {
for (String downloadId : downloadIds) {
DownloadEntry update = mDownloads.get(downloadId);
if (update != null) {
update.mUpdate.setAvailableOnline(false);
}
}
}
@Override
public void setUpdatesAvailableOnline(List<String> downloadIds, boolean purgeList) {
List<String> toRemove = new ArrayList<>();
for (DownloadEntry entry : mDownloads.values()) {
@@ -327,18 +326,20 @@ public class UpdaterController implements Controller {
}
}
@Override
public boolean addUpdate(UpdateInfo update) {
return addUpdate(update, true);
}
private boolean addUpdate(final UpdateInfo updateInfo, boolean availableOnline) {
public boolean addUpdate(final UpdateInfo updateInfo, boolean availableOnline) {
Log.d(TAG, "Adding download: " + updateInfo.getDownloadId());
if (mDownloads.containsKey(updateInfo.getDownloadId())) {
Log.d(TAG, "Download (" + updateInfo.getDownloadId() + ") already added");
Update updateAdded = mDownloads.get(updateInfo.getDownloadId()).mUpdate;
DownloadEntry entry = mDownloads.get(updateInfo.getDownloadId());
if (entry != null) {
Update updateAdded = entry.mUpdate;
updateAdded.setAvailableOnline(availableOnline && updateAdded.getAvailableOnline());
updateAdded.setDownloadUrl(updateInfo.getDownloadUrl());
}
return false;
}
Update update = new Update(updateInfo);
@@ -353,13 +354,18 @@ public class UpdaterController implements Controller {
return true;
}
@Override
public boolean startDownload(String downloadId) {
@SuppressLint("WakelockTimeout")
public void startDownload(String downloadId) {
Log.d(TAG, "Starting " + downloadId);
if (!mDownloads.containsKey(downloadId) || isDownloading(downloadId)) {
return false;
return;
}
Update update = mDownloads.get(downloadId).mUpdate;
DownloadEntry entry = mDownloads.get(downloadId);
if (entry == null) {
Log.e(TAG, "Could not get download entry");
return;
}
Update update = entry.mUpdate;
File destination = new File(mDownloadRoot, update.getName());
if (destination.exists()) {
destination = Utils.appendSequentialNumber(destination);
@@ -373,34 +379,39 @@ public class UpdaterController implements Controller {
.setDestination(update.getFile())
.setDownloadCallback(getDownloadCallback(downloadId))
.setProgressListener(getProgressListener(downloadId))
.setUseDuplicateLinks(true)
.build();
} catch (IOException exception) {
Log.e(TAG, "Could not build download client");
update.setStatus(UpdateStatus.PAUSED_ERROR);
notifyUpdateChange(downloadId);
return false;
return;
}
addDownloadClient(mDownloads.get(downloadId), downloadClient);
addDownloadClient(entry, downloadClient);
update.setStatus(UpdateStatus.STARTING);
notifyUpdateChange(downloadId);
downloadClient.start();
mWakeLock.acquire();
return true;
}
@Override
public boolean resumeDownload(String downloadId) {
@SuppressLint("WakelockTimeout")
public void resumeDownload(String downloadId) {
Log.d(TAG, "Resuming " + downloadId);
if (!mDownloads.containsKey(downloadId) || isDownloading(downloadId)) {
return false;
return;
}
Update update = mDownloads.get(downloadId).mUpdate;
DownloadEntry entry = mDownloads.get(downloadId);
if (entry == null) {
Log.e(TAG, "Could not get download entry");
return;
}
Update update = entry.mUpdate;
File file = update.getFile();
if (file == null || !file.exists()) {
Log.e(TAG, "The destination file of " + downloadId + " doesn't exist, can't resume");
update.setStatus(UpdateStatus.PAUSED_ERROR);
notifyUpdateChange(downloadId);
return false;
return;
}
if (file.exists() && update.getFileSize() > 0 && file.length() >= update.getFileSize()) {
Log.d(TAG, "File already downloaded, starting verification");
@@ -415,81 +426,73 @@ public class UpdaterController implements Controller {
.setDestination(update.getFile())
.setDownloadCallback(getDownloadCallback(downloadId))
.setProgressListener(getProgressListener(downloadId))
.setUseDuplicateLinks(true)
.build();
} catch (IOException exception) {
Log.e(TAG, "Could not build download client");
update.setStatus(UpdateStatus.PAUSED_ERROR);
notifyUpdateChange(downloadId);
return false;
return;
}
addDownloadClient(mDownloads.get(downloadId), downloadClient);
addDownloadClient(entry, downloadClient);
update.setStatus(UpdateStatus.STARTING);
notifyUpdateChange(downloadId);
downloadClient.resume();
mWakeLock.acquire();
}
return true;
}
@Override
public boolean pauseDownload(String downloadId) {
public void pauseDownload(String downloadId) {
Log.d(TAG, "Pausing " + downloadId);
if (!isDownloading(downloadId)) {
return false;
return;
}
DownloadEntry entry = mDownloads.get(downloadId);
if (entry != null) {
entry.mDownloadClient.cancel();
removeDownloadClient(entry);
entry.mUpdate.setStatus(UpdateStatus.PAUSED);
entry.mUpdate.setEta(0);
entry.mUpdate.setSpeed(0);
notifyUpdateChange(downloadId);
return true;
}
}
private void deleteUpdateAsync(final Update update) {
new Thread(new Runnable() {
@Override
public void run() {
new Thread(() -> {
File file = update.getFile();
if (file.exists() && !file.delete()) {
Log.e(TAG, "Could not delete " + file.getAbsolutePath());
}
mUpdatesDbHelper.removeUpdate(update.getDownloadId());
}
}).start();
}
@Override
public boolean deleteUpdate(String downloadId) {
Log.d(TAG, "Cancelling " + downloadId);
public void deleteUpdate(String downloadId) {
Log.d(TAG, "Deleting update: " + downloadId);
if (!mDownloads.containsKey(downloadId) || isDownloading(downloadId)) {
return false;
return;
}
Update update = mDownloads.get(downloadId).mUpdate;
DownloadEntry entry = mDownloads.get(downloadId);
if (entry != null) {
Update update = entry.mUpdate;
update.setStatus(UpdateStatus.DELETED);
update.setProgress(0);
update.setPersistentStatus(UpdateStatus.Persistent.UNKNOWN);
deleteUpdateAsync(update);
if (!update.getAvailableOnline()) {
final boolean isLocalUpdate = Update.LOCAL_ID.equals(downloadId);
if (!isLocalUpdate && !update.getAvailableOnline()) {
Log.d(TAG, "Download no longer available online, removing");
mDownloads.remove(downloadId);
notifyUpdateDelete(downloadId);
} else {
notifyUpdateChange(downloadId);
}
return true;
}
}
@Override
public Set<String> getIds() {
return mDownloads.keySet();
}
@Override
public List<UpdateInfo> getUpdates() {
List<UpdateInfo> updates = new ArrayList<>();
for (DownloadEntry entry : mDownloads.values()) {
@@ -498,7 +501,6 @@ public class UpdaterController implements Controller {
return updates;
}
@Override
public UpdateInfo getUpdate(String downloadId) {
DownloadEntry entry = mDownloads.get(downloadId);
return entry != null ? entry.mUpdate : null;
@@ -509,34 +511,46 @@ public class UpdaterController implements Controller {
return entry != null ? entry.mUpdate : null;
}
@Override
public boolean isDownloading(String downloadId) {
//noinspection ConstantConditions
return mDownloads.containsKey(downloadId) &&
mDownloads.get(downloadId).mDownloadClient != null;
}
@Override
public boolean hasActiveDownloads() {
return mActiveDownloads > 0;
}
@Override
public boolean isVerifyingUpdate() {
return mVerifyingUpdates.size() > 0;
}
@Override
public boolean isVerifyingUpdate(String downloadId) {
return mVerifyingUpdates.contains(downloadId);
}
@Override
public boolean isInstallingUpdate() {
return ABUpdateInstaller.isInstallingUpdate();
return UpdateInstaller.isInstalling() ||
ABUpdateInstaller.isInstallingUpdate(mContext);
}
@Override
public boolean isInstallingUpdate(String downloadId) {
return ABUpdateInstaller.isInstallingUpdate(downloadId);
return UpdateInstaller.isInstalling(downloadId) ||
ABUpdateInstaller.isInstallingUpdate(mContext, downloadId);
}
public boolean isInstallingABUpdate() {
return ABUpdateInstaller.isInstallingUpdate(mContext);
}
public boolean isWaitingForReboot(String downloadId) {
return ABUpdateInstaller.isWaitingForReboot(mContext, downloadId);
}
public void setPerformanceMode(boolean enable) {
if (!Utils.isABDevice()) {
return;
}
ABUpdateInstaller.getInstance(mContext, this).setPerformanceMode(enable);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
*/
package org.lineageos.updater.controller;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
@@ -22,23 +23,26 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.NotificationCompat;
import android.support.v7.preference.PreferenceManager;
import android.text.format.Formatter;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager;
import org.lineageos.updater.R;
import org.lineageos.updater.UpdaterReceiver;
import org.lineageos.updater.UpdatesActivity;
import org.lineageos.updater.misc.BuildInfoUtils;
import org.lineageos.updater.misc.Constants;
import org.lineageos.updater.misc.FileUtils;
import org.lineageos.updater.misc.StringGenerator;
import org.lineageos.updater.misc.Utils;
import org.lineageos.updater.model.Update;
import org.lineageos.updater.model.UpdateInfo;
import org.lineageos.updater.model.UpdateStatus;
@@ -55,6 +59,13 @@ public class UpdaterService extends Service {
public static final String EXTRA_DOWNLOAD_ID = "extra_download_id";
public static final String EXTRA_DOWNLOAD_CONTROL = "extra_download_control";
public static final String ACTION_INSTALL_UPDATE = "action_install_update";
public static final String ACTION_INSTALL_STOP = "action_install_stop";
public static final String ACTION_INSTALL_SUSPEND = "action_install_suspend";
public static final String ACTION_INSTALL_RESUME = "action_install_resume";
private static final String ONGOING_NOTIFICATION_CHANNEL =
"ongoing_notification_channel";
public static final int DOWNLOAD_RESUME = 0;
public static final int DOWNLOAD_PAUSE = 1;
@@ -77,8 +88,14 @@ public class UpdaterService extends Service {
mUpdaterController = UpdaterController.getInstance(this);
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationBuilder = new NotificationCompat.Builder(this);
mNotificationManager = getSystemService(NotificationManager.class);
NotificationChannel notificationChannel = new NotificationChannel(
ONGOING_NOTIFICATION_CHANNEL,
getString(R.string.ongoing_channel_title),
NotificationManager.IMPORTANCE_LOW);
mNotificationManager.createNotificationChannel(notificationChannel);
mNotificationBuilder = new NotificationCompat.Builder(this,
ONGOING_NOTIFICATION_CHANNEL);
mNotificationBuilder.setSmallIcon(R.drawable.ic_system_update);
mNotificationBuilder.setShowWhen(false);
mNotificationStyle = new NotificationCompat.BigTextStyle();
@@ -86,7 +103,7 @@ public class UpdaterService extends Service {
Intent notificationIntent = new Intent(this, UpdatesActivity.class);
PendingIntent intent = PendingIntent.getActivity(this, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
mNotificationBuilder.setContentIntent(intent);
mBroadcastReceiver = new BroadcastReceiver() {
@@ -108,14 +125,18 @@ public class UpdaterService extends Service {
setNotificationTitle(update);
handleInstallProgress(update);
} else if (UpdaterController.ACTION_UPDATE_REMOVED.equals(intent.getAction())) {
final boolean isLocalUpdate = Update.LOCAL_ID.equals(downloadId);
Bundle extras = mNotificationBuilder.getExtras();
if (extras != null && downloadId.equals(
if (extras != null && !isLocalUpdate && downloadId.equals(
extras.getString(UpdaterController.EXTRA_DOWNLOAD_ID))) {
mNotificationBuilder.setExtras(null);
UpdateInfo update = mUpdaterController.getUpdate(downloadId);
if (update.getStatus() != UpdateStatus.INSTALLED) {
mNotificationManager.cancel(NOTIFICATION_ID);
}
}
}
}
};
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(UpdaterController.ACTION_DOWNLOAD_PROGRESS);
@@ -153,7 +174,16 @@ public class UpdaterService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_DOWNLOAD_CONTROL.equals(intent.getAction())) {
Log.d(TAG, "Starting service");
if (intent == null || intent.getAction() == null) {
if (ABUpdateInstaller.isInstallingUpdate(this)) {
// The service is being restarted.
ABUpdateInstaller installer = ABUpdateInstaller.getInstance(this,
mUpdaterController);
installer.reconnect();
}
} else if (ACTION_DOWNLOAD_CONTROL.equals(intent.getAction())) {
String downloadId = intent.getStringExtra(EXTRA_DOWNLOAD_ID);
int action = intent.getIntExtra(EXTRA_DOWNLOAD_CONTROL, -1);
if (action == DOWNLOAD_RESUME) {
@@ -171,51 +201,50 @@ public class UpdaterService extends Service {
}
try {
if (Utils.isABUpdate(update.getFile())) {
ABUpdateInstaller.start(this, mUpdaterController, downloadId);
ABUpdateInstaller installer = ABUpdateInstaller.getInstance(this,
mUpdaterController);
installer.install(downloadId);
} else {
boolean deleteUpdate = PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean(Constants.PREF_AUTO_UPDATES_CHECK, false);
if (deleteUpdate) {
// Renaming the file is enough to have it deleted automatically
File uncrytpFile = new File(
update.getFile().getAbsolutePath() + Constants.UNCRYPT_FILE_EXT);
update.getFile().renameTo(uncrytpFile);
installPackage(uncrytpFile);
} else if (Utils.isEncrypted(this, update.getFile())) {
// uncrypt rewrites the file so that it can be read without mounting
// the filesystem, so create a copy of it.
File uncrytpFile = new File(
update.getFile().getAbsolutePath() + Constants.UNCRYPT_FILE_EXT);
FileUtils.prepareForUncrypt(this, update.getFile(), uncrytpFile,
new Runnable() {
@Override
public void run() {
installPackage(uncrytpFile);
}
});
} else {
installPackage(update.getFile());
}
UpdateInstaller installer = UpdateInstaller.getInstance(this,
mUpdaterController);
installer.install(downloadId);
}
} catch (IOException e) {
Log.e(TAG, "Could not install update", e);
// TODO: user facing message
mUpdaterController.getActualUpdate(downloadId)
.setStatus(UpdateStatus.INSTALLATION_FAILED);
mUpdaterController.notifyUpdateChange(downloadId);
}
} else if (ACTION_INSTALL_STOP.equals(intent.getAction())) {
if (UpdateInstaller.isInstalling()) {
UpdateInstaller installer = UpdateInstaller.getInstance(this,
mUpdaterController);
installer.cancel();
} else if (ABUpdateInstaller.isInstallingUpdate(this)) {
ABUpdateInstaller installer = ABUpdateInstaller.getInstance(this,
mUpdaterController);
installer.reconnect();
installer.cancel();
}
} else if (ACTION_INSTALL_SUSPEND.equals(intent.getAction())) {
if (ABUpdateInstaller.isInstallingUpdate(this)) {
ABUpdateInstaller installer = ABUpdateInstaller.getInstance(this,
mUpdaterController);
installer.reconnect();
installer.suspend();
}
} else if (ACTION_INSTALL_RESUME.equals(intent.getAction())) {
if (ABUpdateInstaller.isInstallingUpdateSuspended(this)) {
ABUpdateInstaller installer = ABUpdateInstaller.getInstance(this,
mUpdaterController);
installer.reconnect();
installer.resume();
}
}
Log.d(TAG, "Service started");
return START_NOT_STICKY;
return ABUpdateInstaller.isInstallingUpdate(this) ? START_STICKY : START_NOT_STICKY;
}
private void installPackage(File update) {
try {
android.os.RecoverySystem.installPackage(this, update);
} catch (IOException e) {
// TODO: show error message
Log.e(TAG, "Could not install update", e);
}
}
public Controller getUpdaterController() {
public UpdaterController getUpdaterController() {
return mUpdaterController;
}
@@ -242,17 +271,22 @@ public class UpdaterService extends Service {
mNotificationStyle.setSummaryText(null);
String text = getString(R.string.download_starting_notification);
mNotificationStyle.bigText(text);
mNotificationBuilder.setStyle(mNotificationStyle);
mNotificationBuilder.setSmallIcon(android.R.drawable.stat_sys_download);
mNotificationBuilder.setTicker(text);
mNotificationBuilder.setOngoing(true);
mNotificationBuilder.setAutoCancel(false);
startForeground(NOTIFICATION_ID, mNotificationBuilder.build());
startForeground(NOTIFICATION_ID, mNotificationBuilder.build(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
break;
}
case DOWNLOADING: {
String text = getString(R.string.downloading_notification);
mNotificationStyle.bigText(text);
mNotificationBuilder.addAction(com.android.internal.R.drawable.ic_media_pause,
mNotificationBuilder.setStyle(mNotificationStyle);
mNotificationBuilder.setSmallIcon(android.R.drawable.stat_sys_download);
mNotificationBuilder.addAction(android.R.drawable.ic_media_pause,
getString(R.string.pause_button),
getPausePendingIntent(update.getDownloadId()));
mNotificationBuilder.setTicker(text);
@@ -268,13 +302,16 @@ public class UpdaterService extends Service {
mNotificationBuilder.mActions.clear();
String text = getString(R.string.download_paused_notification);
mNotificationStyle.bigText(text);
mNotificationBuilder.addAction(com.android.internal.R.drawable.ic_media_play,
mNotificationBuilder.setStyle(mNotificationStyle);
mNotificationBuilder.setSmallIcon(R.drawable.ic_pause);
mNotificationBuilder.addAction(android.R.drawable.ic_media_play,
getString(R.string.resume_button),
getResumePendingIntent(update.getDownloadId()));
mNotificationBuilder.setTicker(text);
mNotificationBuilder.setOngoing(false);
mNotificationBuilder.setAutoCancel(false);
mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
tryStopSelf();
break;
}
case PAUSED_ERROR: {
@@ -285,18 +322,23 @@ public class UpdaterService extends Service {
mNotificationBuilder.mActions.clear();
String text = getString(R.string.download_paused_error_notification);
mNotificationStyle.bigText(text);
mNotificationBuilder.addAction(com.android.internal.R.drawable.ic_media_play,
mNotificationBuilder.setStyle(mNotificationStyle);
mNotificationBuilder.setSmallIcon(android.R.drawable.stat_sys_warning);
mNotificationBuilder.addAction(android.R.drawable.ic_media_play,
getString(R.string.resume_button),
getResumePendingIntent(update.getDownloadId()));
mNotificationBuilder.setTicker(text);
mNotificationBuilder.setOngoing(false);
mNotificationBuilder.setAutoCancel(false);
mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
tryStopSelf();
break;
}
case VERIFYING: {
mNotificationBuilder.setProgress(0, 0, true);
mNotificationStyle.setSummaryText(null);
mNotificationBuilder.setStyle(mNotificationStyle);
mNotificationBuilder.setSmallIcon(R.drawable.ic_system_update);
mNotificationBuilder.mActions.clear();
String text = getString(R.string.verifying_download_notification);
mNotificationStyle.bigText(text);
@@ -306,9 +348,11 @@ public class UpdaterService extends Service {
}
case VERIFIED: {
stopForeground(STOP_FOREGROUND_DETACH);
mNotificationBuilder.setProgress(100, 100, false);
mNotificationBuilder.setStyle(null);
mNotificationBuilder.setSmallIcon(R.drawable.ic_system_update);
mNotificationBuilder.setProgress(0, 0, false);
String text = getString(R.string.download_completed_notification);
mNotificationStyle.bigText(text);
mNotificationBuilder.setContentText(text);
mNotificationBuilder.setTicker(text);
mNotificationBuilder.setOngoing(false);
mNotificationBuilder.setAutoCancel(true);
@@ -318,9 +362,11 @@ public class UpdaterService extends Service {
}
case VERIFICATION_FAILED: {
stopForeground(STOP_FOREGROUND_DETACH);
mNotificationBuilder.setStyle(null);
mNotificationBuilder.setSmallIcon(android.R.drawable.stat_sys_warning);
mNotificationBuilder.setProgress(0, 0, false);
String text = getString(R.string.verification_failed_notification);
mNotificationStyle.bigText(text);
mNotificationBuilder.setContentText(text);
mNotificationBuilder.setTicker(text);
mNotificationBuilder.setOngoing(false);
mNotificationBuilder.setAutoCancel(true);
@@ -330,22 +376,35 @@ public class UpdaterService extends Service {
}
case INSTALLING: {
mNotificationBuilder.mActions.clear();
mNotificationBuilder.setProgress(0, 0, true);
mNotificationBuilder.setStyle(mNotificationStyle);
mNotificationBuilder.setSmallIcon(R.drawable.ic_system_update);
mNotificationBuilder.setProgress(0, 0, false);
mNotificationStyle.setSummaryText(null);
String text = getString(R.string.installing_update);
String text = UpdateInstaller.isInstalling() ?
getString(R.string.dialog_prepare_zip_message) :
getString(R.string.installing_update);
mNotificationStyle.bigText(text);
if (ABUpdateInstaller.isInstallingUpdate(this)) {
mNotificationBuilder.addAction(android.R.drawable.ic_media_pause,
getString(R.string.suspend_button),
getSuspendInstallationPendingIntent());
}
mNotificationBuilder.setTicker(text);
mNotificationBuilder.setOngoing(true);
mNotificationBuilder.setAutoCancel(false);
startForeground(NOTIFICATION_ID, mNotificationBuilder.build());
startForeground(NOTIFICATION_ID, mNotificationBuilder.build(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
break;
}
case INSTALLED: {
stopForeground(STOP_FOREGROUND_DETACH);
mNotificationBuilder.setProgress(100, 100, false);
mNotificationBuilder.mActions.clear();
mNotificationBuilder.setStyle(null);
mNotificationBuilder.setSmallIcon(R.drawable.ic_system_update);
mNotificationBuilder.setProgress(0, 0, false);
String text = getString(R.string.installing_update_finished);
mNotificationStyle.bigText(text);
mNotificationBuilder.setContentText(text);
mNotificationBuilder.addAction(R.drawable.ic_system_update,
getString(R.string.reboot),
getRebootPendingIntent());
@@ -353,14 +412,25 @@ public class UpdaterService extends Service {
mNotificationBuilder.setOngoing(false);
mNotificationBuilder.setAutoCancel(true);
mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
boolean deleteUpdate = pref.getBoolean(Constants.PREF_AUTO_DELETE_UPDATES, false);
boolean isLocal = Update.LOCAL_ID.equals(update.getDownloadId());
// Always delete local updates
if (deleteUpdate || isLocal) {
mUpdaterController.deleteUpdate(update.getDownloadId());
}
tryStopSelf();
break;
}
case INSTALLATION_FAILED: {
stopForeground(STOP_FOREGROUND_DETACH);
mNotificationBuilder.setStyle(null);
mNotificationBuilder.setSmallIcon(android.R.drawable.stat_sys_warning);
mNotificationBuilder.setProgress(0, 0, false);
String text = getString(R.string.installing_update_error);
mNotificationStyle.bigText(text);
mNotificationBuilder.setContentText(text);
mNotificationBuilder.setTicker(text);
mNotificationBuilder.setOngoing(false);
mNotificationBuilder.setAutoCancel(true);
@@ -368,6 +438,30 @@ public class UpdaterService extends Service {
tryStopSelf();
break;
}
case INSTALLATION_CANCELLED: {
stopForeground(true);
tryStopSelf();
break;
}
case INSTALLATION_SUSPENDED: {
stopForeground(STOP_FOREGROUND_DETACH);
// In case we pause before the first progress update
mNotificationBuilder.setProgress(100, update.getProgress(), false);
mNotificationBuilder.mActions.clear();
String text = getString(R.string.installation_suspended_notification);
mNotificationStyle.bigText(text);
mNotificationBuilder.setStyle(mNotificationStyle);
mNotificationBuilder.setSmallIcon(R.drawable.ic_pause);
mNotificationBuilder.addAction(android.R.drawable.ic_media_play,
getString(R.string.resume_button),
getResumeInstallationPendingIntent());
mNotificationBuilder.setTicker(text);
mNotificationBuilder.setOngoing(true);
mNotificationBuilder.setAutoCancel(false);
mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
tryStopSelf();
break;
}
}
}
@@ -381,7 +475,7 @@ public class UpdaterService extends Service {
setNotificationTitle(update);
String speed = Formatter.formatFileSize(this, update.getSpeed());
CharSequence eta = StringGenerator.formatDuration(this, update.getEta() * 1000);
CharSequence eta = StringGenerator.formatETA(this, update.getEta() * 1000);
mNotificationStyle.bigText(
getString(R.string.text_download_speed, eta, speed));
@@ -389,20 +483,16 @@ public class UpdaterService extends Service {
}
private void handleInstallProgress(UpdateInfo update) {
setNotificationTitle(update);
int progress = update.getInstallProgress();
mNotificationBuilder.setProgress(100, progress, false);
setNotificationTitle(update);
if (progress == 0) {
mNotificationStyle.bigText(getString(R.string.finalizing_package));
mNotificationBuilder.setProgress(0, 0, true);
} else {
String percent = NumberFormat.getPercentInstance().format(progress / 100.f);
mNotificationStyle.setSummaryText(percent);
mNotificationStyle.bigText(getString(R.string.preparing_ota_first_boot));
}
boolean notAB = UpdateInstaller.isInstalling();
mNotificationStyle.bigText(notAB ? getString(R.string.dialog_prepare_zip_message) :
update.getFinalizing() ?
getString(R.string.finalizing_package) :
getString(R.string.preparing_ota_first_boot));
mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
}
@@ -410,7 +500,7 @@ public class UpdaterService extends Service {
String buildDate = StringGenerator.getDateLocalizedUTC(this,
DateFormat.MEDIUM, update.getTimestamp());
String buildInfo = getString(R.string.list_build_version_date,
BuildInfoUtils.getBuildVersion(), buildDate);
update.getVersion(), buildDate);
mNotificationStyle.setBigContentTitle(buildInfo);
mNotificationBuilder.setContentTitle(buildInfo);
}
@@ -421,7 +511,7 @@ public class UpdaterService extends Service {
intent.putExtra(EXTRA_DOWNLOAD_ID, downloadId);
intent.putExtra(EXTRA_DOWNLOAD_CONTROL, DOWNLOAD_RESUME);
return PendingIntent.getService(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
private PendingIntent getPausePendingIntent(String downloadId) {
@@ -430,14 +520,27 @@ public class UpdaterService extends Service {
intent.putExtra(EXTRA_DOWNLOAD_ID, downloadId);
intent.putExtra(EXTRA_DOWNLOAD_CONTROL, DOWNLOAD_PAUSE);
return PendingIntent.getService(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
private PendingIntent getRebootPendingIntent() {
final Intent intent = new Intent(this, UpdaterReceiver.class);
intent.setAction(UpdaterReceiver.ACTION_INSTALL_REBOOT);
return PendingIntent.getBroadcast(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
private PendingIntent getSuspendInstallationPendingIntent() {
final Intent intent = new Intent(this, UpdaterService.class);
intent.setAction(ACTION_INSTALL_SUSPEND);
return PendingIntent.getService(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
private PendingIntent getResumeInstallationPendingIntent() {
final Intent intent = new Intent(this, UpdaterService.class);
intent.setAction(ACTION_INSTALL_RESUME);
return PendingIntent.getService(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,27 +17,23 @@ package org.lineageos.updater.download;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public interface DownloadClient {
interface DownloadCallback {
void onResponse(int statusCode, String url, Headers headers);
void onResponse(Headers headers);
void onSuccess(File destination);
void onSuccess();
void onFailure(boolean cancelled);
}
interface ProgressListener {
void update(long bytesRead, long contentLength, long speed, long eta, boolean done);
void update(long bytesRead, long contentLength, long speed, long eta);
}
interface Headers {
String get(String name);
Map<String, List<String>> getAll();
}
/**
@@ -63,6 +59,7 @@ public interface DownloadClient {
private File mDestination;
private DownloadClient.DownloadCallback mCallback;
private DownloadClient.ProgressListener mProgressListener;
private boolean mUseDuplicateLinks;
public DownloadClient build() throws IOException {
if (mUrl == null) {
@@ -72,7 +69,8 @@ public interface DownloadClient {
} else if (mCallback == null) {
throw new IllegalStateException("No download callback defined");
}
return new HttpURLConnectionClient(mUrl, mDestination, mProgressListener, mCallback);
return new HttpURLConnectionClient(mUrl, mDestination, mProgressListener, mCallback,
mUseDuplicateLinks);
}
public Builder setUrl(String url) {
@@ -94,5 +92,10 @@ public interface DownloadClient {
mProgressListener = progressListener;
return this;
}
public Builder setUseDuplicateLinks(boolean useDuplicateLinks) {
mUseDuplicateLinks = useDuplicateLinks;
return this;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,18 +25,23 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class HttpURLConnectionClient implements DownloadClient {
private final static String TAG = "HttpURLConnectionClient";
private final HttpURLConnection mClient;
private HttpURLConnection mClient;
private final File mDestination;
private final DownloadClient.ProgressListener mProgressListener;
private final DownloadClient.DownloadCallback mCallback;
private final boolean mUseDuplicateLinks;
private DownloadThread mDownloadThread;
@@ -46,19 +51,17 @@ public class HttpURLConnectionClient implements DownloadClient {
return mClient.getHeaderField(name);
}
@Override
public Map<String, List<String>> getAll() {
return mClient.getHeaderFields();
}
}
HttpURLConnectionClient(String url, File destination,
DownloadClient.ProgressListener progressListener,
DownloadClient.DownloadCallback callback) throws IOException {
DownloadClient.DownloadCallback callback,
boolean useDuplicateLinks) throws IOException {
mClient = (HttpURLConnection) new URL(url).openConnection();
mDestination = destination;
mProgressListener = progressListener;
mCallback = callback;
mUseDuplicateLinks = useDuplicateLinks;
}
@Override
@@ -113,6 +116,10 @@ public class HttpURLConnectionClient implements DownloadClient {
return (statusCode / 100) == 2;
}
private static boolean isRedirectCode(int statusCode) {
return (statusCode / 100) == 3;
}
private static boolean isPartialContentCode(int statusCode) {
return statusCode == 206;
}
@@ -133,8 +140,20 @@ public class HttpURLConnectionClient implements DownloadClient {
mResume = resume;
}
private void calculateSpeed() {
private void calculateSpeed(boolean justResumed) {
final long millis = SystemClock.elapsedRealtime();
if (justResumed) {
// If we don't start over with these after resumption, we get huge numbers for
// ETA since the delta will grow, resulting in a very low speed
mLastMillis = millis;
mSpeed = -1; // we don't want the moving avg with values from who knows when
// need to do this as well, otherwise the second time we call calculateSpeed(),
// the difference (mTotalBytesRead - mCurSampleBytes) will be larger than expected,
// resulting in a higher speed calculation
mCurSampleBytes = mTotalBytesRead;
return;
}
final long delta = millis - mLastMillis;
if (delta > 500) {
final long curSpeed = ((mTotalBytesRead - mCurSampleBytes) * 1000) / delta;
@@ -155,14 +174,102 @@ public class HttpURLConnectionClient implements DownloadClient {
}
}
private void changeClientUrl(URL newUrl) throws IOException {
String range = mClient.getRequestProperty("Range");
mClient.disconnect();
mClient = (HttpURLConnection) newUrl.openConnection();
if (range != null) {
mClient.setRequestProperty("Range", range);
}
}
private void handleDuplicateLinks() throws IOException {
String protocol = mClient.getURL().getProtocol();
class DuplicateLink {
private final String mUrl;
private final int mPriority;
private DuplicateLink(String url, int priority) {
mUrl = url;
mPriority = priority;
}
}
PriorityQueue<DuplicateLink> duplicates = null;
for (Map.Entry<String, List<String>> entry : mClient.getHeaderFields().entrySet()) {
if ("Link".equalsIgnoreCase((entry.getKey()))) {
duplicates = new PriorityQueue<>(entry.getValue().size(),
Comparator.comparingInt(d -> d.mPriority));
// https://tools.ietf.org/html/rfc6249
// https://tools.ietf.org/html/rfc5988#section-5
String regex = "(?i)<(.+)>\\s*;\\s*rel=duplicate(?:.*pri=([0-9]+).*|.*)?";
Pattern pattern = Pattern.compile(regex);
for (String field : entry.getValue()) {
Matcher matcher = pattern.matcher(field);
if (matcher.matches()) {
String url = matcher.group(1);
String pri = matcher.group(2);
int priority = pri != null ? Integer.parseInt(pri) : 999999;
duplicates.add(new DuplicateLink(url, priority));
Log.d(TAG, "Adding duplicate link " + url);
} else {
Log.d(TAG, "Ignoring link " + field);
}
}
}
}
String newUrl = mClient.getHeaderField("Location");
for (;;) {
try {
URL url = new URL(newUrl);
if (!url.getProtocol().equals(protocol)) {
// If we hadn't handled duplicate links, we wouldn't have
// used this url.
throw new IOException("Protocol changes are not allowed");
}
Log.d(TAG, "Downloading from " + newUrl);
changeClientUrl(url);
mClient.setConnectTimeout(5000);
mClient.connect();
if (!isSuccessCode(mClient.getResponseCode())) {
throw new IOException("Server replied with " + mClient.getResponseCode());
}
return;
} catch (IOException e) {
if (duplicates != null && !duplicates.isEmpty()) {
DuplicateLink link = duplicates.poll();
if (link != null) {
duplicates.remove(link);
newUrl = link.mUrl;
Log.e(TAG, "Using duplicate link " + link.mUrl, e);
}
} else {
throw e;
}
}
}
}
@Override
public void run() {
boolean justResumed = false;
try {
mClient.setInstanceFollowRedirects(!mUseDuplicateLinks);
mClient.connect();
int responseCode = mClient.getResponseCode();
mCallback.onResponse(responseCode, mClient.getURL().toString(), new Headers());
if (mUseDuplicateLinks && isRedirectCode(responseCode)) {
handleDuplicateLinks();
responseCode = mClient.getResponseCode();
}
mCallback.onResponse(new Headers());
if (mResume && isPartialContentCode(responseCode)) {
justResumed = true;
mTotalBytesRead = mDestination.length();
Log.d(TAG, "The server fulfilled the partial content request");
} else if (mResume || !isSuccessCode(responseCode)) {
@@ -175,21 +282,21 @@ public class HttpURLConnectionClient implements DownloadClient {
InputStream inputStream = mClient.getInputStream();
OutputStream outputStream = new FileOutputStream(mDestination, mResume)
) {
mTotalBytes = mClient.getContentLength() + mTotalBytesRead;
mTotalBytes = mClient.getContentLengthLong() + mTotalBytesRead;
byte[] b = new byte[8192];
int count;
while (!isInterrupted() && (count = inputStream.read(b)) > 0) {
outputStream.write(b, 0, count);
mTotalBytesRead += count;
calculateSpeed();
calculateSpeed(justResumed);
calculateEta();
justResumed = false; // otherwise we will never get speed and ETA again
if (mProgressListener != null) {
mProgressListener.update(mTotalBytesRead, mTotalBytes, mSpeed, mEta,
false);
mProgressListener.update(mTotalBytesRead, mTotalBytes, mSpeed, mEta);
}
}
if (mProgressListener != null) {
mProgressListener.update(mTotalBytesRead, mTotalBytes, mSpeed, mEta, true);
mProgressListener.update(mTotalBytesRead, mTotalBytes, mSpeed, mEta);
}
outputStream.flush();
@@ -197,7 +304,7 @@ public class HttpURLConnectionClient implements DownloadClient {
if (isInterrupted()) {
mCallback.onFailure(true);
} else {
mCallback.onSuccess(mDestination);
mCallback.onSuccess();
}
}
} catch (IOException e) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2017-2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,19 +23,39 @@ public final class Constants {
public static final String AB_PAYLOAD_BIN_PATH = "payload.bin";
public static final String AB_PAYLOAD_PROPERTIES_PATH = "payload_properties.txt";
public static final int AUTO_UPDATES_CHECK_INTERVAL_NEVER = 0;
public static final int AUTO_UPDATES_CHECK_INTERVAL_DAILY = 1;
public static final int AUTO_UPDATES_CHECK_INTERVAL_WEEKLY = 2;
public static final int AUTO_UPDATES_CHECK_INTERVAL_MONTHLY = 3;
public static final String PREF_LAST_UPDATE_CHECK = "last_update_check";
public static final String PREF_AUTO_UPDATES_CHECK = "auto_updates_check";
public static final String PREF_AUTO_UPDATES_CHECK_INTERVAL = "auto_updates_check_interval";
public static final String PREF_AUTO_DELETE_UPDATES = "auto_delete_updates";
public static final String PREF_AB_PERF_MODE = "ab_perf_mode";
public static final String PREF_METERED_NETWORK_WARNING = "pref_metered_network_warning";
public static final String PREF_MOBILE_DATA_WARNING = "pref_mobile_data_warning";
public static final String PREF_NEEDS_REBOOT_ID = "needs_reboot_id";
public static final String UNCRYPT_FILE_EXT = ".uncrypt";
public static final String PROP_AB_DEVICE = "ro.build.ab_update";
public static final String PROP_BUILD_DATE = "ro.build.date.utc";
public static final String PROP_BUILD_VERSION = "ro.lineage.build.version";
public static final String PROP_BUILD_VERSION_INCREMENTAL = "ro.build.version.incremental";
public static final String PROP_DEVICE = "ro.lineage.device";
public static final String PROP_NEXT_DEVICE = "ro.updater.next_device";
public static final String PROP_RELEASE_TYPE = "ro.lineage.releasetype";
public static final String PROP_UPDATER_ALLOW_DOWNGRADING = "lineage.updater.allow_downgrading";
public static final String PROP_UPDATER_URI = "lineage.updater.uri";
public static final String PREF_INSTALL_OLD_TIMESTAMP = "install_old_timestamp";
public static final String PREF_INSTALL_NEW_TIMESTAMP = "install_new_timestamp";
public static final String PREF_INSTALL_PACKAGE_PATH = "install_package_path";
public static final String PREF_INSTALL_AGAIN = "install_again";
public static final String PREF_INSTALL_NOTIFIED = "install_notified";
public static final String UPDATE_RECOVERY_EXEC = "/vendor/bin/install-recovery.sh";
public static final String UPDATE_RECOVERY_PROPERTY = "persist.vendor.recovery_update";
public static final String HAS_SEEN_INFO_DIALOG = "has_seen_info_dialog";
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.updater.misc;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns;
import android.util.Log;
import androidx.annotation.NonNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
public class FileUtils {
private static final String TAG = "FileUtils";
public interface ProgressCallBack {
void update(int progress);
}
private static class CallbackByteChannel implements ReadableByteChannel {
private final ProgressCallBack mCallback;
private final long mSize;
private final ReadableByteChannel mReadableByteChannel;
private long mSizeRead;
private int mProgress;
private CallbackByteChannel(ReadableByteChannel readableByteChannel, long expectedSize,
ProgressCallBack callback) {
this.mCallback = callback;
this.mSize = expectedSize;
this.mReadableByteChannel = readableByteChannel;
}
@Override
public void close() throws IOException {
mReadableByteChannel.close();
}
@Override
public boolean isOpen() {
return mReadableByteChannel.isOpen();
}
@Override
public int read(ByteBuffer bb) throws IOException {
int read;
if ((read = mReadableByteChannel.read(bb)) > 0) {
mSizeRead += read;
int progress = mSize > 0 ? Math.round(mSizeRead * 100.f / mSize) : -1;
if (mProgress != progress) {
mCallback.update(progress);
mProgress = progress;
}
}
return read;
}
}
public static void copyFile(File sourceFile, File destFile, ProgressCallBack progressCallBack)
throws IOException {
try (FileChannel sourceChannel = new FileInputStream(sourceFile).getChannel();
FileChannel destChannel = new FileOutputStream(destFile).getChannel()) {
if (progressCallBack != null) {
ReadableByteChannel readableByteChannel = new CallbackByteChannel(sourceChannel,
sourceFile.length(), progressCallBack);
destChannel.transferFrom(readableByteChannel, 0, sourceChannel.size());
} else {
destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
}
} catch (IOException e) {
Log.e(TAG, "Could not copy file", e);
if (destFile.exists()) {
//noinspection ResultOfMethodCallIgnored
destFile.delete();
}
throw e;
}
}
public static void copyFile(ContentResolver cr, File sourceFile, Uri destUri,
ProgressCallBack progressCallBack) throws IOException {
try (FileChannel sourceChannel = new FileInputStream(sourceFile).getChannel();
ParcelFileDescriptor pfd = cr.openFileDescriptor(destUri, "w");
FileChannel destChannel = new FileOutputStream(pfd.getFileDescriptor()).getChannel()) {
if (progressCallBack != null) {
ReadableByteChannel readableByteChannel = new CallbackByteChannel(sourceChannel,
sourceFile.length(), progressCallBack);
destChannel.transferFrom(readableByteChannel, 0, sourceChannel.size());
} else {
destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
}
} catch (IOException e) {
Log.e(TAG, "Could not copy file", e);
throw e;
}
}
public static String queryName(@NonNull ContentResolver resolver, Uri uri) {
try (Cursor returnCursor = resolver.query(uri, null, null, null, null)) {
returnCursor.moveToFirst();
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
return returnCursor.getString(nameIndex);
} catch (Exception e) {
// ignore
return null;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2017-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,13 +36,6 @@ public final class StringGenerator {
return f.format(date);
}
public static String getTimeLocalizedUTC(Context context, long unixTimestamp) {
DateFormat f = DateFormat.getTimeInstance(DateFormat.SHORT, getCurrentLocale(context));
f.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = new Date(unixTimestamp * 1000);
return f.format(date);
}
public static String getDateLocalized(Context context, int dateFormat, long unixTimestamp) {
DateFormat f = DateFormat.getDateInstance(dateFormat, getCurrentLocale(context));
Date date = new Date(unixTimestamp * 1000);
@@ -56,31 +49,20 @@ public final class StringGenerator {
return f.format(date);
}
public static String getDateTimeLocalized(Context context, long unixTimestamp) {
DateFormat f = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT,
getCurrentLocale(context));
Date date = new Date(unixTimestamp * 1000);
return f.format(date);
}
public static String bytesToMegabytes(Context context, long bytes) {
return String.format(getCurrentLocale(context), "%.0f", bytes / 1024.f / 1024.f);
}
public static String formatDuration(Context context, long millis) {
public static String formatETA(Context context, long millis) {
final long SECOND_IN_MILLIS = 1000;
final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
Resources res = context.getResources();
if (millis >= HOUR_IN_MILLIS) {
final int hours = (int) ((millis + 1800000) / HOUR_IN_MILLIS);
return res.getQuantityString(R.plurals.duration_hours, hours, hours);
return res.getQuantityString(R.plurals.eta_hours, hours, hours);
} else if (millis >= MINUTE_IN_MILLIS) {
final int minutes = (int) ((millis + 30000) / MINUTE_IN_MILLIS);
return res.getQuantityString(R.plurals.duration_minutes, minutes, minutes);
return res.getQuantityString(R.plurals.eta_minutes, minutes, minutes);
} else {
final int seconds = (int) ((millis + 500) / SECOND_IN_MILLIS);
return res.getQuantityString(R.plurals.duration_seconds, seconds, seconds);
return res.getQuantityString(R.plurals.eta_seconds, seconds, seconds);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2017-2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
*/
package org.lineageos.updater.misc;
import android.app.AlarmManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@@ -22,28 +23,28 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.os.SystemProperties;
import android.os.storage.StorageManager;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import androidx.preference.PreferenceManager;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.lineageos.updater.R;
import org.lineageos.updater.UpdatesDbHelper;
import org.lineageos.updater.controller.UpdaterService;
import org.lineageos.updater.model.UpdateBaseInfo;
import org.lineageos.updater.model.Update;
import org.lineageos.updater.model.UpdateBaseInfo;
import org.lineageos.updater.model.UpdateInfo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
@@ -66,7 +67,7 @@ public class Utils {
}
public static File getExportPath(Context context) {
File dir = new File(Environment.getExternalStorageDirectory(),
File dir = new File(context.getExternalFilesDir(null),
context.getString(R.string.export_path));
if (!dir.isDirectory()) {
if (dir.exists() || !dir.mkdirs()) {
@@ -88,14 +89,20 @@ public class Utils {
update.setName(object.getString("filename"));
update.setDownloadId(object.getString("id"));
update.setType(object.getString("romtype"));
update.setFileSize(object.getLong("size"));
update.setDownloadUrl(object.getString("url"));
update.setVersion(object.getString("version"));
return update;
}
public static boolean isCompatible(UpdateBaseInfo update) {
if (update.getTimestamp() < SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0)) {
Log.d(TAG, update.getName() + " is older than current build");
if (update.getVersion().compareTo(SystemProperties.get(Constants.PROP_BUILD_VERSION)) < 0) {
Log.d(TAG, update.getName() + " is older than current Android version");
return false;
}
if (!SystemProperties.getBoolean(Constants.PROP_UPDATER_ALLOW_DOWNGRADING, false) &&
update.getTimestamp() <= SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0)) {
Log.d(TAG, update.getName() + " is older than/equal to the current build");
return false;
}
if (!update.getType().equalsIgnoreCase(SystemProperties.get(Constants.PROP_RELEASE_TYPE))) {
@@ -106,7 +113,8 @@ public class Utils {
}
public static boolean canInstall(UpdateBaseInfo update) {
return update.getTimestamp() >= SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0) &&
return (SystemProperties.getBoolean(Constants.PROP_UPDATER_ALLOW_DOWNGRADING, false) ||
update.getTimestamp() > SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0)) &&
update.getVersion().equalsIgnoreCase(
SystemProperties.get(Constants.PROP_BUILD_VERSION));
}
@@ -115,14 +123,14 @@ public class Utils {
throws IOException, JSONException {
List<UpdateInfo> updates = new ArrayList<>();
String json = "";
StringBuilder json = new StringBuilder();
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
for (String line; (line = br.readLine()) != null;) {
json += line;
json.append(line);
}
}
JSONObject obj = new JSONObject(json);
JSONObject obj = new JSONObject(json.toString());
JSONArray updatesList = obj.getJSONArray("response");
for (int i = 0; i < updatesList.length(); i++) {
if (updatesList.isNull(i)) {
@@ -136,7 +144,7 @@ public class Utils {
Log.d(TAG, "Ignoring incompatible update " + update.getName());
}
} catch (JSONException e) {
Log.e(TAG, "Could not parse update object, index=" + i);
Log.e(TAG, "Could not parse update object, index=" + i, e);
}
}
@@ -144,15 +152,31 @@ public class Utils {
}
public static String getServerURL(Context context) {
String serverUrl = SystemProperties.get(Constants.PROP_UPDATER_URI);
if (serverUrl.trim().isEmpty()) {
serverUrl = context.getString(R.string.conf_update_server_url_def);
}
String incrementalVersion = SystemProperties.get(Constants.PROP_BUILD_VERSION_INCREMENTAL);
String device = SystemProperties.get(Constants.PROP_NEXT_DEVICE,
SystemProperties.get(Constants.PROP_DEVICE));
String type = SystemProperties.get(Constants.PROP_RELEASE_TYPE).toLowerCase(Locale.ROOT);
return serverUrl + "/v1/" + device + "/" + type + "/" + incrementalVersion;
String serverUrl = SystemProperties.get(Constants.PROP_UPDATER_URI);
if (serverUrl.trim().isEmpty()) {
serverUrl = context.getString(R.string.updater_server_url);
}
return serverUrl.replace("{device}", device)
.replace("{type}", type)
.replace("{incr}", incrementalVersion);
}
public static String getUpgradeBlockedURL(Context context) {
String device = SystemProperties.get(Constants.PROP_NEXT_DEVICE,
SystemProperties.get(Constants.PROP_DEVICE));
return context.getString(R.string.blocked_update_info_url, device);
}
public static String getChangelogURL(Context context) {
String device = SystemProperties.get(Constants.PROP_NEXT_DEVICE,
SystemProperties.get(Constants.PROP_DEVICE));
return context.getString(R.string.menu_changelog_url, device);
}
public static void triggerUpdate(Context context, String downloadId) {
@@ -163,18 +187,24 @@ public class Utils {
}
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
return !(info == null || !info.isConnected() || !info.isAvailable());
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
Network activeNetwork = cm.getActiveNetwork();
NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(activeNetwork);
if (networkCapabilities != null &&
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
|| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
|| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_USB)
|| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
|| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
}
return false;
}
public static boolean isOnWifiOrEthernet(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
return (info != null && (info.getType() == ConnectivityManager.TYPE_ETHERNET
|| info.getType() == ConnectivityManager.TYPE_WIFI));
public static boolean isNetworkMetered(Context context) {
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
return cm.isActiveNetworkMetered();
}
/**
@@ -183,8 +213,6 @@ public class Utils {
* @param oldJson old update list
* @param newJson new update list
* @return true if newJson has at least a compatible update not available in oldJson
* @throws IOException
* @throws JSONException
*/
public static boolean checkForNewUpdates(File oldJson, File newJson)
throws IOException, JSONException {
@@ -235,16 +263,13 @@ public class Utils {
}
public static void removeUncryptFiles(File downloadPath) {
File[] uncryptFiles = downloadPath.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(Constants.UNCRYPT_FILE_EXT);
}
});
File[] uncryptFiles = downloadPath.listFiles(
(dir, name) -> name.endsWith(Constants.UNCRYPT_FILE_EXT));
if (uncryptFiles == null) {
return;
}
for (File file : uncryptFiles) {
//noinspection ResultOfMethodCallIgnored
file.delete();
}
}
@@ -254,15 +279,30 @@ public class Utils {
* the user can't access and that might have stale files. This can happen if
* the data of the application are wiped.
*
* @param context
*/
public static void cleanupDownloadsDir(Context context) {
File downloadPath = getDownloadPath(context);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
removeUncryptFiles(downloadPath);
long buildTimestamp = SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0);
long prevTimestamp = preferences.getLong(Constants.PREF_INSTALL_OLD_TIMESTAMP, 0);
String lastUpdatePath = preferences.getString(Constants.PREF_INSTALL_PACKAGE_PATH, null);
boolean reinstalling = preferences.getBoolean(Constants.PREF_INSTALL_AGAIN, false);
boolean deleteUpdates = preferences.getBoolean(Constants.PREF_AUTO_DELETE_UPDATES, false);
if ((buildTimestamp != prevTimestamp || reinstalling) && deleteUpdates &&
lastUpdatePath != null) {
File lastUpdate = new File(lastUpdatePath);
if (lastUpdate.exists()) {
//noinspection ResultOfMethodCallIgnored
lastUpdate.delete();
// Remove the pref not to delete the file if re-downloaded
preferences.edit().remove(Constants.PREF_INSTALL_PACKAGE_PATH).apply();
}
}
final String DOWNLOADS_CLEANUP_DONE = "cleanup_done";
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (preferences.getBoolean(DOWNLOADS_CLEANUP_DONE, false)) {
return;
}
@@ -285,6 +325,7 @@ public class Utils {
for (File file : files) {
if (!knownPaths.contains(file.getAbsolutePath())) {
Log.d(TAG, "Deleting " + file.getAbsolutePath());
//noinspection ResultOfMethodCallIgnored
file.delete();
}
}
@@ -313,6 +354,10 @@ public class Utils {
throw new IllegalStateException();
}
public static boolean isABDevice() {
return SystemProperties.getBoolean(Constants.PROP_AB_DEVICE, false);
}
public static boolean isABUpdate(ZipFile zipFile) {
return zipFile.getEntry(Constants.AB_PAYLOAD_BIN_PATH) != null &&
zipFile.getEntry(Constants.AB_PAYLOAD_PROPERTIES_PATH) != null;
@@ -329,7 +374,8 @@ public class Utils {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
}
public static void addToClipboard(Context context, String label, String text, String toastMessage) {
public static void addToClipboard(Context context, String label, String text,
String toastMessage) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(
Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(label, text);
@@ -341,4 +387,41 @@ public class Utils {
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
return sm.isEncrypted(file);
}
public static int getUpdateCheckSetting(Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getInt(Constants.PREF_AUTO_UPDATES_CHECK_INTERVAL,
Constants.AUTO_UPDATES_CHECK_INTERVAL_WEEKLY);
}
public static boolean isUpdateCheckEnabled(Context context) {
return getUpdateCheckSetting(context) != Constants.AUTO_UPDATES_CHECK_INTERVAL_NEVER;
}
public static long getUpdateCheckInterval(Context context) {
switch (Utils.getUpdateCheckSetting(context)) {
case Constants.AUTO_UPDATES_CHECK_INTERVAL_DAILY:
return AlarmManager.INTERVAL_DAY;
case Constants.AUTO_UPDATES_CHECK_INTERVAL_WEEKLY:
default:
return AlarmManager.INTERVAL_DAY * 7;
case Constants.AUTO_UPDATES_CHECK_INTERVAL_MONTHLY:
return AlarmManager.INTERVAL_DAY * 30;
}
}
public static boolean isRecoveryUpdateExecPresent() {
return new File(Constants.UPDATE_RECOVERY_EXEC).exists();
}
public static String getDisplayVersion(String version) {
float floatVersion = 0;
try {
floatVersion = Float.parseFloat(version);
} catch (NumberFormatException ignored) {
// ignore
}
// Lineage 20 and up should only be integer values (we don't have minor versions anymore)
return (floatVersion >= 20) ? String.valueOf((int)floatVersion) : version;
}
}

View File

@@ -18,35 +18,32 @@ package org.lineageos.updater.model;
import java.io.File;
public class Update extends UpdateBase implements UpdateInfo {
public static final String LOCAL_ID = "local";
private UpdateStatus mStatus = UpdateStatus.UNKNOWN;
private int mPersistentStatus = UpdateStatus.Persistent.UNKNOWN;
private File mFile;
private long mFileSize;
private int mProgress;
private long mEta;
private long mSpeed;
private int mInstallProgress;
private boolean mAvailableOnline;
private boolean mIsFinalizing;
public Update() {
}
public Update(UpdateBaseInfo update) {
super(update);
}
public Update(UpdateInfo update) {
super(update);
mStatus = update.getStatus();
mPersistentStatus = update.getPersistentStatus();
mFile = update.getFile();
mFileSize = update.getFileSize();
mProgress = update.getProgress();
mEta = update.getEta();
mSpeed = update.getSpeed();
mInstallProgress = update.getInstallProgress();
mAvailableOnline = update.getAvailableOnline();
mIsFinalizing = update.getFinalizing();
}
@Override
@@ -76,15 +73,6 @@ public class Update extends UpdateBase implements UpdateInfo {
mFile = file;
}
@Override
public long getFileSize() {
return mFileSize;
}
public void setFileSize(long fileSize) {
mFileSize = fileSize;
}
@Override
public int getProgress() {
return mProgress;
@@ -129,4 +117,13 @@ public class Update extends UpdateBase implements UpdateInfo {
public void setAvailableOnline(boolean availableOnline) {
mAvailableOnline = availableOnline;
}
@Override
public boolean getFinalizing() {
return mIsFinalizing;
}
public void setFinalizing(boolean finalizing) {
mIsFinalizing = finalizing;
}
}

View File

@@ -23,6 +23,7 @@ public class UpdateBase implements UpdateBaseInfo {
private long mTimestamp;
private String mType;
private String mVersion;
private long mFileSize;
public UpdateBase() {
}
@@ -34,6 +35,7 @@ public class UpdateBase implements UpdateBaseInfo {
mTimestamp = update.getTimestamp();
mType = update.getType();
mVersion = update.getVersion();
mFileSize = update.getFileSize();
}
@Override
@@ -89,4 +91,13 @@ public class UpdateBase implements UpdateBaseInfo {
public void setDownloadUrl(String downloadUrl) {
mDownloadUrl = downloadUrl;
}
@Override
public long getFileSize() {
return mFileSize;
}
public void setFileSize(long fileSize) {
mFileSize = fileSize;
}
}

View File

@@ -27,4 +27,6 @@ public interface UpdateBaseInfo {
String getVersion();
String getDownloadUrl();
long getFileSize();
}

View File

@@ -35,4 +35,6 @@ public interface UpdateInfo extends UpdateBaseInfo {
int getInstallProgress();
boolean getAvailableOnline();
boolean getFinalizing();
}

View File

@@ -19,7 +19,6 @@ public enum UpdateStatus {
UNKNOWN,
STARTING,
DOWNLOADING,
DOWNLOADED,
PAUSED,
PAUSED_ERROR,
DELETED,
@@ -28,7 +27,9 @@ public enum UpdateStatus {
VERIFICATION_FAILED,
INSTALLING,
INSTALLED,
INSTALLATION_FAILED;
INSTALLATION_FAILED,
INSTALLATION_CANCELLED,
INSTALLATION_SUSPENDED;
public static final class Persistent {
public static final int UNKNOWN = 0;

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2022 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:pathData="M0,0h108v108h-108z"
android:fillColor="#167C80"/>
<path
android:pathData="M58,58C58,60.209 56.209,62 54,62C51.791,62 50,60.209 50,58C50,58 51.791,58 54,58C56.209,58 58,58 58,58Z"
android:fillColor="#85BABC"/>
<path
android:pathData="M62,46C62,50.418 58.418,54 54,54C49.582,54 46,50.418 46,46C46,46 49.582,46 54,46C58.418,46 62,46 62,46Z"
android:fillColor="#CAE1E2"/>
<path
android:pathData="M54,30m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0"
android:fillColor="#ffffff"/>
</vector>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2022 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group>
<clip-path
android:pathData="M0,0h108v108h-108z"/>
<path
android:pathData="M108,0H0V108H108V0ZM42,30C39.791,30 38,31.791 38,34V74C38,76.209 39.791,78 42,78H66C68.209,78 70,76.209 70,74V34C70,31.791 68.209,30 66,30H42Z"
android:fillColor="#2A3232"
android:fillType="evenOdd"/>
<path
android:pathData="M28.54,28.54m-72,0a72,72 0,1 1,144 0a72,72 0,1 1,-144 0"
android:fillAlpha="0.6">
<aapt:attr name="android:fillColor">
<gradient
android:gradientRadius="72"
android:centerX="28.54"
android:centerY="28.54"
android:type="radial">
<item android:offset="0" android:color="#19FFFFFF"/>
<item android:offset="1" android:color="#00FFFFFF"/>
</gradient>
</aapt:attr>
</path>
</group>
</vector>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/inverted"
android:pathData="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" />
</vector>

View File

@@ -6,6 +6,6 @@
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:fillColor="@color/inverted"
android:pathData="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
</vector>

View File

@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z" />

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M7,1C5.8954,1 5,1.8954 5,3V21C5,22.1046 5.8954,23 7,23H17C18.1046,23 19,22.1046 19,21V3C19,1.8954 18.1046,1 17,1H16H8H7ZM8,1L12,1L16,1C16,3.2091 14.2091,5 12,5C9.7909,5 8,3.2091 8,1ZM12,10C13.6569,10 15,8.6568 15,7L12,7L9,7C9,8.6568 10.3431,10 12,10ZM14,12C14,13.1046 13.1046,14 12,14C10.8954,14 10,13.1046 10,12L12,12L14,12Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

View File

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:padding="16dp"
android:weightSum="2"
android:baselineAligned="false">
<RelativeLayout
android:id="@+id/header_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:layout_gravity="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/header_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:paddingBottom="16dp"
android:textColor="?android:attr/textColorPrimary"
android:textSize="56sp"
tools:text="LineageOS\n20" />
<TextView
android:id="@+id/header_build_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp"
tools:text="Android 13"/>
<TextView
android:id="@+id/header_build_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp"
tools:text="1970-01-01"/>
<TextView
android:id="@+id/header_last_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp"
tools:text="Last checked: 1970-01-01"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:weightSum="2"
android:orientation="horizontal">
<Button
android:id="@+id/refresh"
android:drawableStart="@drawable/ic_menu_refresh"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/menu_refresh"
style="@style/Widget.AppCompat.Button.Borderless.Colored"/>
<Button
android:id="@+id/preferences"
android:drawableStart="@drawable/ic_menu_preferences"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/menu_preferences"
style="@style/Widget.AppCompat.Button.Borderless.Colored"/>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:layout_gravity="end">
<androidx.core.widget.NestedScrollView
android:id="@+id/no_new_updates_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="46dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/list_no_updates"
android:textColor="?android:textColorSecondary" />
</androidx.core.widget.NestedScrollView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="12dp"
android:clipToPadding="false"
android:paddingBottom="5dp"
android:scrollbars="vertical"
android:layout_gravity="end"
tools:listitem="@layout/update_item_view"/>
<ProgressBar
android:id="@+id/refresh_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="gone"/>
</RelativeLayout>
</LinearLayout>

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
android:nextFocusRight="@+id/update_action"
android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:cardBackgroundColor="@color/tv_card_background"
app:cardCornerRadius="16dp"
app:contentPadding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1"
android:baselineAligned="false">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/build_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.87"
android:drawablePadding="8dp"
android:maxLines="1"
android:paddingBottom="8sp"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
tools:text="LineageOS 15.1" />
<TextView
android:id="@+id/build_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textSize="14sp"
tools:text="29 February 2018" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/progress"
android:visibility="invisible"
tools:visibility="visible">
<ProgressBar
android:id="@+id/progress_bar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:paddingTop="4sp"
tools:progress="65" />
<TextView
android:id="@+id/progress_percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="8dp"
android:paddingEnd="8dp"
tools:text="65%" />
</LinearLayout>
<TextView
android:id="@+id/progress_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/progress"
android:ellipsize="marquee"
android:singleLine="true"
android:visibility="invisible"
tools:text="162 of 1.1GB (3 minutes left)"
tools:visibility="visible" />
<TextView
android:id="@+id/build_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="8sp"
android:singleLine="true"
tools:text="300 MB"
tools:visibility="invisible" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageButton
android:id="@+id/update_menu"
style="?android:attr/actionOverflowButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:padding="8dp"
android:contentDescription="@null" />
<Button
android:id="@id/update_action"
style="@style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
tools:text="Pause" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -1,30 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:layout_behavior="org.lineageos.updater.ui.FlingBehavior">
android:outlineAmbientShadowColor="@android:color/transparent"
android:outlineSpotShadowColor="@android:color/transparent"
android:background="?android:attr/colorPrimary"
android:theme="@style/Theme.CollapsingToolbar.Settings">
<android.support.design.widget.CollapsingToolbarLayout
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/AppTheme.AppBarOverlay"
app:collapsedTitleTextAppearance="@style/TextAppearanceWhite"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleTextAppearance="@style/TextAppearanceTransparent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
android:layout_height="wrap_content"
android:clipToPadding="false"
app:forceApplySystemWindowInsetTop="true"
app:extraMultilineHeightEnabled="true"
app:contentScrim="@color/toolbar_collapsed"
app:maxLines="3"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:scrimAnimationDuration="50"
app:scrimVisibleHeightTrigger="@dimen/settingslib_scrim_visible_height_trigger"
app:statusBarScrim="@null"
app:titleCollapseMode="fade"
app:collapsedTitleTextAppearance="@style/CollapsingToolbarTitle.Collapsed"
app:expandedTitleTextAppearance="@style/CollapsingToolbarTitle.Expanded"
app:expandedTitleMarginStart="@dimen/expanded_title_margin_start"
app:expandedTitleMarginEnd="@dimen/expanded_title_margin_end"
app:toolbarId="@id/action_bar">
<RelativeLayout
android:id="@+id/header_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="86dp"
@@ -39,44 +54,50 @@
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:paddingBottom="16dp"
android:textColor="@color/white"
android:textSize="56sp" />
<TextView
android:id="@+id/header_build_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/header_title"
android:textColor="@color/white"
android:textSize="12sp" />
android:textColor="?android:attr/textColorPrimary"
android:textSize="56sp"
tools:text="LineageOS\n20"/>
<TextView
android:id="@+id/header_build_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/header_build_date"
android:textColor="@color/white"
android:textSize="12sp" />
android:layout_below="@id/header_title"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp"
tools:text="Android 13"/>
<TextView
android:id="@+id/header_build_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/header_build_version"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp"
tools:text="1970-01-01"/>
<TextView
android:id="@+id/header_last_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/header_build_version"
android:textColor="@color/white"
android:textSize="12sp" />
android:layout_below="@id/header_build_date"
android:layout_marginTop="8dp"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp"
tools:text="Last checked: 1970-01-01"/>
</RelativeLayout>
<android.support.v7.widget.Toolbar
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:titleTextColor="@color/white"
android:theme="?android:attr/actionBarTheme"
android:transitionName="shared_element_view"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<android.support.v4.widget.NestedScrollView
<androidx.core.widget.NestedScrollView
android:id="@+id/no_new_updates_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -89,14 +110,15 @@
android:gravity="center"
android:text="@string/list_no_updates"
android:textColor="?android:textColorSecondary" />
</android.support.v4.widget.NestedScrollView>
</androidx.core.widget.NestedScrollView>
<android.support.v7.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="5dp"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:listitem="@layout/update_item_view" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingEnd="24dp"
android:paddingStart="24dp"
android:paddingTop="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/menu_auto_updates_check"
android:textColor="@color/inverted"
android:textSize="16sp" />
<Spinner
android:id="@+id/preferences_auto_updates_check_interval"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:entries="@array/menu_auto_updates_check_interval_entries" />
</LinearLayout>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/preferences_auto_delete_updates"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/menu_auto_delete_updates"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/preferences_metered_network_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/menu_metered_network_warning"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/preferences_ab_perf_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/menu_ab_perf_mode"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/preferences_update_recovery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/menu_update_recovery"
android:textSize="16sp" />
</LinearLayout>

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
android:nextFocusRight="@+id/update_action"
android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:cardCornerRadius="16dp"
app:contentPadding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1"
android:baselineAligned="false">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/build_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.87"
android:drawablePadding="8dp"
android:maxLines="1"
android:paddingBottom="8sp"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
tools:text="LineageOS 20" />
<TextView
android:id="@+id/build_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textSize="14sp"
tools:text="18 June 2023" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/progress"
android:visibility="invisible"
tools:visibility="visible">
<ProgressBar
android:id="@+id/progress_bar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:paddingTop="4sp"
tools:progress="65" />
<TextView
android:id="@+id/progress_percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="8dp"
android:paddingEnd="8dp"
tools:text="65%" />
</LinearLayout>
<TextView
android:id="@+id/progress_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/progress"
android:ellipsize="marquee"
android:singleLine="true"
android:visibility="invisible"
tools:text="162 of 1.1 GB (3 minutes left)"
tools:visibility="visible" />
<TextView
android:id="@+id/build_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="8sp"
android:singleLine="true"
tools:text="1.1 GB"
tools:visibility="invisible" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageButton
android:id="@+id/update_menu"
style="?android:attr/actionOverflowButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:padding="8dp"
android:contentDescription="@null" />
<Button
android:id="@id/update_action"
style="@style/Widget.AppCompat.Button.Borderless.Colored"
android:background="?android:selectableItemBackgroundBorderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
tools:text="Pause" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_export_update"
android:title="@string/menu_export_update" />
<item
android:id="@+id/menu_delete_action"
android:title="@string/menu_delete_update" />
<item
android:id="@+id/menu_copy_url"
android:title="@string/menu_copy_url" />
</menu>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_refresh"
android:icon="@drawable/ic_menu_refresh"
android:title="@string/menu_refresh"
app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_local_update"
android:title="@string/local_update_import"
app:showAsAction="never" />
<item
android:id="@+id/menu_preferences"
android:title="@string/menu_preferences"
app:showAsAction="never" />
<item
android:id="@+id/menu_show_changelog"
android:title="@string/menu_show_changelog"
app:showAsAction="never" />
</menu>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2022 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">المُحدث</string>
<string name="display_name">المُحدث</string>
<string name="verification_failed_notification">فشل التحقق</string>
<string name="verifying_download_notification">التحقق من التحديث</string>
<string name="downloading_notification">جارٍ التنزيل</string>
<string name="download_paused_notification">توقف التنزيل مؤقتاً</string>
<string name="download_paused_error_notification">خطأ في التنزيل</string>
<string name="download_completed_notification">اكتمل التنزيل</string>
<string name="download_starting_notification">بدء التنزيل</string>
<string name="update_failed_notification">فشل التحديث</string>
<string name="installation_suspended_notification">تم تعليق التثبيت</string>
<string name="new_updates_found_title">تحديثات جديدة</string>
<string name="text_download_speed">%1$s، %2$s/ثانية</string>
<string name="pause_button">إيقاف مؤقت</string>
<string name="resume_button">استئناف</string>
<string name="suspend_button">تعليق</string>
<string name="installing_update">جارٍ تثبيت حزمة التحديث</string>
<string name="installing_update_error">خطأ في التثبيت</string>
<string name="installing_update_finished">تم تثبيت التحديث</string>
<string name="finalizing_package">جارٍ إنهاء تثبيت الحزمة</string>
<string name="preparing_ota_first_boot">جارٍ الإعداد للتشغيل الأول</string>
<string name="dialog_prepare_zip_message">التجهيز للتحديث الأولي</string>
<string name="dialog_battery_low_title">البطارية منخفضة</string>
<string name="dialog_battery_low_message_pct">مستوى شحن البطارية منخفض للغاية؛ وتحتاج على الأقل <xliff:g id="percent_discharging">%1$d</xliff:g>%% من البطارية للمتابعة، <xliff:g id="percent_charging">%2$d</xliff:g>%% في حالة الشحن.</string>
<string name="reboot">إعادة التشغيل</string>
<string name="menu_refresh">تحديث</string>
<string name="menu_preferences">التفضيلات</string>
<string name="menu_auto_updates_check">التحقق من التحديثات التلقائية</string>
<string name="menu_auto_updates_check_interval_daily">مرة في اليوم</string>
<string name="menu_auto_updates_check_interval_weekly">مرة في الأسبوع</string>
<string name="menu_auto_updates_check_interval_monthly">مرة في الشهر</string>
<string name="menu_auto_updates_check_interval_never">مطلقًا</string>
<string name="menu_auto_delete_updates">حذف التحديثات بعد التثبيت</string>
<string name="menu_delete_update">حذف</string>
<string name="menu_copy_url">نسخ الرابط</string>
<string name="menu_export_update">تصدير التحديث</string>
<string name="menu_show_changelog">إظهار التغييرات</string>
<string name="menu_ab_perf_mode">إعطاء الأولوية لعملية التحديث</string>
<string name="menu_update_recovery">تحديث وضع الاسترداد</string>
<string name="toast_forced_update_recovery">من المستحيل تعطيل تحديثات Lineage Recovery على هذا الجهاز</string>
<string name="snack_updates_found">تم العثور على تحديثات جديدة</string>
<string name="snack_no_updates_found">لا توجد تحديثات جديدة</string>
<string name="snack_updates_check_failed">فشل التحقق من وجود تحديث. برجاء التحقق من اتصالك بالإنترنت وإعادة المحاولة لاحقًا.</string>
<string name="snack_download_failed">فشل التنزيل. برجاء التحقق من اتصالك بالإنترنت وإعادة المحاولة لاحقًا.</string>
<string name="snack_download_verification_failed">فشل التحقق من التحديث.</string>
<string name="snack_download_verified">اكتمل التنزيل.</string>
<string name="snack_update_not_installable">لا يمكن تثبيت هذا التحديث على الاصدار الحالي.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">أندرويد <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">آخر تحقق: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> من <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> من <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">جارٍ التحقق من التحديث</string>
<string name="list_no_updates">لا توجد تحديثات جديدة. للبحث عن تحديثات جديدة يدويًا، استخدم الزر تحديث.</string>
<string name="action_download">تنزيل</string>
<string name="action_pause">إيقاف مؤقت</string>
<string name="action_resume">استئناف</string>
<string name="action_install">تثبيت</string>
<string name="action_info">معلومات</string>
<string name="action_delete">حذف</string>
<string name="action_cancel">إلغاء</string>
<string name="confirm_delete_dialog_title">حذف الملف</string>
<string name="confirm_delete_dialog_message">حذف ملف التحديث المحدد؟</string>
<string name="apply_update_dialog_title">تطبيق التحديث</string>
<string name="apply_update_dialog_message">أنت على وشك تثبيت <xliff:g id="update_name">%1$s</xliff:g>.\n\nإذا قمت بالضغط على <xliff:g id="ok">%2$s</xliff:g>، سيعاد تشغيل الجهاز بنفسه في وضع الاستعادة لتثبيت التحديث.\n\nملاحظة: هذه الميزة تتطلب مسترد متوافق أو سيلزم تثبيت التحديثات يدويًا.</string>
<string name="apply_update_dialog_message_ab">أنت على وشك تثبيت <xliff:g id="update_name">%1$s</xliff:g>.\n\nعند الضغط على <xliff:g id="ok">%2$s</xliff:g>، وسوف يبدأ الجهاز بالتثبيت في الخلفية.\n\nعندما ينتهي، ستُطالب بإعادة التشغيل.</string>
<string name="cancel_installation_dialog_message">إلغاء التثبيت؟</string>
<string name="label_download_url">عنوان التنزيل</string>
<string name="toast_download_url_copied">تم نسخ الرابط</string>
<string name="dialog_export_title">تصدير التحديث</string>
<string name="notification_export_success">تم تصدير التحديث</string>
<string name="notification_export_fail">خطأ في التصدير</string>
<string name="toast_already_exporting">جاري تصدير تحديث بالفعل</string>
<string name="toast_export_started">بدأ التصدير</string>
<plurals name="eta_seconds">
<item quantity="zero"><xliff:g id="count">%d</xliff:g> ثانية متبقية</item>
<item quantity="one"><xliff:g id="count">%d</xliff:g> ثانية متبقية</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> ثانية متبقية</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> ثانية متبقية</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> ثانية متبقية</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> ثانية متبقية</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="zero"><xliff:g id="count">%d</xliff:g> دقائق متبقية</item>
<item quantity="one"><xliff:g id="count">%d</xliff:g> دقيقة متبقية</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> دقيقة متبقية</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> دقيقة متبقية</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> دقيقة متبقية</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> دقيقة متبقية</item>
</plurals>
<plurals name="eta_hours">
<item quantity="zero"><xliff:g id="count">%d</xliff:g> ساعات متبقية</item>
<item quantity="one"><xliff:g id="count">%d</xliff:g> ساعات متبقية</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> ساعات متبقية</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> ساعات متبقية</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> ساعات متبقية</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> ساعات متبقية</item>
</plurals>
<string name="update_over_metered_network_title">تنبيه</string>
<string name="update_over_metered_network_message">أنت على وشك تنزيل حُزْمَة التحديث عبر شبكة مقيدة التي من المحتمل أن تسبب استخداما عاليا للبيانات. هل ترغب في المتابعة؟</string>
<string name="checkbox_metered_network_warning">لا تظهر هذا مجدداً</string>
<string name="menu_metered_network_warning">تحذير شبكة مقننة</string>
<string name="blocked_update_dialog_title">التحديث محظور</string>
<string name="blocked_update_dialog_message">لا يمكن تثبيت التحديث باستخدام تطبيق المُحدث. برجاء قراءة <xliff:g id="info_url">%1$s </xliff:g> للحصول على مزيد من المعلومات.</string>
<string name="export_channel_title">اكتمال التصدير</string>
<string name="new_updates_channel_title">تحديثات جديدة</string>
<string name="ongoing_channel_title">التنزيلات الحالية</string>
<string name="update_failed_channel_title">فشل التحديث</string>
<string name="info_dialog_title">هل كنت تعلم؟ </string>
<string name="info_dialog_message">تحديثات LineageOS هي حزم تثبيت كاملة. وهذا يعني أنه يمكنك دائماً تثبيت أحدث إصدار فقط، حتى إذا كنت قد تخطيت بعض الإصدارات السابقة!</string>
<string name="info_dialog_ok">شكرًا على المعلومة!</string>
</resources>

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<!--
Copyright (C) 2017 The LineageOS Project
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,8 +15,6 @@
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Directory where the update files will be downloaded and stored.
WARNING: The application can and will delete any unknown file. -->
<!-- Directory where the downloads will be exported to.
The path is relative to the root of the external storage.-->
<string name="menu_update_recovery">পুনৰুদ্ধাৰ আপডেট কৰক</string>
<string name="toast_forced_update_recovery">এই ডিভাইচত Lineage পুনৰুদ্ধাৰ আপডেটসমূহ নিষ্ক্ৰিয় কৰাটো অসম্ভৱ।</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Anovador</string>
<string name="display_name">Anovador</string>
<string name="verification_failed_notification">La verificación falló</string>
<string name="verifying_download_notification">Verificando l\'anovamientu</string>
<string name="downloading_notification">En descarga</string>
<string name="download_paused_notification">La descarga ta en posa</string>
<string name="download_paused_error_notification">Error de la descarga</string>
<string name="download_completed_notification">Completóse la descarga</string>
<string name="download_starting_notification">Aniciando la descarga</string>
<string name="update_failed_notification">L\'anovamientu falló</string>
<string name="installation_suspended_notification">Suspendióse la instalación</string>
<string name="new_updates_found_title">Hai anovamientos</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Posar</string>
<string name="resume_button">Siguir</string>
<string name="suspend_button">Suspender</string>
<string name="installing_update">Instalando\'l paquete d\'anovamientu</string>
<string name="installing_update_error">Error de la instalación</string>
<string name="installing_update_finished">Instalóse l\'anovamientu</string>
<string name="finalizing_package">Finando la instalación del paquete</string>
<string name="preparing_ota_first_boot">Tresnando\'l primer arrinque</string>
<string name="dialog_prepare_zip_message">Tresnáu preliminar del anovamientu</string>
<string name="dialog_battery_low_title">Queda poca batería</string>
<string name="dialog_battery_low_message_pct">El nivel de batería ye perbaxu, tien d\'haber polo menos un <xliff:g id="percent_discharging">%1$d</xliff:g>%% de batería pa siguir, <xliff:g id="percent_charging">%2$d</xliff:g>%% si ta en carga.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Executa los comandos siguientes y volvi probar l\'anovamientu:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Nun se pue instalar l\'anovamientu con OverlayFS montáu</string>
<string name="reboot">Reaniciar</string>
<string name="menu_refresh">Anovar</string>
<string name="menu_preferences">Preferencies</string>
<string name="menu_auto_updates_check">Busca d\'anovamientos</string>
<string name="menu_auto_updates_check_interval_daily">Diaria</string>
<string name="menu_auto_updates_check_interval_weekly">Selmanal</string>
<string name="menu_auto_updates_check_interval_monthly">Mensual</string>
<string name="menu_auto_updates_check_interval_never">Enxamás</string>
<string name="menu_auto_delete_updates">Desaniciar los anovamientos al instalalos</string>
<string name="menu_delete_update">Desaniciar</string>
<string name="menu_copy_url">Copiar la URL</string>
<string name="menu_export_update">Esportar l\'anovamientu</string>
<string name="menu_show_changelog">Amosar el rexistru de cambeos</string>
<string name="menu_ab_perf_mode">Priorizar el procesu d\'anovamientu</string>
<string name="menu_update_recovery">Anovar el recovery</string>
<string name="toast_forced_update_recovery">Ye imposible desactivar los anovamientos del recovery de Lineage nesti preséu.</string>
<string name="snack_updates_found">Atopáronse anovamientos</string>
<string name="snack_no_updates_found">Nun s\'atopó nengún anovamientu</string>
<string name="snack_updates_check_failed">La comprobación d\'anovamientos falló. Comprueba la conexón a internet y volvi tentalo.</string>
<string name="snack_download_failed">La descarga falló. Comprueba la conexón a internet y volvi tentalo.</string>
<string name="snack_download_verification_failed">La comprobación d\'anovamientos falló</string>
<string name="snack_download_verified">Completóse la descarga.</string>
<string name="snack_update_not_installable">Esti anovamientu nun se pue instalar sobre la versión actual.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Última comprobación: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verificando l\'anovamientu</string>
<string name="list_no_updates">Nun s\'atopó nengún anovamientu. Pa comprobar manualmente si los hai, usa\'l botón «Anovar».</string>
<string name="action_download">Baxar</string>
<string name="action_pause">Posar</string>
<string name="action_resume">Siguir</string>
<string name="action_install">Instalar</string>
<string name="action_info">Información</string>
<string name="action_delete">Desaniciar</string>
<string name="action_cancel">Encaboxar</string>
<string name="confirm_delete_dialog_title">Desaniciu d\'un ficheru</string>
<string name="confirm_delete_dialog_message">¿Quies desaniciar l\'anovamientu seleicionáu?</string>
<string name="apply_update_dialog_title">Instalación d\'un anovamientu</string>
<string name="apply_update_dialog_message">Tas a piques d\'instalar «<xliff:g id="update_name">%1$s</xliff:g>».\n\nSi primes «<xliff:g id="ok">%2$s</xliff:g>», el preséu va reaniciase y entrar nel mou de recuperación pa instalar l\'anovamientu.\n\nNota: esta función rique un recovery compatible o los anovamientos tienen que s\'instalar manualmente.</string>
<string name="apply_update_dialog_message_ab">Tas a piques d\'instalar «<xliff:g id="update_name">%1$s</xliff:g>».\n\nSi primes «<xliff:g id="ok">%2$s</xliff:g>», el preséu va comenzar la instalación en segundu planu.\n\nNamás acabar, el propiu preséu va suxerite que lu reanicies.</string>
<string name="cancel_installation_dialog_message">¿Quies encaboxar la instalación?</string>
<string name="label_download_url">URL de la descarga</string>
<string name="toast_download_url_copied">Copióse la URL</string>
<string name="dialog_export_title">Esportando l\'anovamientu</string>
<string name="notification_export_success">Esportóse l\'anovamientu</string>
<string name="notification_export_fail">Error de la esportación</string>
<string name="toast_already_exporting">Yá ta esportándose un anovamientu</string>
<string name="toast_export_started">Anicióse la esportación</string>
<plurals name="eta_seconds">
<item quantity="one">Queda 1 segundu</item>
<item quantity="other">Queden <xliff:g id="count">%d</xliff:g> segundos</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">Queda 1 minutu</item>
<item quantity="other">Queden <xliff:g id="count">%d</xliff:g> minutos</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">Queda 1 hora</item>
<item quantity="other">Queden <xliff:g id="count">%d</xliff:g> hores</item>
</plurals>
<string name="update_over_metered_network_title">Alvertencia</string>
<string name="update_over_metered_network_message">Tas a piques de baxar un paquete d\'anovamientu pente una rede midida, lo que probablemente vaiga xenerar un usu altu de datos. ¿Quies siguir?</string>
<string name="checkbox_metered_network_warning">Nun volver amosar</string>
<string name="menu_metered_network_warning">Alvertir al tar nuna rede midida</string>
<string name="blocked_update_dialog_title">Bloquióse l\'anovamientu</string>
<string name="blocked_update_dialog_message">Esti anovamientu nun se pue instalar con «Anovador». Llei <xliff:g id="info_url">%1$s</xliff:g> pa consiguir más información.</string>
<string name="export_channel_title">Esportación completada</string>
<string name="new_updates_channel_title">Hai anovamientos</string>
<string name="ongoing_channel_title">Descargues en cursu</string>
<string name="update_failed_channel_title">Anovamientu fallíu</string>
<string name="info_dialog_title">¿Sabíeslo?</string>
<string name="info_dialog_message">Los anovamientos de LineageOS son paquetes d\'instalación completos. Esto significa que siempre pues instalar l\'últimu anovamientu, ¡magar que saltares dalgún intermediu!</string>
<string name="info_dialog_ok">¡Gracies!</string>
<string name="local_update_import">Anovamientu llocal</string>
<string name="local_update_import_progress">Importando l\'anovamientu llocal\u2026</string>
<string name="local_update_import_success">Importóse «%1$s». ¿Quies instalar l\'anovamientu?</string>
<string name="local_update_import_failure">Hebo un fallu al importar l\'anovamientu llocal</string>
<string name="local_update_import_install">Instalar</string>
<string name="local_update_name">Anovamientu llocal</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Güncəlləyici</string>
<string name="display_name">Güncəlləyici</string>
<string name="verification_failed_notification">Doğrulama uğursuz oldu</string>
<string name="verifying_download_notification">Güncəlləmə doğrulanır</string>
<string name="downloading_notification">Endirilir</string>
<string name="download_paused_notification">Endirməyə fasilə verildi</string>
<string name="download_paused_error_notification">Endirmə xətası</string>
<string name="download_completed_notification">Endirmə tamamlandı</string>
<string name="download_starting_notification">Endirmə başladılır</string>
<string name="update_failed_notification">Güncəlləmə uğursuz oldu</string>
<string name="installation_suspended_notification">Quraşdırma dayandırıldı</string>
<string name="new_updates_found_title">Yeni güncəlləmələr</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Fasilə ver</string>
<string name="resume_button">Davam etdir</string>
<string name="suspend_button">Dayandır</string>
<string name="installing_update">Güncəlləmə paketi quraşdırılır</string>
<string name="installing_update_error">Quraşdırma xətası</string>
<string name="installing_update_finished">Güncəlləmə quraşdırıldı</string>
<string name="finalizing_package">Paket quraşdırma tamamlanır</string>
<string name="preparing_ota_first_boot">İlk yükləmə üçün hazırlanır</string>
<string name="dialog_prepare_zip_message">Güncəlləməyə ilkin hazırlıq</string>
<string name="dialog_battery_low_title">Zəif batareya</string>
<string name="dialog_battery_low_message_pct">Batareya səviyyəsi çox aşağıdır, davam etmək üçün ən az <xliff:g id="percent_discharging">%1$d</xliff:g>%% olmalıdır, <xliff:g id="percent_charging">%2$d</xliff:g>%% dolur.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Lütfən aşağıdakı əmrləri işə salın və yenidən güncəlləməyə çalışın:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">OverlayFS taxılı ikən güncəlləmə quraşdırıla bilmir</string>
<string name="reboot">Yenidən başlat</string>
<string name="menu_refresh">Təzələ</string>
<string name="menu_preferences">Tərcihlər</string>
<string name="menu_auto_updates_check">Avto-güncəlləmə yoxlanışı</string>
<string name="menu_auto_updates_check_interval_daily">Gündə bir dəfə</string>
<string name="menu_auto_updates_check_interval_weekly">Həftədə bir dəfə</string>
<string name="menu_auto_updates_check_interval_monthly">Ayda bir dəfə</string>
<string name="menu_auto_updates_check_interval_never">Heç vaxt</string>
<string name="menu_auto_delete_updates">Quraşdırılanda güncəlləmələri sil</string>
<string name="menu_delete_update">Sil</string>
<string name="menu_copy_url">URL-ni Kopyala</string>
<string name="menu_export_update">Güncəlləməni xaricə köçür</string>
<string name="menu_show_changelog">Dəyişiklik jurnalını göstər</string>
<string name="menu_ab_perf_mode">Üstünlüyü güncəlləmə prosesinə ver</string>
<string name="menu_update_recovery">Geri qaytarma rejimini güncəllə</string>
<string name="toast_forced_update_recovery">Bu cihazda Lineage Geri qaytarma güncəlləmələrini sıradan çıxartmaq mümkün deyil.</string>
<string name="snack_updates_found">Yeni güncəlləmə tapıldı</string>
<string name="snack_no_updates_found">Yeni güncəlləmə tapılmadı</string>
<string name="snack_updates_check_failed">Güncəlləmə yoxlanışı uğursuz oldu. Lütfən internet bağlantınızı yoxlayıb daha sonra yenidən sınayın.</string>
<string name="snack_download_failed">Endirmə uğursuz oldu. Lütfən internet bağlantınızı yoxlayıb yenidən sınayın.</string>
<string name="snack_download_verification_failed">Güncəlləmə doğrulaması uğursuz oldu.</string>
<string name="snack_download_verified">Endirmə tamamlandı.</string>
<string name="snack_update_not_installable">Bu güncəlləmə hazırkı quruluşun üzərinə quraşdırıla bilməz.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Son yoxlama: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> / <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> / <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Güncəlləmə doğrulanır</string>
<string name="list_no_updates">Yeni güncəlləmə tapılmadı. Yeni güncəlləmələri əllə yoxlamaq üçün Təzələ düyməsini istifadə edin.</string>
<string name="action_download">Endir</string>
<string name="action_pause">Fasilə ver</string>
<string name="action_resume">Davam etdir</string>
<string name="action_install">Quraşdır</string>
<string name="action_info">Məlumat</string>
<string name="action_delete">Sil</string>
<string name="action_cancel">İmtina</string>
<string name="confirm_delete_dialog_title">Faylı sil</string>
<string name="confirm_delete_dialog_message">Seçilmiş güncəlləmə faylı silinsin?</string>
<string name="apply_update_dialog_title">Güncəlləməni tətbiq et</string>
<string name="apply_update_dialog_message"><xliff:g id="update_name">%1$s</xliff:g> quraşdırırsınız.\n\n<xliff:g id="ok">%2$s</xliff:g> bassanız, cihaz güncəlləməni quraşdırmaq üçün geri qaytarma rejimində yenidən başlayacaq.\n\nQeyd: Bu özəlliyin uyumlu bir Geri qaytarma mühitinə ehtiyacı var və ya güncəlləmələr əllə quraşdırılmalıdır.</string>
<string name="apply_update_dialog_message_ab"><xliff:g id="update_name">%1$s</xliff:g> quraşdırırsınız.\n\n<xliff:g id="ok">%2$s</xliff:g> düyməsinə bassanız, cihaz arxaplanda quraşdırılmağa başlıyacaq.\n\nƏməliyyat bitəndə, yenidən başladılmalıdır.</string>
<string name="cancel_installation_dialog_message">Quraşdırmadan imtina edilsin?</string>
<string name="label_download_url">Endirmə bağlantısı</string>
<string name="toast_download_url_copied">Bağlantı kopyalandı</string>
<string name="dialog_export_title">Güncəlləmə xaricə köçürülür</string>
<string name="notification_export_success">Güncəlləmə xaricə köçürüldü</string>
<string name="notification_export_fail">Köçürmə xətası</string>
<string name="toast_already_exporting">Artıq bir güncəlləmə xaricə köçürülür</string>
<string name="toast_export_started">Xaricə köçürmə başladı</string>
<plurals name="eta_seconds">
<item quantity="one">1 saniyə qaldı</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> saniyə qaldı</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 dəqiqə qaldı</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> dəqiqə qaldı</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 saat qaldı</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> saat qaldı</item>
</plurals>
<string name="update_over_metered_network_title">Xəbərdarlıq</string>
<string name="update_over_metered_network_message">Ölçülən bir şəbəkə üzərindən böyük ehtimalla yüksək data istifadəsinə səbəb olacaq bir güncəlləmə paketi endirmək üzrəsiniz. Davam etmək istəyirsiniz?</string>
<string name="checkbox_metered_network_warning">Təkrar göstərmə</string>
<string name="menu_metered_network_warning">Ölçülən şəbəkə xəbərdarlığı</string>
<string name="blocked_update_dialog_title">Güncəlləmə əngəlləndi</string>
<string name="blocked_update_dialog_message">Bu güncəlləmə, tətbiq güncəlləyici istifadə edilərək quraşdırıla bilməz. Ətraflı məlumat üçün lütfən <xliff:g id="info_url">%1$s</xliff:g> ünvanını oxuyun.</string>
<string name="export_channel_title">Köçürmə tamamlandı</string>
<string name="new_updates_channel_title">Yeni güncəlləmələr</string>
<string name="ongoing_channel_title">Davam edən endirmələr</string>
<string name="update_failed_channel_title">Güncəlləmə uğursuz oldu</string>
<string name="info_dialog_title">Bilirdiniz?</string>
<string name="info_dialog_message">LineageOS güncəlləmələri tam quraşdırma paketləridir. Yəni, güncəlləməni ötürsəniz belə, hər zaman yalnız son güncəlləməni quraşdıra bilərsiniz!</string>
<string name="info_dialog_ok">Məlumat üçün təşəkkürlər!</string>
<string name="local_update_import">Yerli güncəlləmə</string>
<string name="local_update_import_progress">Yerli güncəlləmə daxilə köçürülür\u2026</string>
<string name="local_update_import_success">%1$s daxilə köçürüldü. Quraşdırmaq istəyirsiniz?</string>
<string name="local_update_import_failure">Yerli güncəlləmə daxilə köçürülmədi</string>
<string name="local_update_import_install">Quraşdır</string>
<string name="local_update_name">Yerli güncəlləmə</string>
</resources>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="download_paused_error_notification">Памылка спампоўвання</string>
<string name="installation_suspended_notification">Усталяванне прыпынена</string>
<string name="new_updates_found_title">Новыя абнаўленні</string>
<string name="text_download_speed">%1$s, %2$s/с</string>
<string name="installing_update">Усталяванне пакета з абнаўленнем</string>
<string name="installing_update_error">Памылка ўсталявання</string>
<string name="preparing_ota_first_boot">Падрыхтоўка да першага запуску</string>
<string name="dialog_prepare_zip_message">Падрыхтоўка абнаўлення</string>
<string name="reboot">Перазапуск</string>
<string name="menu_refresh">Абнавiць</string>
<string name="menu_auto_updates_check">Аўтаматычная праверка абнаўленняў</string>
<string name="menu_auto_updates_check_interval_monthly">Штомесяц</string>
<string name="menu_auto_updates_check_interval_never">Ніколі</string>
<string name="menu_auto_delete_updates">Выдаліць файлы абнаўлення пасля ўсталявання</string>
<string name="menu_delete_update">Выдаліць</string>
<string name="menu_copy_url">Скапіяваць URL-адрас</string>
<string name="menu_export_update">Экспартаванне абнаўлення</string>
<string name="menu_ab_perf_mode">Прыярытэт працэсу абнаўлення</string>
<string name="snack_no_updates_found">Абнаўленні не знойдзены</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_last_updates_check">Апошняя праверка: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_no_updates">Новыя абнаўленні не знойдзены. Каб праверыць абнаўленні ўручную, націсніце кнопку Абнавіць.</string>
<string name="action_download">Спампаваць</string>
<string name="action_install">Усталяваць</string>
<string name="action_info">Інфармацыя</string>
<string name="action_delete">Выдаліць</string>
<string name="confirm_delete_dialog_title">Выдаліць файл</string>
<string name="confirm_delete_dialog_message">Выдаліць выбраны файл абнаўлення?</string>
<string name="apply_update_dialog_title">Ужыць абнаўленне</string>
<string name="label_download_url">URL-адрасы спамповак</string>
<string name="dialog_export_title">Экспартаванне абнаўлення</string>
<string name="toast_export_started">Пачалося экспартаванне</string>
<string name="checkbox_metered_network_warning">Больш не паказваць</string>
<string name="new_updates_channel_title">Новыя абнаўленні</string>
<string name="ongoing_channel_title">Бягучыя спампоўкі</string>
<string name="info_dialog_title">Ці ведалі вы што?</string>
<string name="local_update_import">Лакальнае абнаўленне</string>
<string name="local_update_import_failure">Не ўдалося імпартаваць лакальнае абнаўленне</string>
<string name="local_update_import_install">Усталяваць</string>
<string name="local_update_name">Лакальнае абнаўленне</string>
</resources>

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Актуализатор</string>
<string name="display_name">Актуализатор</string>
<string name="verification_failed_notification">Неуспешна проверка</string>
<string name="verifying_download_notification">Проверено обновяване</string>
<string name="downloading_notification">Сваляне</string>
<string name="download_paused_notification">Пауза на сваляне</string>
<string name="download_paused_error_notification">Грешка при изтегляне</string>
<string name="download_completed_notification">Изтеглянето приключи</string>
<string name="download_starting_notification">Започни сваляне</string>
<string name="update_failed_notification">Актуализацията прекратена</string>
<string name="installation_suspended_notification">Инсталацията е прекратена</string>
<string name="new_updates_found_title">Нови актуализации</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Пауза</string>
<string name="resume_button">Възобнови</string>
<string name="suspend_button">Прекратено</string>
<string name="installing_update">Инсталиране на пакета за актуализация</string>
<string name="installing_update_error">Грешка при инсталиране</string>
<string name="installing_update_finished">Актуализацията е инсталирана</string>
<string name="finalizing_package">Финализиране на пакетната инсталация</string>
<string name="preparing_ota_first_boot">Подготовка за първо зареждане</string>
<string name="dialog_prepare_zip_message">Предварителна подготовка на актуализацията</string>
<string name="dialog_battery_low_title">Изтощена батерия</string>
<string name="dialog_battery_low_message_pct">Нивото на батерията е прекалено ниско, необходимо е най-малко <xliff:g id="percent_discharging">%1$d</xliff:g>%% за да продължите, <xliff:g id="percent_charging">%2$d</xliff:g>%%.</string>
<string name="reboot">Рестартиране</string>
<string name="menu_refresh">Опресняване</string>
<string name="menu_preferences">Настройки</string>
<string name="menu_auto_updates_check">Автоматична проверка за актуализациите</string>
<string name="menu_auto_updates_check_interval_daily">Ежедневно</string>
<string name="menu_auto_updates_check_interval_weekly">Ежеседмично</string>
<string name="menu_auto_updates_check_interval_monthly">Ежемесечно</string>
<string name="menu_auto_updates_check_interval_never">Никога</string>
<string name="menu_auto_delete_updates">Изтриване на актуализациите след инсталиране</string>
<string name="menu_delete_update">Изтриване</string>
<string name="menu_copy_url">Копирай адреса</string>
<string name="menu_export_update">Експортиране на актуализация</string>
<string name="menu_show_changelog">Покажи промените</string>
<string name="menu_ab_perf_mode">Приоритет на процеса на актуализиране</string>
<string name="menu_update_recovery">Актуализиране на recovery</string>
<string name="toast_forced_update_recovery">Невъзможно е да деактивирате актуализациите на Lineage Recovery на това устройство.</string>
<string name="snack_updates_found">Намерена е нова актуализация</string>
<string name="snack_no_updates_found">Няма нови актуализации</string>
<string name="snack_updates_check_failed">Проверката за актуализации се провали. Моля проверете връзката с интернет и опитайте отново по-късно.</string>
<string name="snack_download_failed">Неуспешно изтегляне. Моля проверете вашата интернет връзка и опитайте отново по-късно.</string>
<string name="snack_download_verification_failed">Проверката на актуализацията е неуспешна.</string>
<string name="snack_download_verified">Изтеглянето приключи.</string>
<string name="snack_update_not_installable">Тази актуализация не може да бъде инсталирана на текущата версия.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Последна проверка: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">Проверка на актуализацията</string>
<string name="list_no_updates">Не са намерени нови актуализации. За да проверите ръчно за нови актуализации, използвайте бутона за обновяване.</string>
<string name="action_download">Изтегли</string>
<string name="action_pause">Пауза</string>
<string name="action_resume">Възобнови</string>
<string name="action_install">Инсталиране</string>
<string name="action_info">Информация</string>
<string name="action_delete">Изтриване</string>
<string name="action_cancel">Отказ</string>
<string name="confirm_delete_dialog_title">Изтриване на файл</string>
<string name="confirm_delete_dialog_message">Да бъде ли изтрит файлът на избраната актуализация?</string>
<string name="apply_update_dialog_title">Приложи актуализацията</string>
<string name="cancel_installation_dialog_message">Анулиране на инсталирането?</string>
<string name="label_download_url">Изтеглете URL</string>
<string name="toast_download_url_copied">URL Копиран</string>
<string name="dialog_export_title">Експортиране на актуализация</string>
<string name="notification_export_success">Актуализацията е експортирана</string>
<string name="notification_export_fail">Грешка при експортиране</string>
<string name="toast_already_exporting">Вече изнася актуализация</string>
<plurals name="eta_seconds">
<item quantity="one">остава 1 секунда</item>
<item quantity="other">остават <xliff:g id="count">%d</xliff:g> секунди</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">остава 1 минута</item>
<item quantity="other">остават <xliff:g id="count">%d</xliff:g> минути</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">остава 1 час</item>
<item quantity="other">остават <xliff:g id="count">%d</xliff:g> часа</item>
</plurals>
<string name="update_over_metered_network_title">Внимание</string>
<string name="checkbox_metered_network_warning">Не показвай отново</string>
<string name="blocked_update_dialog_title">Актуализацията е блокирана</string>
<string name="blocked_update_dialog_message">Тази актуализация не може да бъде инсталирана посредством приложението за актуализации. Моля прочетете <xliff:g id="info_url">%1$s</xliff:g> за повече информация.</string>
<string name="export_channel_title">Експортирането приключи</string>
<string name="new_updates_channel_title">Нови актуализации</string>
<string name="ongoing_channel_title">Текущи изтегляния</string>
<string name="update_failed_channel_title">Актуализацията прекратена</string>
</resources>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">আধুনিকীকরণকারী</string>
<string name="display_name">আধুনিকীকরণকারী</string>
<string name="verification_failed_notification">যাচাইকরণ ব্যর্থ হয়েছে</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">বিরাম</string>
<string name="menu_update_recovery">রিকভারি আপডেট করুন</string>
<string name="toast_forced_update_recovery">এই ডিভাইসে লিনিয়েজ রিকভারি এর আপডেট বন্ধ করা সম্ভব নয়</string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> এর <xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>) এর <xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g></string>
<string name="apply_update_dialog_message">আপনি এখন <xliff:g id="update_name">%1$s</xliff:g> ইনস্টল করতে যাচ্ছেন। আপনি যদি <xliff:g id="ok">%2$s</xliff:g> বোতামে টিপ দেন, তাহলে ডিভাইসটি আপডেট করার জন্য রিকভারি মোডে চলে যাবে।\n\n এই কাজটি সম্পাদনের জন্য আপডেট সমর্থন করে এমন একটি রিকভারি লাগবে। তা না হলে আপডেটটি আপনার মেনুয়ালি ইনস্টল করতে হবে।</string>
<string name="apply_update_dialog_message_ab">আপনি এখন <xliff:g id="update_name">%1$s</xliff:g> ইনস্টল করতে যাচ্ছেন।\n\nআপনি যদি <xliff:g id="ok">%2$s</xliff:g> বোতামে টিপ দেন, তাহলে ডিভাইসটি ব্যাকগ্রাউন্ড এ ইনস্টল করতে থাকবে।\n\nআপডেটটি ইনস্টল করা শেষ হলে আপনাকে রিস্টার্ট করতে বলা হবে।</string>
<string name="toast_export_started">রপ্তানি করা শুরু হয়েছে</string>
<plurals name="eta_seconds">
<item quantity="one">১ সেকেন্ড বাকি</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> সেকেন্ড বাকি</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">১ মিনিট বাকি</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> মিনিট বাকি</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">১ ঘণ্টা বাকি</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> ঘণ্টা বাকি</item>
</plurals>
<string name="info_dialog_title">আপনি কি জানতেন?</string>
<string name="info_dialog_message">লিনিএজ ওএস এর আপডেট প্যাকেজে সকল ফাইল দেওয়া থাকে। অর্থাৎ আপনি মাঝের আপডেটগুলো ইনস্টল না করে শুধুমাত্র লেটেস্ট আপডেট ইনস্টল করতে পারবেন।</string>
<string name="info_dialog_ok">তথ্যটির জন্য ধন্যবাদ</string>
</resources>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="dialog_battery_low_title">Slaba baterija</string>
<string name="dialog_battery_low_message_pct">Baterija je slaba, potrebno je barem <xliff:g id="percent_discharging">%1$d</xliff:g>%% baterije za nastavak, <xliff:g id="percent_charging">%2$d</xliff:g>%% ukoliko se puni.</string>
<string name="menu_auto_updates_check_interval_daily">Jednom dnevno</string>
<string name="menu_auto_updates_check_interval_weekly">Jednom sedmično</string>
<string name="menu_auto_updates_check_interval_monthly">Jednom mjesečno</string>
<string name="menu_auto_updates_check_interval_never">Nikada</string>
<plurals name="eta_seconds">
<item quantity="one">1 sekunda preostala</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> sekunde preostale</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> sekundi preostalo</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minuta preostala</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> minute preostale</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minuta preostalo</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 sat preostao</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> sata preostalo</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> sati preostalo</item>
</plurals>
<string name="export_channel_title">Izvoz završen</string>
<string name="ongoing_channel_title">Preuzimanja u toku</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Actualitzador</string>
<string name="display_name">Actualitzador</string>
<string name="verification_failed_notification">Ha fallat la verificació</string>
<string name="verifying_download_notification">S\'està verificant l\'actualització</string>
<string name="downloading_notification">S\'està baixant</string>
<string name="download_paused_notification">Baixada en pausa</string>
<string name="download_paused_error_notification">Baixada fallida</string>
<string name="download_completed_notification">Baixada completada</string>
<string name="download_starting_notification">S\'està iniciant la baixada</string>
<string name="update_failed_notification">Actualització fallida</string>
<string name="installation_suspended_notification">Instal·lació suspesa</string>
<string name="new_updates_found_title">Noves actualitzacions</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pausa</string>
<string name="resume_button">Reprèn</string>
<string name="suspend_button">Suspèn</string>
<string name="installing_update">S\'està instal·lant el paquet d\'actualització</string>
<string name="installing_update_error">Instal·lació fallida</string>
<string name="installing_update_finished">Actualització instal·lada</string>
<string name="finalizing_package">S\'està finalitzant la instal·lació del paquet</string>
<string name="preparing_ota_first_boot">S\'està preparant el primer inici</string>
<string name="dialog_prepare_zip_message">Preparació preliminar de l\'actualització</string>
<string name="dialog_battery_low_title">Bateria baixa</string>
<string name="dialog_battery_low_message_pct">El nivell de la bateria és massa baix, necessiteu com a mínim <xliff:g id="percent_discharging">%1$d</xliff:g>%% de bateria per continuar, <xliff:g id="percent_charging">%2$d</xliff:g>%% si el dispositiu s\'està carregant.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Executeu les ordres següents i torneu a provar l\'actualització:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">No es pot instal·lar l\'actualització amb l\'OverlayFS muntat</string>
<string name="reboot">Reinicia</string>
<string name="menu_refresh">Recarrega</string>
<string name="menu_preferences">Preferències</string>
<string name="menu_auto_updates_check">Comprova automàticament les actualitzacions</string>
<string name="menu_auto_updates_check_interval_daily">Un cop al dia</string>
<string name="menu_auto_updates_check_interval_weekly">Un cop per setmana</string>
<string name="menu_auto_updates_check_interval_monthly">Un cop al mes</string>
<string name="menu_auto_updates_check_interval_never">Mai</string>
<string name="menu_auto_delete_updates">Elimina les actualitzacions una vegada s\'hagin instal·lat</string>
<string name="menu_delete_update">Elimina</string>
<string name="menu_copy_url">Copia l\'URL</string>
<string name="menu_export_update">Exporta l\'actualització</string>
<string name="menu_show_changelog">Mostra el registre de canvis</string>
<string name="menu_ab_perf_mode">Prioritza el procés d\'actualització</string>
<string name="menu_update_recovery">Actualitza el recuperador</string>
<string name="toast_forced_update_recovery">No és possible desactivar les actualitzacions del recuperador del Lineage en aquest dispositiu.</string>
<string name="snack_updates_found">No s\'han trobat noves actualitzacions</string>
<string name="snack_no_updates_found">No s\'han trobat noves actualitzacions</string>
<string name="snack_updates_check_failed">Ha fallat la comprovació d\'actualització. Verifiqueu la connexió a Internet i tomeu-ho a provar més tard.</string>
<string name="snack_download_failed">Ha fallat la la baixada. Verifiqueu la connexió a Internet i torneu-ho a provar més tard.</string>
<string name="snack_download_verification_failed">Ha fallat la verificació de l\'actualització.</string>
<string name="snack_download_verified">Baixada completada.</string>
<string name="snack_update_not_installable">Aquesta actualització no es pot instal·lar a sobre de la compilació actual.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Darrera comprovació: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">S\'està verificant l\'actualització</string>
<string name="list_no_updates">No s\'han trobat noves actualitzacions. Per comprovar manualment si hi ha noves actualitzacions, utilitzeu el botó Refresca.</string>
<string name="action_download">Baixa</string>
<string name="action_pause">Pausa</string>
<string name="action_resume">Reprèn</string>
<string name="action_install">Instal·la</string>
<string name="action_info">Informació</string>
<string name="action_delete">Suprimeix</string>
<string name="action_cancel">Cancel·la</string>
<string name="confirm_delete_dialog_title">Esborra el fitxer</string>
<string name="confirm_delete_dialog_message">Vols esborrar el fitxer d\'actualització seleccionat?</string>
<string name="apply_update_dialog_title">Aplica l\'actualització</string>
<string name="apply_update_dialog_message">Esteu a punt d\'instal·lar <xliff:g id="update_name">%1$s</xliff:g>.\n\nSi premeu <xliff:g id="ok">%2$s</xliff:g>, el dispositiu es reiniciarà en el mode recuperació per a instal·lar l\'actualització.\n\nNota: Aquesta funció requereix un Recuperador compatible o les actualitzacions hauran de ser instal·lades manualment.</string>
<string name="apply_update_dialog_message_ab">Esteu a punt d\'instal·lar <xliff:g id="update_name">%1$s</xliff:g>.\n\nSi premeu <xliff:g id="ok">%2$s</xliff:g>, el dispositiu començarà a instal·lar-ho en segon pla.\n\nUna vegada completat, se us demanarà que el reinicieu.</string>
<string name="cancel_installation_dialog_message">Voleu cancel·lar la instal·lació?</string>
<string name="label_download_url">URL de baixada</string>
<string name="toast_download_url_copied">URL copiada</string>
<string name="dialog_export_title">S\'està exportant l\'actualització</string>
<string name="notification_export_success">Actualització exportada</string>
<string name="notification_export_fail">Ha fallat l\'exportació</string>
<string name="toast_already_exporting">Ja s\'està exportant una actualització</string>
<string name="toast_export_started">S\'ha iniciat l\'exportació</string>
<plurals name="eta_seconds">
<item quantity="one">Falta 1 segon</item>
<item quantity="other">Falten <xliff:g id="count">%d</xliff:g> segons</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">Falta 1 minut</item>
<item quantity="other">Falten <xliff:g id="count">%d</xliff:g> minuts</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">Falta 1 hora</item>
<item quantity="other">Falten <xliff:g id="count">%d</xliff:g> hores</item>
</plurals>
<string name="update_over_metered_network_title">Advertència</string>
<string name="update_over_metered_network_message">Esteu a punt de baixar un paquet d\'actualització a través d\'una xarxa mesurada que és probable que provoqui un ús elevat de dades. Voleu continuar?</string>
<string name="checkbox_metered_network_warning">No ho tornis a mostrar</string>
<string name="menu_metered_network_warning">Avís de xarxa mesurada</string>
<string name="blocked_update_dialog_title">Actualització bloquejada</string>
<string name="blocked_update_dialog_message">Aquesta actualització no es pot instal·lar mitjançant l\'aplicació actualitzador. Per obtenir més informació, llegiu <xliff:g id="info_url">%1$s</xliff:g>.</string>
<string name="export_channel_title">Exportació completada</string>
<string name="new_updates_channel_title">Noves actualitzacions</string>
<string name="ongoing_channel_title">Baixades en curs</string>
<string name="update_failed_channel_title">Actualització fallida</string>
<string name="info_dialog_title">Ho sabies?</string>
<string name="info_dialog_message">Les actualitzacions de LineageOS són paquets d\'instal·lació complets. Açò significa que sempre pots instal·lar únicament l\'última actualització, encara que t\'hagis saltat alguna actualització per entremig.</string>
<string name="info_dialog_ok">Gràcies per la informació!</string>
<string name="local_update_import">Actualització local</string>
<string name="local_update_import_progress">S\'està important l\'actualització local\u2026</string>
<string name="local_update_import_success">S\'ha importat %1$s. Ho voleu instal·lar?</string>
<string name="local_update_import_failure">No s\'ha pogut importar l\'actualització local</string>
<string name="local_update_import_install">Instal·la</string>
<string name="local_update_name">Actualització local</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Aktualizace</string>
<string name="display_name">Aktualizace</string>
<string name="verification_failed_notification">Ověření selhalo</string>
<string name="verifying_download_notification">Ověření aktualizace</string>
<string name="downloading_notification">Stahování</string>
<string name="download_paused_notification">Stahování pozastaveno</string>
<string name="download_paused_error_notification">Chyba při stahování</string>
<string name="download_completed_notification">Stahování úspěšné</string>
<string name="download_starting_notification">Zahajování stahování</string>
<string name="update_failed_notification">Aktualizace se nezdařila</string>
<string name="installation_suspended_notification">Instalace odložena</string>
<string name="new_updates_found_title">Nové aktualizace</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pozastavit</string>
<string name="resume_button">Obnovit</string>
<string name="suspend_button">Pozastavit</string>
<string name="installing_update">Instalace balíčku aktualizace</string>
<string name="installing_update_error">Chyba instalace</string>
<string name="installing_update_finished">Aktualizace byla nainstalována</string>
<string name="finalizing_package">Dokončování instalace balíčku</string>
<string name="preparing_ota_first_boot">Příprava na první spuštění</string>
<string name="dialog_prepare_zip_message">Příprava předběžné aktualizace</string>
<string name="dialog_battery_low_title">Slabá baterie</string>
<string name="dialog_battery_low_message_pct">Úroveň nabití baterie je příliš nízká, potřebujete alespoň <xliff:g id="percent_discharging">%1$d</xliff:g>%% baterie pro pokračování, <xliff:g id="percent_charging">%2$d</xliff:g>%% při nabíjení.</string>
<string name="reboot">Reboot</string>
<string name="menu_refresh">Obnovit</string>
<string name="menu_preferences">Předvolby</string>
<string name="menu_auto_updates_check">Automatická kontrola aktualizací</string>
<string name="menu_auto_updates_check_interval_daily">Jednou denně</string>
<string name="menu_auto_updates_check_interval_weekly">Jednou týdně</string>
<string name="menu_auto_updates_check_interval_monthly">Jednou měsíčně</string>
<string name="menu_auto_updates_check_interval_never">Nikdy</string>
<string name="menu_auto_delete_updates">Odstranit aktualizace po instalaci</string>
<string name="menu_delete_update">Odstranit</string>
<string name="menu_copy_url">Kopírovat URL</string>
<string name="menu_export_update">Export aktualizace</string>
<string name="menu_show_changelog">Zobrazit seznam změn</string>
<string name="menu_ab_perf_mode">Upřednostňovat proces aktualizace</string>
<string name="menu_update_recovery">Aktualizovat recovery oddíl</string>
<string name="toast_forced_update_recovery">Na tomto zařízení není možné zakázat aktualizace oddílu Lineage recovery</string>
<string name="snack_updates_found">Nalezeny nové aktualizace</string>
<string name="snack_no_updates_found">Nové aktualizace nenalezeny</string>
<string name="snack_updates_check_failed">Zjištění nové verze selhalo. Prosím zkontrolujte připojení k internetu a pokus opakujte.</string>
<string name="snack_download_failed">Stahování selhalo. Prosím zkontrolujte připojení k internetu a pokus opakujte.</string>
<string name="snack_download_verification_failed">Ověření aktualizace se nezdařilo.</string>
<string name="snack_download_verified">Stahování úspěšné.</string>
<string name="snack_update_not_installable">Tuto aktualizaci nelze nainstalovat přes aktuální sestavení.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Poslední kontrola: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> z(e) <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> z(e) <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Ověření aktualizace</string>
<string name="list_no_updates">Nebyly nalezeny žádné nové aktualizace. Chcete-li ručně vyhledat nové aktualizace, použijte tlačítko „Obnovit“.</string>
<string name="action_download">Stáhnout</string>
<string name="action_pause">Pozastavit</string>
<string name="action_resume">Pokračovat</string>
<string name="action_install">Instalovat</string>
<string name="action_info">Informace</string>
<string name="action_delete">Odstranit</string>
<string name="action_cancel">Zrušit</string>
<string name="confirm_delete_dialog_title">Smazat soubor</string>
<string name="confirm_delete_dialog_message">Smazat zvolený soubor aktualizace?</string>
<string name="apply_update_dialog_title">Použít aktualizaci</string>
<string name="apply_update_dialog_message">Chystáte se instalovat <xliff:g id="update_name">%1$s</xliff:g>.\n\nPokud stisknete <xliff:g id="ok">%2$s</xliff:g>, telefon se restartuje do režimu Recovery, kde budete pokračovat v instalaci aktualizace.\n\nPoznámka: tato funkce vyžaduje nainstalovaný kompatibilní režim Recovery nebo je nutné instalaci provést ručně.</string>
<string name="apply_update_dialog_message_ab">Chystáte se instalovat <xliff:g id="update_name">%1$s</xliff:g>.\n\nPokud stisknete <xliff:g id="ok">%2$s</xliff:g>, spustí se instalace na pozadí.\n\nPo dokončení budete vyzváni k restartu.</string>
<string name="cancel_installation_dialog_message">Zrušit instalaci?</string>
<string name="label_download_url">URL stažení</string>
<string name="toast_download_url_copied">URL zkopírována</string>
<string name="dialog_export_title">Export aktualizace</string>
<string name="notification_export_success">Aktualizace exportována</string>
<string name="notification_export_fail">Chyba exportu</string>
<string name="toast_already_exporting">Aktualizace se již exportuje</string>
<string name="toast_export_started">Export byl zahájen</string>
<plurals name="eta_seconds">
<item quantity="one">Zbývá 1 sekunda</item>
<item quantity="few">Zbývají <xliff:g id="count">%d</xliff:g> sekundy</item>
<item quantity="many">Zbývá <xliff:g id="count">%d</xliff:g> sekund</item>
<item quantity="other">Zbývá <xliff:g id="count">%d</xliff:g> sekund</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">Zbývá 1 minuta</item>
<item quantity="few">Zbývají <xliff:g id="count">%d</xliff:g> minuty</item>
<item quantity="many">Zbývá <xliff:g id="count">%d</xliff:g> minut</item>
<item quantity="other">Zbývá <xliff:g id="count">%d</xliff:g> minut</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">Zbývá 1 hodina</item>
<item quantity="few">Zbývají <xliff:g id="count">%d</xliff:g> hodiny</item>
<item quantity="many">Zbývá <xliff:g id="count">%d</xliff:g> hodin</item>
<item quantity="other">Zbývá <xliff:g id="count">%d</xliff:g> hodin</item>
</plurals>
<string name="update_over_metered_network_title">Varování</string>
<string name="update_over_metered_network_message">Chystáte se stáhnout aktualizaci skrze měřenou síť, což pravděpodobně zapříčiní vysoké využití dat. Chcete pokračovat?</string>
<string name="checkbox_metered_network_warning">Znovu nezobrazovat</string>
<string name="menu_metered_network_warning">Upozornění na měřenou síť</string>
<string name="blocked_update_dialog_title">Aktualizace zablokována</string>
<string name="blocked_update_dialog_message">Tuto aktualizaci nelze nainstalovat pomocí aplikace aktualizace. Přečtěte si <xliff:g id="info_url">%1$s </xliff:g> pro další informace.</string>
<string name="export_channel_title">Dokončení exportu</string>
<string name="new_updates_channel_title">Nové aktualizace</string>
<string name="ongoing_channel_title">Probíhající stahování</string>
<string name="update_failed_channel_title">Aktualizace se nezdařila</string>
<string name="info_dialog_title">Věděli jste, že…</string>
<string name="info_dialog_message">Aktualizace LineageOS jsou plné instalační balíčky. To znamená, že můžete vždy nainstalovat pouze nejnovější aktualizaci, a\u00a0je možné některé z\u00a0nich zcela přeskočit!</string>
<string name="info_dialog_ok">Děkujeme za informace!</string>
<string name="local_update_import">Místní aktualizace</string>
<string name="local_update_import_progress">Probíhá import místní aktualizace\u2026</string>
<string name="local_update_import_success">%1$s byla importována. Chcete ji nainstalovat?</string>
<string name="local_update_import_failure">Nepodařilo se importovat místní aktualizaci</string>
<string name="local_update_import_install">Instalovat</string>
<string name="local_update_name">Místní aktualizace</string>
</resources>

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Diweddarydd</string>
<string name="display_name">Diweddarydd</string>
<string name="verification_failed_notification">Methodd y dilysiad</string>
<string name="verifying_download_notification">Yn dilysu\'r diweddariad</string>
<string name="downloading_notification">Yn lawrlwytho</string>
<string name="download_paused_notification">Lawrlwytho wedi seibio</string>
<string name="download_paused_error_notification">Gwall lawrlwytho</string>
<string name="download_completed_notification">Lawrlwytho wedi cwblhau</string>
<string name="download_starting_notification">Yn dechrau lawrlwytho</string>
<string name="update_failed_notification">Methodd y diweddariad</string>
<string name="installation_suspended_notification">Ataliwyd y gosod</string>
<string name="new_updates_found_title">Diweddariadau newydd</string>
<string name="text_download_speed">%1$s, %2$s/e</string>
<string name="pause_button">Seibio</string>
<string name="resume_button">Parhau</string>
<string name="suspend_button">Atal</string>
<string name="installing_update">Yn gosod pecyn diweddaru</string>
<string name="installing_update_error">Gwall gosod</string>
<string name="installing_update_finished">Gosodwyd y diweddariad</string>
<string name="finalizing_package">Yn cwblhau gosod y pecyn</string>
<string name="preparing_ota_first_boot">Yn paratoi i lwytho a rhedeg am y tro cyntaf</string>
<string name="dialog_prepare_zip_message">Paratoi diweddaru rhagbaratoawl</string>
<string name="dialog_battery_low_title">Batri isel</string>
<string name="dialog_battery_low_message_pct">Does dim digon o bŵer yn y batri. Rhaid cael o leiaf <xliff:g id="percent_discharging">%1$d</xliff:g>%% o fatri er mwyn parhau, <xliff:g id="percent_charging">%2$d</xliff:g>%% os yn gwefru.</string>
<string name="reboot">Ailgychwyn</string>
<string name="menu_refresh">Ail-lwytho</string>
<string name="menu_preferences">Dewisiadau</string>
<string name="menu_auto_updates_check">Gwirio yn awtomatig</string>
<string name="menu_auto_updates_check_interval_daily">Unwaith y dydd</string>
<string name="menu_auto_updates_check_interval_weekly">Unwaith yr wythnos</string>
<string name="menu_auto_updates_check_interval_monthly">Unwaith y mis</string>
<string name="menu_auto_updates_check_interval_never">Byth</string>
<string name="menu_auto_delete_updates">Dileu diweddariadau ar ôl eu gosod</string>
<string name="menu_delete_update">Dileu</string>
<string name="menu_copy_url">Copïo\'r URL</string>
<string name="menu_export_update">Allforio\'r diweddariad</string>
<string name="menu_show_changelog">Dangos log newid</string>
<string name="menu_ab_perf_mode">Blaenoriaethu\'r broses diweddaru</string>
<string name="menu_update_recovery">Adfer y modd diweddaru</string>
<string name="toast_forced_update_recovery">Mae\'n amhosibl analluogi diweddariadau Adfer Lineage ar y ddyfais hon.</string>
<string name="snack_updates_found">Mae yna ddiweddariad(au) newydd</string>
<string name="snack_no_updates_found">Ni chanfuwyd diweddariadau newydd</string>
<string name="snack_updates_check_failed">Methodd gwiriad y diweddariad. Gwiria dy gysylltiad â\'r rhwydwaith a rhoi cynnig arall arni.</string>
<string name="snack_download_failed">Methodd y lawrlwytho. Gwiria dy gysylltiad â\'r rhwydwaith a rhoi cynnig arall arni.</string>
<string name="snack_download_verification_failed">Methodd dilysiad y diweddariad.</string>
<string name="snack_download_verified">Lawrlwytho wedi cwblhau.</string>
<string name="snack_update_not_installable">Ni ellir gosod y diweddariad hwn ar ben yr adeiledd cyfredol.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Gwiriwyd diwethaf: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> o <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> o <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Yn dilysu\'r diweddariad</string>
<string name="list_no_updates">Ni chanfuwyd diweddariadau newydd. I wirio am ddiweddariadau newydd dy hun, defnyddia\'r botwm ail-lwytho.</string>
<string name="action_download">Lawrlwytho</string>
<string name="action_pause">Seibio</string>
<string name="action_resume">Parhau</string>
<string name="action_install">Gosod</string>
<string name="action_info">Gwybodaeth</string>
<string name="action_delete">Dileu</string>
<string name="action_cancel">Diddymu</string>
<string name="confirm_delete_dialog_title">Dileu ffeil</string>
<string name="confirm_delete_dialog_message">Dileu\'r ffeil diweddariad a ddewiswyd?</string>
<string name="apply_update_dialog_title">Gosod diweddariad</string>
<string name="apply_update_dialog_message">Rwyt ar fin osod <xliff:g id="update_name">%1$s</xliff:g>.\n\nOs wyt yn gwasgu <xliff:g id="ok">%2$s</xliff:g>, bydd y ddyfais yn ail-ddechrau ei hun i\'r modd adfer er mwyn gosod y diweddariad.\n\nNodyn: Mae ar y nodwedd hon angen Modd Adfer (Recovery) cydnaws er mwyn gosod diweddariadau yn awtomatig.</string>
<string name="apply_update_dialog_message_ab">Rwyt ar fin osod <xliff:g id="update_name">%1$s</xliff:g>.\n\nOs wyt yn gwasgu <xliff:g id="ok">%2$s</xliff:g>, bydd y ddyfais yn dechrau\'r gosod yn y cefndir.\n\nPan fydd wedi\'i gwblhau, cei dy hysbysu i ailddechrau\'r system.</string>
<string name="cancel_installation_dialog_message">Diddymu\'r gosod?</string>
<string name="label_download_url">URL lawrlwytho</string>
<string name="toast_download_url_copied">Copïwyd yr URL</string>
<string name="dialog_export_title">Yn allforio\'r diweddariad</string>
<string name="notification_export_success">Allforiwyd y diweddariad</string>
<string name="notification_export_fail">Gwall allforio</string>
<string name="toast_already_exporting">Eisoes yn allforio diweddariad</string>
<string name="toast_export_started">Wedi dechrau allforio</string>
<plurals name="eta_seconds">
<item quantity="zero"><xliff:g id="count">%d</xliff:g> eiliadau yn weddill</item>
<item quantity="one"><xliff:g id="count">%d</xliff:g> eiliad yn weddill</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> eiliad yn weddill</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> eiliad yn weddill</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> eiliad yn weddill</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> eiliad yn weddill</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="zero"><xliff:g id="count">%d</xliff:g> munudau yn weddill</item>
<item quantity="one"><xliff:g id="count">%d</xliff:g> munud yn weddill</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> funud yn weddill</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> munud yn weddill</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> munud yn weddill</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> munud yn weddill</item>
</plurals>
<plurals name="eta_hours">
<item quantity="zero"><xliff:g id="count">%d</xliff:g> oriau yn weddill</item>
<item quantity="one"><xliff:g id="count">%d</xliff:g> awr yn weddill</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> awr yn weddill</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> awr yn weddill</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> awr yn weddill</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> awr yn weddill</item>
</plurals>
<string name="update_over_metered_network_title">Rhybudd</string>
<string name="update_over_metered_network_message">Rwyt ar fin lawrlwytho pecyn diweddaru gyda llawer o ddata dros rwydwaith mesuredig. Wyt ti am barhau?</string>
<string name="checkbox_metered_network_warning">Peidio â dangos eto</string>
<string name="menu_metered_network_warning">Rhybudd rhwydwaith mesuredig</string>
<string name="blocked_update_dialog_title">Rhwystrwyd y diweddariad</string>
<string name="blocked_update_dialog_message">Ni ellir gosod y diweddariad hwn gyda\'r ap diweddarydd. Gweler <xliff:g id="info_url">%1$s</xliff:g> am wybodaeth bellach.</string>
<string name="export_channel_title">Cwblhawyd allforio</string>
<string name="new_updates_channel_title">Diweddariadau newydd</string>
<string name="ongoing_channel_title">Llwythi sy\'n parhau</string>
<string name="update_failed_channel_title">Methodd y diweddariad</string>
<string name="info_dialog_title">A wyddet ti?</string>
<string name="info_dialog_message">Mae diweddariadau LineageOS yn becynnau gosod llawn, felly mae o hyd yn bosib gosod y diweddariad diweddaraf, hyd yn oed os wyt wedi neidio ambell ddiweddariad ers y diwethaf!</string>
<string name="info_dialog_ok">Diolch am y wybodaeth!</string>
<string name="local_update_import">Diweddariad lleol</string>
<string name="local_update_import_progress">Yn mewnforio diweddariad lleol\u2026</string>
<string name="local_update_import_success">%1$s wedi ei fewnforio. Wyt ti am ei osod?</string>
<string name="local_update_import_failure">Methwyd â mewnforio diweddariad lleol</string>
<string name="local_update_import_install">Gosod</string>
<string name="local_update_name">Diweddariad lleol</string>
</resources>

View File

@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Opdatering</string>
<string name="display_name">Opdatering</string>
<string name="verification_failed_notification">Bekræftelse fejlede</string>
<string name="verifying_download_notification">Bekræfter opdatering</string>
<string name="downloading_notification">Henter</string>
<string name="download_paused_notification">Overførsel på pause</string>
<string name="download_paused_error_notification">Overførselsfejl</string>
<string name="download_completed_notification">Overførsel fuldført</string>
<string name="download_starting_notification">Starter overførsel</string>
<string name="update_failed_notification">Opdatering fejlede</string>
<string name="installation_suspended_notification">Installation suspenderet</string>
<string name="new_updates_found_title">Nye opdateringer</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pause</string>
<string name="resume_button">Genoptag</string>
<string name="suspend_button">Suspendér</string>
<string name="installing_update">Installerer opdateringspakke</string>
<string name="installing_update_error">Installeringsfejl</string>
<string name="installing_update_finished">Opdatering installeret</string>
<string name="finalizing_package">Fuldfører pakkeinstallering</string>
<string name="preparing_ota_first_boot">Forbereder på første opstart</string>
<string name="dialog_prepare_zip_message">Indledende opdateringsforberedelse</string>
<string name="dialog_battery_low_title">Lavt batteriniveau</string>
<string name="dialog_battery_low_message_pct">Du har for lidt strøm på dit batteri. Du skal mindst bruge <xliff:g id="percent_discharging">%1$d</xliff:g>%% for at installere opdateringen, <xliff:g id="percent_charging">%2$d</xliff:g>%% hvis din enhed oplader.</string>
<string name="reboot">Genstart</string>
<string name="menu_refresh">Genopfrisk</string>
<string name="menu_preferences">Præferencer</string>
<string name="menu_auto_updates_check">Auto-opdateringskontrol</string>
<string name="menu_auto_updates_check_interval_daily">Én gang dagligt</string>
<string name="menu_auto_updates_check_interval_weekly">En gang om ugen</string>
<string name="menu_auto_updates_check_interval_monthly">En gang om måneden</string>
<string name="menu_auto_updates_check_interval_never">Aldrig</string>
<string name="menu_auto_delete_updates">Slet opdateringer, når installeret</string>
<string name="menu_delete_update">Slet</string>
<string name="menu_copy_url">Kopiér URL</string>
<string name="menu_export_update">Eksportér opdatering</string>
<string name="menu_show_changelog">Vis ændringslog</string>
<string name="menu_ab_perf_mode">Prioritér opdateringsproces</string>
<string name="menu_update_recovery">Opdatér gendannelse</string>
<string name="toast_forced_update_recovery">Det er umuligt at deaktivere Lineage Gendannelse opdateringer på denne enhed.</string>
<string name="snack_updates_found">Nye opdateringer fundet</string>
<string name="snack_no_updates_found">Ingen nye opdateringer fundet</string>
<string name="snack_updates_check_failed">Opdateringskontrollen fejlede. Kontrollér venligst din internetforbindelse og prøv igen senere.</string>
<string name="snack_download_failed">Overførslen fejlede. Kontrollér venligst din internetforbindelse og prøv igen senere.</string>
<string name="snack_download_verification_failed">Opdateringsbekræftelsen fejlede.</string>
<string name="snack_download_verified">Overførsel fuldført.</string>
<string name="snack_update_not_installable">Denne opdatering kan ikke installeres ovenpå det nuværende build.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Sidst kontrolleret: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> af <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> af <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Bekræfter opdatering</string>
<string name="list_no_updates">Ingen nye opdateringer fundet. Brug Genopfrisk-knappen, for manuel kontrol af nye opdateringer.</string>
<string name="action_download">Hent</string>
<string name="action_pause">Pause</string>
<string name="action_resume">Genoptag</string>
<string name="action_install">Installér</string>
<string name="action_info">Info</string>
<string name="action_delete">Slet</string>
<string name="action_cancel">Afbryd</string>
<string name="confirm_delete_dialog_title">Slet fil</string>
<string name="confirm_delete_dialog_message">Slet den valgte opdateringsfil?</string>
<string name="apply_update_dialog_title">Anvend opdatering</string>
<string name="apply_update_dialog_message">Du er ved at installere <xliff:g id="update_name">%1$s</xliff:g>. \n\n Hvis du trykker <xliff:g id="ok">%2$s</xliff:g>, enheden vil genstarte i gendannelsestilstand for at installere opdateringen.\n\nNoter: Denne funktion kræver en kompitabel gendannelse eller opdateing vil have brug for at blive installeret manuelt.</string>
<string name="apply_update_dialog_message_ab">Du er ved at installere <xliff:g id="update_name">%1$s</xliff:g>.\n\n Hvis du trykker <xliff:g id="ok">%2$s</xliff:g>, vil enheden begynde at installere i baggrunden.\n\n Når færdig, vil du blive spurgt om at genstarte.</string>
<string name="cancel_installation_dialog_message">Afbryd installeringen?</string>
<string name="label_download_url">Hent URL</string>
<string name="toast_download_url_copied">URL kopieret</string>
<string name="dialog_export_title">Eksporterer opdatering</string>
<string name="notification_export_success">Opdatering eksporteret</string>
<string name="notification_export_fail">Eksportfejl</string>
<string name="toast_already_exporting">Eksporterer allerede en opdatering</string>
<string name="toast_export_started">Eksportering startet</string>
<plurals name="eta_seconds">
<item quantity="one">1 sekund tilbage</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> sekunder tilbage</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minut tilbage</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutter tilbage</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 time tilbage</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> timer tilbage</item>
</plurals>
<string name="update_over_metered_network_title">Advarsel</string>
<string name="update_over_metered_network_message">Du er ved at downloade en opdateringspakke over målingstilsluttet netværk, hvilket med stor sandsynlighed kan give højt data forbrug. Vil du gerne fortsætte?</string>
<string name="checkbox_metered_network_warning">Vis ikke igen</string>
<string name="menu_metered_network_warning">Målingstilsluttet netværks advarsel</string>
<string name="blocked_update_dialog_title">Opdatering blokeret</string>
<string name="blocked_update_dialog_message">Denne opdatering kan ikke installeres over opdatering-app\'en. Læs venligst <xliff:g id="info_url">%1$s</xliff:g> for mere information.</string>
<string name="export_channel_title">Eksport fuldførelse</string>
<string name="new_updates_channel_title">Nye opdateringer</string>
<string name="ongoing_channel_title">Igangværende Downloads</string>
<string name="update_failed_channel_title">Opdatering fejlede</string>
<string name="info_dialog_title">Vidste du?</string>
<string name="info_dialog_message">LineageOS opdateringer er komplette installationspakker. Det betyder, at du altid kun kan installere den seneste opdatering, selv om du har sprunget nogle over!</string>
<string name="info_dialog_ok">Tak for info!</string>
<string name="local_update_import">Lokal opdatering</string>
<string name="local_update_import_progress">Importerer lokal opdatering\u2026</string>
<string name="local_update_import_success">%1$s er blevet importeret. Vil du installere det?</string>
<string name="local_update_import_failure">Import af lokal opdatering mislykkedes</string>
<string name="local_update_import_install">Installér</string>
<string name="local_update_name">Lokal opdatering</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Updater</string>
<string name="display_name">Updater</string>
<string name="verification_failed_notification">Überprüfung fehlgeschlagen</string>
<string name="verifying_download_notification">Update wird geprüft</string>
<string name="downloading_notification">Wird heruntergeladen</string>
<string name="download_paused_notification">Herunterladen pausiert</string>
<string name="download_paused_error_notification">Fehler beim Herunterladen</string>
<string name="download_completed_notification">Herunterladen abgeschlossen</string>
<string name="download_starting_notification">Herunterladen wird gestartet</string>
<string name="update_failed_notification">Update fehlgeschlagen</string>
<string name="installation_suspended_notification">Installation unterbrechen</string>
<string name="new_updates_found_title">Neue Updates</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pause</string>
<string name="resume_button">Fortsetzen</string>
<string name="suspend_button">Unterbrechen</string>
<string name="installing_update">Update-Paket wird installiert</string>
<string name="installing_update_error">Installationsfehler</string>
<string name="installing_update_finished">Update installiert</string>
<string name="finalizing_package">Die Paketinstallation wird abgeschlossen</string>
<string name="preparing_ota_first_boot">Erster Start wird vorbereitet</string>
<string name="dialog_prepare_zip_message">Update wird vorbereitet</string>
<string name="dialog_battery_low_title">Niedriger Akkustand</string>
<string name="dialog_battery_low_message_pct">Dein Akkustand ist zu niedrig. Es werden mindestens <xliff:g id="percent_discharging">%1$d</xliff:g>%% Restkapazität (oder <xliff:g id="percent_charging">%2$d</xliff:g>%% mit angeschlossenem Ladegerät) benötigt, um fortzufahren.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Bitte führe die folgenden Befehle aus und versuche anschließend das Update erneut durchzuführen:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Update kann nicht installiert werden, wenn OverlayFS eingebunden ist</string>
<string name="reboot">Neustart</string>
<string name="menu_refresh">Aktualisieren</string>
<string name="menu_preferences">Einstellungen</string>
<string name="menu_auto_updates_check">Automatisch nach Updates suchen</string>
<string name="menu_auto_updates_check_interval_daily">Einmal am Tag</string>
<string name="menu_auto_updates_check_interval_weekly">Einmal pro Woche</string>
<string name="menu_auto_updates_check_interval_monthly">Einmal pro Monat</string>
<string name="menu_auto_updates_check_interval_never">Niemals</string>
<string name="menu_auto_delete_updates">Updates nach Installation löschen</string>
<string name="menu_delete_update">Löschen</string>
<string name="menu_copy_url">URL in Zwischenablage kopieren</string>
<string name="menu_export_update">Update exportieren</string>
<string name="menu_show_changelog">Changelog anzeigen</string>
<string name="menu_ab_perf_mode">Updateprozess priorisieren</string>
<string name="menu_update_recovery">Recovery aktualisieren</string>
<string name="toast_forced_update_recovery">Es ist nicht möglich, die Updates vom Lineage-Recovery auf diesem Gerät zu deaktivieren.</string>
<string name="snack_updates_found">Neue Updates gefunden</string>
<string name="snack_no_updates_found">Keine neuen Updates gefunden</string>
<string name="snack_updates_check_failed">Die Suche nach Updates ist fehlgeschlagen. Bitte überprüfe die Internetverbindung und versuche es später erneut.</string>
<string name="snack_download_failed">Das Herunterladen ist fehlgeschlagen. Bitte überpüfe die Internetverbindung und versuche es später erneut.</string>
<string name="snack_download_verification_failed">Die Update-Überprüfung ist fehlgeschlagen.</string>
<string name="snack_download_verified">Herunterladen abgeschlossen.</string>
<string name="snack_update_not_installable">Dieses Update kann nicht auf die bestehende Installation angewendet werden.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Zuletzt geprüft: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> von <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> von <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Update wird geprüft</string>
<string name="list_no_updates">Keine neuen Updates gefunden. Um manuell nach neuen Updates zu suchen, verwende die Schaltfläche \"Aktualisieren\".</string>
<string name="action_download">Herunterladen</string>
<string name="action_pause">Anhalten</string>
<string name="action_resume">Fortsetzen</string>
<string name="action_install">Installieren</string>
<string name="action_info">Information</string>
<string name="action_delete">Löschen</string>
<string name="action_cancel">Abbrechen</string>
<string name="confirm_delete_dialog_title">Datei löschen</string>
<string name="confirm_delete_dialog_message">Soll die ausgewählte Update-Datei gelöscht werden?</string>
<string name="apply_update_dialog_title">Update installieren</string>
<string name="apply_update_dialog_message">Bereit zur Installation von <xliff:g id="update_name">%1$s</xliff:g>\n\nWenn du <xliff:g id="ok">%2$s</xliff:g> drückst, wird das Gerät im Recovery-Modus gestartet, um das Update durchzuführen.\n\nHinweis: Diese Funktion erfordert ein kompatibles Recovery-System, anderenfalls muss das Update manuell installiert werden.</string>
<string name="apply_update_dialog_message_ab">Bereit zur Installation von <xliff:g id="update_name">%1$s</xliff:g>\n\nWenn du <xliff:g id="ok">%2$s drückst</xliff:g>, beginnt das Gerät im Hintergrund mit der Installation.\n\nSobald diese abgeschlossen ist, wirst du zum Neustart aufgefordert.</string>
<string name="cancel_installation_dialog_message">Installation abbrechen?</string>
<string name="label_download_url">Download URL</string>
<string name="toast_download_url_copied">URL wurde kopiert</string>
<string name="dialog_export_title">Update wird exportiert</string>
<string name="notification_export_success">Update wurde exportiert</string>
<string name="notification_export_fail">Fehler beim Export</string>
<string name="toast_already_exporting">Update wird bereits exportiert</string>
<string name="toast_export_started">Export gestartet</string>
<plurals name="eta_seconds">
<item quantity="one">noch 1 Sekunde</item>
<item quantity="other">noch <xliff:g id="count">%d</xliff:g> Sekunden</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">noch 1 Minute</item>
<item quantity="other">noch <xliff:g id="count">%d</xliff:g> Minuten</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">noch 1 Stunde</item>
<item quantity="other">noch <xliff:g id="count">%d</xliff:g> Stunden</item>
</plurals>
<string name="update_over_metered_network_title">Achtung</string>
<string name="update_over_metered_network_message">Du bist dabei ein Software-Update über ein getaktetes Netzwerk herunterzuladen, was zu einem hohen Datenverbrauch führen kann. Möchtest du fortfahren?</string>
<string name="checkbox_metered_network_warning">Nicht wieder anzeigen</string>
<string name="menu_metered_network_warning">Warnen bei getakteter Verbindung</string>
<string name="blocked_update_dialog_title">Update blockiert</string>
<string name="blocked_update_dialog_message">Dieses Update kann mit der Updater-App nicht installiert werden. Für weitere Informationen lies bitte <xliff:g id="info_url">%1$s </xliff:g>.</string>
<string name="export_channel_title">Export abgeschlossen</string>
<string name="new_updates_channel_title">Neue Updates</string>
<string name="ongoing_channel_title">Laufende Downloads</string>
<string name="update_failed_channel_title">Update fehlgeschlagen</string>
<string name="info_dialog_title">Schon gewusst?</string>
<string name="info_dialog_message">LineageOS-Updates sind vollständige Installationspakete. Das bedeutet, dass du immer nur das neueste Update installieren zu brauchst, auch wenn du zwischendurch welche übersprungen hast!</string>
<string name="info_dialog_ok">Danke für die Information!</string>
<string name="local_update_import">Lokales Update</string>
<string name="local_update_import_progress">Lokales Update wird importiert\u2026</string>
<string name="local_update_import_success">%1$s wurde importiert. Möchtest du es installieren?</string>
<string name="local_update_import_failure">Fehler beim Importieren des lokalen Updates</string>
<string name="local_update_import_install">Installieren</string>
<string name="local_update_name">Lokales Update</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Ενημερώσεις</string>
<string name="display_name">Ενημερώσεις</string>
<string name="verification_failed_notification">Αποτυχία επαλήθευσης</string>
<string name="verifying_download_notification">Επαλήθευση ενημέρωσης</string>
<string name="downloading_notification">Λήψη</string>
<string name="download_paused_notification">Λήψη σε παύση</string>
<string name="download_paused_error_notification">Σφάλμα λήψης</string>
<string name="download_completed_notification">Η λήψη ολοκληρώθηκε</string>
<string name="download_starting_notification">Έναρξη λήψης</string>
<string name="update_failed_notification">Η ενημέρωση απέτυχε</string>
<string name="installation_suspended_notification">Η εγκατάσταση έχει ανασταλεί</string>
<string name="new_updates_found_title">Νέες ενημερώσεις</string>
<string name="text_download_speed">%1$s, %2$s/δ</string>
<string name="pause_button">Παύση</string>
<string name="resume_button">Συνέχιση</string>
<string name="suspend_button">Αναστολή</string>
<string name="installing_update">Εγκατάσταση πακέτου ενημέρωσης</string>
<string name="installing_update_error">Σφάλμα εγκατάστασης</string>
<string name="installing_update_finished">Η ενημέρωση εγκαταστάθηκε</string>
<string name="finalizing_package">Ολοκλήρωση της εγκατάστασης του πακέτου</string>
<string name="preparing_ota_first_boot">Προετοιμασία για την πρώτη εκκίνηση</string>
<string name="dialog_prepare_zip_message">Προκαταρκτική προετοιμασία ενημέρωσης</string>
<string name="dialog_battery_low_title">Χαμηλή μπαταρία</string>
<string name="dialog_battery_low_message_pct">Η στάθμη της μπαταρίας είναι πολύ χαμηλή, χρειάζεστε τουλάχιστον <xliff:g id="percent_discharging">%1$d</xliff:g>%% της μπαταρίας για να συνεχίσετε ή <xliff:g id="percent_charging">%2$d</xliff:g>%% κατά την φόρτιση.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Παρακαλώ εκτελέστε τις ακόλουθες εντολές και δοκιμάστε ξανά την ενημέρωση:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Αδυναμία εγκατάστασης ενημέρωσης με το OverlayFS προσαρτημένο</string>
<string name="reboot">Επανεκκίνηση</string>
<string name="menu_refresh">Ανανέωση</string>
<string name="menu_preferences">Προτιμήσεις</string>
<string name="menu_auto_updates_check">Αυτόματος έλεγχος ενημερώσεων</string>
<string name="menu_auto_updates_check_interval_daily">Μία φορά την ημέρα</string>
<string name="menu_auto_updates_check_interval_weekly">Μία φορά την εβδομάδα</string>
<string name="menu_auto_updates_check_interval_monthly">Μία φορά το μήνα</string>
<string name="menu_auto_updates_check_interval_never">Ποτέ</string>
<string name="menu_auto_delete_updates">Διαγραφή αρχείου μετά την ενημέρωση</string>
<string name="menu_delete_update">Διαγραφή</string>
<string name="menu_copy_url">Αντιγραφή URL</string>
<string name="menu_export_update">Εξαγωγή ενημέρωσης</string>
<string name="menu_show_changelog">Εμφάνιση αλλαγών</string>
<string name="menu_ab_perf_mode">Επιτάχυνση διαδικασίας ενημέρωσης</string>
<string name="menu_update_recovery">Ενημέρωση recovery</string>
<string name="toast_forced_update_recovery">Είναι αδύνατο να απενεργοποιήσετε τις ενημερώσεις Lineage Recovery σε αυτή τη συσκευή.</string>
<string name="snack_updates_found">Βρέθηκαν νέες ενημερώσεις</string>
<string name="snack_no_updates_found">Δεν βρέθηκαν νέες ενημερώσεις</string>
<string name="snack_updates_check_failed">Ο έλεγχος για ενημερώσεις απέτυχε. Παρακαλώ ελέγξτε την σύνδεσή σας στο διαδίκτυο και προσπαθήστε αργότερα.</string>
<string name="snack_download_failed">Η λήψη απέτυχε. Παρακαλούμε ελέγξτε την σύνδεση σας στο διαδίκτυο και προσπαθήστε αργότερα.</string>
<string name="snack_download_verification_failed">Αποτυχία επαλήθευσης της ενημέρωσης.</string>
<string name="snack_download_verified">Η λήψη ολοκληρώθηκε.</string>
<string name="snack_update_not_installable">Αυτή η ενημέρωση δεν μπορεί να εγκατασταθεί πάνω από την τρέχουσα έκδοση.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Τελευταίος έλεγχος: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> από <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> από <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Επαλήθευση ενημέρωσης</string>
<string name="list_no_updates">Δεν βρέθηκαν νέες ενημερώσεις. Για να ελέγξετε χειροκίνητα για νέες ενημερώσεις, χρησιμοποιήστε το πλήκτρο Ανανέωσης.</string>
<string name="action_download">Λήψη</string>
<string name="action_pause">Παύση</string>
<string name="action_resume">Συνέχιση</string>
<string name="action_install">Εγκατάσταση</string>
<string name="action_info">Πληροφορίες</string>
<string name="action_delete">Διαγραφή</string>
<string name="action_cancel">Ακύρωση</string>
<string name="confirm_delete_dialog_title">Διαγραφή αρχείου</string>
<string name="confirm_delete_dialog_message">Διαγραφή του επιλεγμένου αρχείου ενημέρωσης;</string>
<string name="apply_update_dialog_title">Εφαρμογή ενημέρωσης</string>
<string name="apply_update_dialog_message">Πρόκειται να εγκαταστήσετε το <xliff:g id="update_name">%1$s</xliff:g>.\n\nΑν πατήσετε <xliff:g id="ok">%2$s</xliff:g>, η συσκευή θα κάνει επανεκκίνηση σε λειτουργία recovery για να εγκατασταθεί η ενημέρωση.\n\nΣημείωση: Αυτή η λειτουργία απαιτεί μια συμβατή recovery αλλιώς η ενημέρωση θα πρέπει να εγκατασταθεί χειροκίνητα.</string>
<string name="apply_update_dialog_message_ab">Πρόκειται να εγκαταστήσετε το <xliff:g id="update_name">%1$s</xliff:g>.\n\nΕάν πατήσετε <xliff:g id="ok">%2$s</xliff:g>, η συσκευή θα ξεκινήσει την εγκατάσταση στο παρασκήνιο.\n\nΌταν ολοκληρωθεί, θα σας ζητηθεί να κάνετε επανεκκίνηση.</string>
<string name="cancel_installation_dialog_message">Ακύρωση της εγκατάστασης;</string>
<string name="label_download_url">Λήψη συνδέσμου</string>
<string name="toast_download_url_copied">Ο σύνδεσμος αντιγράφηκε</string>
<string name="dialog_export_title">Εξαγωγή ενημέρωσης</string>
<string name="notification_export_success">Η ενημέρωση εξάχθηκε</string>
<string name="notification_export_fail">Σφάλμα εξαγωγής</string>
<string name="toast_already_exporting">Εξάγεται ήδη μία ενημέρωση</string>
<string name="toast_export_started">Η εξαγωγή ξεκίνησε</string>
<plurals name="eta_seconds">
<item quantity="one">απομένει 1 δευτερόλεπτο</item>
<item quantity="other">απομένουν <xliff:g id="count">%d</xliff:g> δευτερόλεπτα</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">απομένει 1 λεπτό</item>
<item quantity="other">απομένουν <xliff:g id="count">%d</xliff:g> λεπτά</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">απομένει 1 ώρα</item>
<item quantity="other">απομένουν <xliff:g id="count">%d</xliff:g> ώρες</item>
</plurals>
<string name="update_over_metered_network_title">Προσοχή</string>
<string name="update_over_metered_network_message">Είστε έτοιμοι να κατεβάσετε ένα πακέτο ενημέρωσης χρησιμοποιώντας ένα δίκτυο με ογκοχρέωση δεδομένων το οποίο είναι πιθανό να προκαλέσει υψηλή χρήση δεδομένων. Θα θέλατε να συνεχίσετε;</string>
<string name="checkbox_metered_network_warning">Να μην εμφανιστεί ξανά</string>
<string name="menu_metered_network_warning">Προειδοποίηση ογκοχρέωσης δικτύου</string>
<string name="blocked_update_dialog_title">Η ενημέρωση μπλοκαρίστηκε</string>
<string name="blocked_update_dialog_message">Αυτή η ενημέρωση δεν μπορεί να εγκατασταθεί χρησιμοποιώντας την εφαρμογή ενημέρωσης. Παρακαλούμε διαβάστε το <xliff:g id="info_url">%1$s </xliff:g> για περισσότερες πληροφορίες.</string>
<string name="export_channel_title">Ολοκλήρωση εξαγωγής</string>
<string name="new_updates_channel_title">Νέες ενημερώσεις</string>
<string name="ongoing_channel_title">Λήψεις σε εξέλιξη</string>
<string name="update_failed_channel_title">Η ενημέρωση απέτυχε</string>
<string name="info_dialog_title">Το γνωρίζατε;</string>
<string name="info_dialog_message">Οι ενημερώσεις LineageOS είναι πλήρη πακέτα εγκατάστασης. Αυτό σημαίνει ότι μπορείτε πάντα να εγκαταστήσετε μόνο την πιο πρόσφατη ενημέρωση, ακόμα κι αν παραλείψατε κάποια ενδιάμεσα!</string>
<string name="info_dialog_ok">Ευχαριστώ για τις πληροφορίες!</string>
<string name="local_update_import">Τοπική ενημέρωση</string>
<string name="local_update_import_progress">Εισαγωγή τοπικής ενημέρωσης\u2026</string>
<string name="local_update_import_success">%1$s έχει εισαχθεί. Θέλετε να τo εγκαταστήσετε;</string>
<string name="local_update_import_failure">Αποτυχία εισαγωγής τοπικής ενημέρωσης</string>
<string name="local_update_import_install">Εγκατάσταση</string>
<string name="local_update_name">Τοπική ενημέρωση</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Updater</string>
<string name="display_name">Updater</string>
<string name="verification_failed_notification">Verification failed</string>
<string name="verifying_download_notification">Verifying update</string>
<string name="downloading_notification">Downloading</string>
<string name="download_paused_notification">Download paused</string>
<string name="download_paused_error_notification">Download error</string>
<string name="download_completed_notification">Download completed</string>
<string name="download_starting_notification">Starting download</string>
<string name="update_failed_notification">Update failed</string>
<string name="installation_suspended_notification">Installation suspended</string>
<string name="new_updates_found_title">New updates</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pause</string>
<string name="resume_button">Resume</string>
<string name="suspend_button">Suspend</string>
<string name="installing_update">Installing update package</string>
<string name="installing_update_error">Install error</string>
<string name="installing_update_finished">Update installed</string>
<string name="finalizing_package">Finalising package installation</string>
<string name="preparing_ota_first_boot">Preparing for first boot</string>
<string name="dialog_prepare_zip_message">Preliminary update preparation</string>
<string name="dialog_battery_low_title">Low battery</string>
<string name="dialog_battery_low_message_pct">The battery level is too low, you need at least <xliff:g id="percent_discharging">%1$d</xliff:g>%% of the battery to continue, <xliff:g id="percent_charging">%2$d</xliff:g>%% if charging.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Please run the following commands and retry the update:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Cannot install update with OverlayFS mounted</string>
<string name="reboot">Reboot</string>
<string name="menu_refresh">Refresh</string>
<string name="menu_preferences">Preferences</string>
<string name="menu_auto_updates_check">Auto updates check</string>
<string name="menu_auto_updates_check_interval_daily">Once a day</string>
<string name="menu_auto_updates_check_interval_weekly">Once a week</string>
<string name="menu_auto_updates_check_interval_monthly">Once a month</string>
<string name="menu_auto_updates_check_interval_never">Never</string>
<string name="menu_auto_delete_updates">Delete updates when installed</string>
<string name="menu_delete_update">Delete</string>
<string name="menu_copy_url">Copy URL</string>
<string name="menu_export_update">Export update</string>
<string name="menu_show_changelog">Show changelog</string>
<string name="menu_ab_perf_mode">Prioritise update process</string>
<string name="menu_update_recovery">Update recovery</string>
<string name="toast_forced_update_recovery">It is impossible to disable Lineage Recovery updates on this device.</string>
<string name="snack_updates_found">New updates found</string>
<string name="snack_no_updates_found">No new updates found</string>
<string name="snack_updates_check_failed">The update check failed. Please check your Internet connection and try again later.</string>
<string name="snack_download_failed">The download failed. Please check your internet connection and try again later.</string>
<string name="snack_download_verification_failed">The update verification failed.</string>
<string name="snack_download_verified">Download completed.</string>
<string name="snack_update_not_installable">This update can\'t be installed on top of the current build.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Last checked: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verifying update</string>
<string name="list_no_updates">No new updates found. To manually check for new updates, use the Refresh button.</string>
<string name="action_download">Download</string>
<string name="action_pause">Pause</string>
<string name="action_resume">Resume</string>
<string name="action_install">Install</string>
<string name="action_info">Info</string>
<string name="action_delete">Delete</string>
<string name="action_cancel">Cancel</string>
<string name="confirm_delete_dialog_title">Delete file</string>
<string name="confirm_delete_dialog_message">Delete the selected update file?</string>
<string name="apply_update_dialog_title">Apply update</string>
<string name="apply_update_dialog_message">You are about to install <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will restart itself in recovery mode to install the update.\n\nNote: This feature requires a compatible Recovery or updates will need to be installed manually.</string>
<string name="apply_update_dialog_message_ab">You are about to install <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will begin installing in the background.\n\nOnce completed, you will be prompted to reboot.</string>
<string name="cancel_installation_dialog_message">Cancel the installation?</string>
<string name="label_download_url">Download URL</string>
<string name="toast_download_url_copied">URL Copied</string>
<string name="dialog_export_title">Exporting update</string>
<string name="notification_export_success">Update exported</string>
<string name="notification_export_fail">Export error</string>
<string name="toast_already_exporting">Already exporting an update</string>
<string name="toast_export_started">Export started</string>
<plurals name="eta_seconds">
<item quantity="one">1 second left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> seconds left</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minute left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutes left</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 hour left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> hours left</item>
</plurals>
<string name="update_over_metered_network_title">Warning</string>
<string name="update_over_metered_network_message">You\'re about to download an update package over a metered network which is likely going to cause high data usage. Would you like to proceed?</string>
<string name="checkbox_metered_network_warning">Do not show again</string>
<string name="menu_metered_network_warning">Metered network warning</string>
<string name="blocked_update_dialog_title">Update blocked</string>
<string name="blocked_update_dialog_message">This update cannot be installed using the updater app. Please read <xliff:g id="info_url">%1$s</xliff:g> for more information.</string>
<string name="export_channel_title">Export completion</string>
<string name="new_updates_channel_title">New updates</string>
<string name="ongoing_channel_title">Ongoing downloads</string>
<string name="update_failed_channel_title">Update failed</string>
<string name="info_dialog_title">Did you know?</string>
<string name="info_dialog_message">LineageOS updates are full installation packages. That means you can always install only the latest update, even if you skipped some in between!</string>
<string name="info_dialog_ok">Thanks for the info!</string>
<string name="local_update_import">Local update</string>
<string name="local_update_import_progress">Importing local update\u2026</string>
<string name="local_update_import_success">%1$s has been imported. Do you want to install it?</string>
<string name="local_update_import_failure">Failed to import local update</string>
<string name="local_update_import_install">Install</string>
<string name="local_update_name">Local update</string>
</resources>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 The LineageOS Project
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,17 +17,6 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Updater</string>
<string name="display_name">Updater</string>
<!-- Directory where the update files will be downloaded and stored.
WARNING: The application can and will delete any unknown file. -->
<string name="download_path" translatable="false">/data/lineageos_updates/</string>
<!-- Directory where the downloads will be exported to.
The path is relative to the root of the external storage.-->
<string name="export_path" translatable="false">LineageOS updates/</string>
<string name="conf_update_server_url_def" translatable="false">https://download.lineageos.org/api</string>
<string name="verification_failed_notification">Verification failed</string>
<string name="verifying_download_notification">Verifying update</string>
<string name="downloading_notification">Downloading</string>
@@ -35,96 +24,108 @@
<string name="download_paused_error_notification">Download error</string>
<string name="download_completed_notification">Download completed</string>
<string name="download_starting_notification">Starting download</string>
<string name="update_failed_notification">Update failed</string>
<string name="installation_suspended_notification">Installation suspended</string>
<string name="new_updates_found_title">New updates</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pause</string>
<string name="resume_button">Resume</string>
<string name="suspend_button">Suspend</string>
<string name="installing_update">Installing update package</string>
<string name="installing_update_error">Install error</string>
<string name="installing_update_finished">Update installed</string>
<string name="finalizing_package">Finalizing package installation</string>
<string name="preparing_ota_first_boot">Preparing for first boot</string>
<string name="dialog_prepare_zip_message">Preliminary update preparation</string>
<string name="notification_prepare_zip_error_title">Could not prepare update</string>
<string name="dialog_battery_low_title">Low battery</string>
<string name="dialog_battery_low_message_pct">The battery level is too low, you need at least <xliff:g id="percent_discharging">%1$d</xliff:g>%% of the battery to continue, <xliff:g id="percent_charging">%2$d</xliff:g>%% if charging.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Please run the following commands and retry the update:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Cannot install update with OverlayFS mounted</string>
<string name="reboot">Reboot</string>
<string name="menu_refresh">Refresh</string>
<string name="menu_preferences">Preferences</string>
<string name="menu_auto_updates_check">Auto updates check</string>
<string name="menu_auto_updates_check_interval_daily">Once a day</string>
<string name="menu_auto_updates_check_interval_weekly">Once a week</string>
<string name="menu_auto_updates_check_interval_monthly">Once a month</string>
<string name="menu_auto_updates_check_interval_never">Never</string>
<string name="menu_auto_delete_updates">Delete updates when installed</string>
<string name="menu_delete_update">Delete</string>
<string name="menu_copy_url">Copy URL</string>
<string name="menu_export_update">Export update</string>
<string name="dialog_checking_for_updates">Checking for updates</string>
<string name="menu_show_changelog">Show changelog</string>
<string name="menu_ab_perf_mode">Prioritize update process</string>
<string name="menu_update_recovery">Update recovery</string>
<string name="toast_forced_update_recovery">It is impossible to disable Lineage Recovery updates on this device.</string>
<string name="snack_updates_found">New updates found</string>
<string name="snack_no_updates_found">No new updates found</string>
<string name="snack_updates_check_failed">The update check failed. Please check your internet connection and try again later.</string>
<string name="snack_download_failed">The download failed. Please check your internet connection and try again later.</string>
<string name="snack_download_verification_failed">The update verification failed.</string>
<string name="snack_download_verified">Download completed.</string>
<string name="snack_update_not_installable">This update can\'t be installed on top of the current build.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Last checked: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> - <xliff:g id="duration" example="3 minutes">%3$s</xliff:g> left</string>
<string name="list_installing_update">Installing update</string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verifying update</string>
<string name="list_no_updates">No new updates found. To manually check for new updates, use the Refresh button.</string>
<string name="action_description_download">Download</string>
<string name="action_description_pause">Pause download</string>
<string name="action_description_resume">Resume download</string>
<string name="action_description_install">Install update</string>
<string name="action_description_info">Show information</string>
<string name="action_description_delete">Delete update</string>
<string name="action_download">Download</string>
<string name="action_pause">Pause</string>
<string name="action_resume">Resume</string>
<string name="action_install">Install</string>
<string name="action_info">Info</string>
<string name="action_delete">Delete</string>
<string name="action_cancel">Cancel</string>
<string name="confirm_delete_dialog_title">Delete file</string>
<string name="confirm_delete_dialog_message">Delete the selected update file?</string>
<string name="apply_update_dialog_title">Apply update</string>
<string name="apply_update_dialog_message">You are about to upgrade to <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will restart itself in recovery mode to install the update.\n\nNote: This feature requires a compatible Recovery or updates will need to be installed manually.</string>
<string name="apply_update_dialog_message_ab">You are about to upgrade to <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will begin installing in the background.\n\nOnce completed, you will be prompted to reboot.</string>
<string name="apply_update_dialog_message">You are about to install <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will restart itself in recovery mode to install the update.\n\nNote: This feature requires a compatible Recovery or updates will need to be installed manually.</string>
<string name="apply_update_dialog_message_ab">You are about to install <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will begin installing in the background.\n\nOnce completed, you will be prompted to reboot.</string>
<string name="cancel_installation_dialog_message">Cancel the installation?</string>
<string name="label_download_url">Download URL</string>
<string name="toast_download_url_copied">URL Copied</string>
<string name="snack_export_failed">Could not export download</string>
<string name="dialog_export_title">Exporting update</string>
<string name="dialog_export_message">Exporting update as <xliff:g id="filename">%1$s</xliff:g> into the external storage.</string>
<string name="notification_export_success">Update exported</string>
<string name="notification_export_fail">Export error</string>
<plurals name="duration_seconds">
<item quantity="one">1 second</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> seconds</item>
<string name="toast_already_exporting">Already exporting an update</string>
<string name="toast_export_started">Export started</string>
<plurals name="eta_seconds">
<item quantity="one">1 second left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> seconds left</item>
</plurals>
<plurals name="duration_minutes">
<item quantity="one">1 minute</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutes</item>
<plurals name="eta_minutes">
<item quantity="one">1 minute left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutes left</item>
</plurals>
<plurals name="duration_hours">
<item quantity="one">1 hour</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> hours</item>
<plurals name="eta_hours">
<item quantity="one">1 hour left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> hours left</item>
</plurals>
<string name="update_on_mobile_data_title">Warning</string>
<string name="update_on_mobile_data_message">You\'re about to download an update package using mobile data which is likely going to cause high data usage. Would you like to proceed?</string>
<string name="checkbox_mobile_data_warning">Do not show again</string>
<string name="menu_mobile_data_warning">Mobile data warning</string>
<string name="update_over_metered_network_title">Warning</string>
<string name="update_over_metered_network_message">You\'re about to download an update package over a metered network which is likely going to cause high data usage. Would you like to proceed?</string>
<string name="checkbox_metered_network_warning">Do not show again</string>
<string name="menu_metered_network_warning">Metered network warning</string>
<string name="blocked_update_dialog_title">Update blocked</string>
<string name="blocked_update_dialog_message">This update cannot be installed using the updater app. Please read <xliff:g id="info_url">%1$s</xliff:g> for more information.</string>
<string name="blocked_update_info_url" translatable="false">http://wiki.lineageos.org/upgrading.html</string>
<string name="export_channel_title">Export completion</string>
<string name="new_updates_channel_title">New updates</string>
<string name="ongoing_channel_title">Ongoing downloads</string>
<string name="update_failed_channel_title">Update failed</string>
<string name="info_dialog_title">Did you know?</string>
<string name="info_dialog_message">LineageOS updates are full installation packages. That means you can always install only the latest update, even if you skipped some in between!</string>
<string name="info_dialog_ok">Thanks for the info!</string>
<string name="local_update_import">Local update</string>
<string name="local_update_import_progress">Importing local update\u2026</string>
<string name="local_update_import_success">%1$s has been imported. Do you want to install it?</string>
<string name="local_update_import_failure">Failed to import local update</string>
<string name="local_update_import_install">Install</string>
<string name="local_update_name">Local update</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Updater</string>
<string name="display_name">Updater</string>
<string name="verification_failed_notification">Verification failed</string>
<string name="verifying_download_notification">Verifying update</string>
<string name="downloading_notification">Downloading</string>
<string name="download_paused_notification">Download paused</string>
<string name="download_paused_error_notification">Download error</string>
<string name="download_completed_notification">Download completed</string>
<string name="download_starting_notification">Starting download</string>
<string name="update_failed_notification">Update failed</string>
<string name="installation_suspended_notification">Installation suspended</string>
<string name="new_updates_found_title">New updates</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pause</string>
<string name="resume_button">Resume</string>
<string name="suspend_button">Suspend</string>
<string name="installing_update">Installing update package</string>
<string name="installing_update_error">Install error</string>
<string name="installing_update_finished">Update installed</string>
<string name="finalizing_package">Finalising package installation</string>
<string name="preparing_ota_first_boot">Preparing for first boot</string>
<string name="dialog_prepare_zip_message">Preliminary update preparation</string>
<string name="dialog_battery_low_title">Low battery</string>
<string name="dialog_battery_low_message_pct">The battery level is too low, you need at least <xliff:g id="percent_discharging">%1$d</xliff:g>%% of the battery to continue, <xliff:g id="percent_charging">%2$d</xliff:g>%% if charging.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Please run the following commands and retry the update:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Cannot install update with OverlayFS mounted</string>
<string name="reboot">Reboot</string>
<string name="menu_refresh">Refresh</string>
<string name="menu_preferences">Preferences</string>
<string name="menu_auto_updates_check">Auto updates check</string>
<string name="menu_auto_updates_check_interval_daily">Once a day</string>
<string name="menu_auto_updates_check_interval_weekly">Once a week</string>
<string name="menu_auto_updates_check_interval_monthly">Once a month</string>
<string name="menu_auto_updates_check_interval_never">Never</string>
<string name="menu_auto_delete_updates">Delete updates when installed</string>
<string name="menu_delete_update">Delete</string>
<string name="menu_copy_url">Copy URL</string>
<string name="menu_export_update">Export update</string>
<string name="menu_show_changelog">Show changelog</string>
<string name="menu_ab_perf_mode">Prioritise update process</string>
<string name="menu_update_recovery">Update recovery</string>
<string name="toast_forced_update_recovery">It is impossible to disable Lineage Recovery updates on this device.</string>
<string name="snack_updates_found">New updates found</string>
<string name="snack_no_updates_found">No new updates found</string>
<string name="snack_updates_check_failed">The update check failed. Please check your internet connection and try again later.</string>
<string name="snack_download_failed">The download failed. Please check your internet connection and try again later.</string>
<string name="snack_download_verification_failed">The update verification failed.</string>
<string name="snack_download_verified">Download completed.</string>
<string name="snack_update_not_installable">This update can\'t be installed on top of the current build.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Last checked: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verifying update</string>
<string name="list_no_updates">No new updates found. To manually check for new updates, use the Refresh button.</string>
<string name="action_download">Download</string>
<string name="action_pause">Pause</string>
<string name="action_resume">Resume</string>
<string name="action_install">Install</string>
<string name="action_info">Info</string>
<string name="action_delete">Delete</string>
<string name="action_cancel">Cancel</string>
<string name="confirm_delete_dialog_title">Delete file</string>
<string name="confirm_delete_dialog_message">Delete the selected update file?</string>
<string name="apply_update_dialog_title">Apply update</string>
<string name="apply_update_dialog_message">You are about to install <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will restart itself in recovery mode to install the update.\n\nNote: This feature requires a compatible Recovery or updates will need to be installed manually.</string>
<string name="apply_update_dialog_message_ab">You are about to install <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will begin installing in the background.\n\nOnce completed, you will be prompted to reboot.</string>
<string name="cancel_installation_dialog_message">Cancel the installation?</string>
<string name="label_download_url">Download URL</string>
<string name="toast_download_url_copied">URL Copied</string>
<string name="dialog_export_title">Exporting update</string>
<string name="notification_export_success">Update exported</string>
<string name="notification_export_fail">Export error</string>
<string name="toast_already_exporting">Already exporting an update</string>
<string name="toast_export_started">Export started</string>
<plurals name="eta_seconds">
<item quantity="one">1 second left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> seconds left</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minute left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutes left</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 hour left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> hours left</item>
</plurals>
<string name="update_over_metered_network_title">Warning</string>
<string name="update_over_metered_network_message">You\'re about to download an update package over a metered network which is likely going to cause high data usage. Would you like to proceed?</string>
<string name="checkbox_metered_network_warning">Do not show again</string>
<string name="menu_metered_network_warning">Metered network warning</string>
<string name="blocked_update_dialog_title">Update blocked</string>
<string name="blocked_update_dialog_message">This update cannot be installed using the updater app. Please read <xliff:g id="info_url">%1$s</xliff:g> for more information.</string>
<string name="export_channel_title">Export completion</string>
<string name="new_updates_channel_title">New updates</string>
<string name="ongoing_channel_title">Ongoing downloads</string>
<string name="update_failed_channel_title">Update failed</string>
<string name="info_dialog_title">Did you know?</string>
<string name="info_dialog_message">LineageOS updates are full installation packages. That means you can always install only the latest update, even if you skipped some in between!</string>
<string name="info_dialog_ok">Thanks for the info!</string>
<string name="local_update_import">Local update</string>
<string name="local_update_import_progress">Importing local update\u2026</string>
<string name="local_update_import_success">%1$s has been imported. Do you want to install it?</string>
<string name="local_update_import_failure">Failed to import local update</string>
<string name="local_update_import_install">Install</string>
<string name="local_update_name">Local update</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Updater</string>
<string name="display_name">Updater</string>
<string name="verification_failed_notification">Verification failed</string>
<string name="verifying_download_notification">Verifying update</string>
<string name="downloading_notification">Downloading</string>
<string name="download_paused_notification">Download paused</string>
<string name="download_paused_error_notification">Download error</string>
<string name="download_completed_notification">Download completed</string>
<string name="download_starting_notification">Starting download</string>
<string name="update_failed_notification">Update failed</string>
<string name="installation_suspended_notification">Installation suspended</string>
<string name="new_updates_found_title">New updates</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pause</string>
<string name="resume_button">Resume</string>
<string name="suspend_button">Suspend</string>
<string name="installing_update">Installing update package</string>
<string name="installing_update_error">Install error</string>
<string name="installing_update_finished">Update installed</string>
<string name="finalizing_package">Finalising package installation</string>
<string name="preparing_ota_first_boot">Preparing for first boot</string>
<string name="dialog_prepare_zip_message">Preliminary update preparation</string>
<string name="dialog_battery_low_title">Low battery</string>
<string name="dialog_battery_low_message_pct">The battery level is too low, you need at least <xliff:g id="percent_discharging">%1$d</xliff:g>%% of the battery to continue, <xliff:g id="percent_charging">%2$d</xliff:g>%% if charging.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Please run the following commands and retry the update:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Cannot install update with OverlayFS mounted</string>
<string name="reboot">Reboot</string>
<string name="menu_refresh">Refresh</string>
<string name="menu_preferences">Preferences</string>
<string name="menu_auto_updates_check">Auto updates check</string>
<string name="menu_auto_updates_check_interval_daily">Once a day</string>
<string name="menu_auto_updates_check_interval_weekly">Once a week</string>
<string name="menu_auto_updates_check_interval_monthly">Once a month</string>
<string name="menu_auto_updates_check_interval_never">Never</string>
<string name="menu_auto_delete_updates">Delete updates when installed</string>
<string name="menu_delete_update">Delete</string>
<string name="menu_copy_url">Copy URL</string>
<string name="menu_export_update">Export update</string>
<string name="menu_show_changelog">Show changelog</string>
<string name="menu_ab_perf_mode">Prioritise update process</string>
<string name="menu_update_recovery">Update recovery</string>
<string name="toast_forced_update_recovery">It is impossible to disable Lineage Recovery updates on this device.</string>
<string name="snack_updates_found">New updates found</string>
<string name="snack_no_updates_found">No new updates found</string>
<string name="snack_updates_check_failed">The update check failed. Please check your internet connection and try again later.</string>
<string name="snack_download_failed">The download failed. Please check your internet connection and try again later.</string>
<string name="snack_download_verification_failed">The update verification failed.</string>
<string name="snack_download_verified">Download completed.</string>
<string name="snack_update_not_installable">This update can\'t be installed on top of the current build.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Last checked: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verifying update</string>
<string name="list_no_updates">No new updates found. To manually check for new updates, use the Refresh button.</string>
<string name="action_download">Download</string>
<string name="action_pause">Pause</string>
<string name="action_resume">Resume</string>
<string name="action_install">Install</string>
<string name="action_info">Info</string>
<string name="action_delete">Delete</string>
<string name="action_cancel">Cancel</string>
<string name="confirm_delete_dialog_title">Delete file</string>
<string name="confirm_delete_dialog_message">Delete the selected update file?</string>
<string name="apply_update_dialog_title">Apply update</string>
<string name="apply_update_dialog_message">You are about to install <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will restart itself in recovery mode to install the update.\n\nNote: This feature requires a compatible Recovery or updates will need to be installed manually.</string>
<string name="apply_update_dialog_message_ab">You are about to install <xliff:g id="update_name">%1$s</xliff:g>.\n\nIf you press <xliff:g id="ok">%2$s</xliff:g>, the device will begin installing in the background.\n\nOnce completed, you will be prompted to reboot.</string>
<string name="cancel_installation_dialog_message">Cancel the installation?</string>
<string name="label_download_url">Download URL</string>
<string name="toast_download_url_copied">URL Copied</string>
<string name="dialog_export_title">Exporting update</string>
<string name="notification_export_success">Update exported</string>
<string name="notification_export_fail">Export error</string>
<string name="toast_already_exporting">Already exporting an update</string>
<string name="toast_export_started">Export started</string>
<plurals name="eta_seconds">
<item quantity="one">1 second left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> seconds left</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minute left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutes left</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 hour left</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> hours left</item>
</plurals>
<string name="update_over_metered_network_title">Warning</string>
<string name="update_over_metered_network_message">You\'re about to download an update package over a metered network which is likely going to cause high data usage. Would you like to proceed?</string>
<string name="checkbox_metered_network_warning">Do not show again</string>
<string name="menu_metered_network_warning">Metered network warning</string>
<string name="blocked_update_dialog_title">Update blocked</string>
<string name="blocked_update_dialog_message">This update cannot be installed using the updater app. Please read <xliff:g id="info_url">%1$s</xliff:g> for more information.</string>
<string name="export_channel_title">Export completion</string>
<string name="new_updates_channel_title">New updates</string>
<string name="ongoing_channel_title">Ongoing downloads</string>
<string name="update_failed_channel_title">Update failed</string>
<string name="info_dialog_title">Did you know?</string>
<string name="info_dialog_message">LineageOS updates are full installation packages. That means you can always install only the latest update, even if you skipped some in between!</string>
<string name="info_dialog_ok">Thanks for the info!</string>
<string name="local_update_import">Local update</string>
<string name="local_update_import_progress">Importing local update\u2026</string>
<string name="local_update_import_success">%1$s has been imported. Do you want to install it?</string>
<string name="local_update_import_failure">Failed to import local update</string>
<string name="local_update_import_install">Install</string>
<string name="local_update_name">Local update</string>
</resources>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="installation_suspended_notification">Instalación suspendida</string>
<string name="suspend_button">Suspender</string>
<string name="menu_auto_updates_check_interval_daily">Una vez al día</string>
<string name="menu_auto_updates_check_interval_weekly">Una vez a la semana</string>
<string name="menu_auto_updates_check_interval_monthly">Una vez al mes</string>
<string name="menu_auto_updates_check_interval_never">Nunca</string>
</resources>

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Actualizador</string>
<string name="display_name">Actualizador</string>
<string name="verification_failed_notification">Verificación fallida</string>
<string name="verifying_download_notification">Verificando actualización</string>
<string name="downloading_notification">Descargando</string>
<string name="download_paused_notification">Descarga pausada</string>
<string name="download_paused_error_notification">Error de descarga</string>
<string name="download_completed_notification">Descarga completada</string>
<string name="download_starting_notification">Iniciando descarga</string>
<string name="update_failed_notification">Error de actualización</string>
<string name="new_updates_found_title">Nuevas actualizaciones</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pausar</string>
<string name="resume_button">Reanudar</string>
<string name="suspend_button">Suspender</string>
<string name="installing_update">Instalando paquete de actualización</string>
<string name="installing_update_error">Error de instalación</string>
<string name="installing_update_finished">Actualización instalada</string>
<string name="finalizing_package">Finalizando instalación del paquete</string>
<string name="preparing_ota_first_boot">Preparando para el primer arranque</string>
<string name="dialog_prepare_zip_message">Preparación preliminar de la actualización</string>
<string name="dialog_battery_low_title">Batería baja</string>
<string name="dialog_battery_low_message_pct">El nivel de la batería es demasiado bajo, necesita al menos <xliff:g id="percent_discharging">%1$d</xliff:g>%% de batería para continuar, <xliff:g id="percent_charging">%2$d</xliff:g>%% si el dispositivo se está cargando.</string>
<string name="reboot">Reiniciar</string>
<string name="menu_refresh">Actualizar</string>
<string name="menu_preferences">Preferencias</string>
<string name="menu_auto_updates_check">Comprobación de actualizaciones automática</string>
<string name="menu_auto_updates_check_interval_daily">Una vez al día</string>
<string name="menu_auto_updates_check_interval_weekly">Semanal</string>
<string name="menu_auto_updates_check_interval_monthly">Mensual</string>
<string name="menu_auto_updates_check_interval_never">Nunca</string>
<string name="menu_auto_delete_updates">Borrar actualizaciones luego de instalar</string>
<string name="menu_delete_update">Borrar</string>
<string name="menu_copy_url">Copiar URL</string>
<string name="menu_export_update">Exportar actualización</string>
<string name="menu_show_changelog">Mostrar registro de cambios</string>
<string name="menu_ab_perf_mode">Priorizar el proceso de actualización</string>
<string name="snack_updates_found">Se encontraron nuevas actualizaciones</string>
<string name="snack_no_updates_found">No se encontraron nuevas actualizaciones</string>
<string name="snack_updates_check_failed">Error en la búsqueda de actualizaciones. Comprueba la conexión a Internet e intenta de nuevo más tarde.</string>
<string name="snack_download_failed">Descarga fallida. Comprueba la conexión a Internet e intenta de nuevo más tarde.</string>
<string name="snack_download_verification_failed">La verificación de la actualización falló.</string>
<string name="snack_download_verified">Descarga completada.</string>
<string name="snack_update_not_installable">Esta actualización no puede instalarse encima de la versión actual.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Última comprobación: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">Verificando actualización</string>
<string name="list_no_updates">Sin nuevas actualizaciones disponibles. Para comprobar manualmente, pulsa el botón «Actualizar».</string>
<string name="action_download">Descargar</string>
<string name="action_pause">Pausar</string>
<string name="action_resume">Reanudar</string>
<string name="action_install">Instalar</string>
<string name="action_info">Información</string>
<string name="action_delete">Borrar</string>
<string name="action_cancel">Cancelar</string>
<string name="confirm_delete_dialog_title">Borrar archivo</string>
<string name="confirm_delete_dialog_message">¿Borrar el archivo de actualización seleccionado?</string>
<string name="apply_update_dialog_title">Aplicar actualización</string>
<string name="cancel_installation_dialog_message">¿Cancelar instalación?</string>
<string name="label_download_url">URL de descarga</string>
<string name="toast_download_url_copied">URL copiada</string>
<string name="dialog_export_title">Exportando actualización</string>
<string name="notification_export_success">Actualización exportada</string>
<string name="notification_export_fail">Error de exportación</string>
<string name="toast_already_exporting">Ya se está exportando una actualización</string>
<plurals name="eta_seconds">
<item quantity="one">Queda 1 segundo</item>
<item quantity="other">Quedan <xliff:g id="count">%d</xliff:g> segundos</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">Queda 1 minuto</item>
<item quantity="other">Quedan <xliff:g id="count">%d</xliff:g> minutos</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">Queda 1 hora</item>
<item quantity="other">Quedan <xliff:g id="count">%d</xliff:g> horas</item>
</plurals>
<string name="update_over_metered_network_title">Advertencia</string>
<string name="checkbox_metered_network_warning">No mostrar de nuevo</string>
<string name="blocked_update_dialog_title">Actualización bloqueada</string>
<string name="blocked_update_dialog_message">Esta actualización no puede instalarse usando la aplicación «Actualizador». Lea <xliff:g id="info_url">%1$s</xliff:g> para más información.</string>
<string name="export_channel_title">Exportación finalizada</string>
<string name="new_updates_channel_title">Nuevas actualizaciones</string>
<string name="ongoing_channel_title">Descargas en curso</string>
<string name="update_failed_channel_title">Error de actualización</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Actualizador</string>
<string name="display_name">Actualizador</string>
<string name="verification_failed_notification">Verificación fallida</string>
<string name="verifying_download_notification">Verificando actualización</string>
<string name="downloading_notification">Descargando</string>
<string name="download_paused_notification">Descarga pausada</string>
<string name="download_paused_error_notification">Error de descarga</string>
<string name="download_completed_notification">Descarga completada</string>
<string name="download_starting_notification">Iniciando descarga</string>
<string name="update_failed_notification">Se produjo un error en la actualización</string>
<string name="installation_suspended_notification">Instalación suspendida</string>
<string name="new_updates_found_title">Nuevas actualizaciones</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pausar</string>
<string name="resume_button">Reanudar</string>
<string name="suspend_button">Suspender</string>
<string name="installing_update">Instalando paquete de actualización</string>
<string name="installing_update_error">Error de instalación</string>
<string name="installing_update_finished">Actualización instalada</string>
<string name="finalizing_package">Finalizando instalación del paquete</string>
<string name="preparing_ota_first_boot">Preparando para el primer arranque</string>
<string name="dialog_prepare_zip_message">Preparación preliminar de la actualización</string>
<string name="dialog_battery_low_title">Batería baja</string>
<string name="dialog_battery_low_message_pct">El nivel de la batería es demasiado bajo, se necesita al menos <xliff:g id="percent_discharging">%1$d</xliff:g>%% de batería para continuar, <xliff:g id="percent_charging">%2$d</xliff:g>%% si el dispositivo se está cargando.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Por favor, ejecuta los siguientes comandos y vuelve a intentar la actualización:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">No se puede instalar la actualización con OverlayFS montado</string>
<string name="reboot">Reiniciar</string>
<string name="menu_refresh">Actualizar</string>
<string name="menu_preferences">Preferencias</string>
<string name="menu_auto_updates_check">Comprobación de actualizaciones automática</string>
<string name="menu_auto_updates_check_interval_daily">Diaria</string>
<string name="menu_auto_updates_check_interval_weekly">Semanal</string>
<string name="menu_auto_updates_check_interval_monthly">Mensual</string>
<string name="menu_auto_updates_check_interval_never">Nunca</string>
<string name="menu_auto_delete_updates">Borrar actualizaciones luego de instalar</string>
<string name="menu_delete_update">Borrar</string>
<string name="menu_copy_url">Copiar URL</string>
<string name="menu_export_update">Exportar actualización</string>
<string name="menu_show_changelog">Mostrar registro de cambios</string>
<string name="menu_ab_perf_mode">Priorizar el proceso de actualización</string>
<string name="menu_update_recovery">Actualizar partición de recuperación (recovery)</string>
<string name="toast_forced_update_recovery">Es imposible desactivar en este dispositivo las actualizaciones del Modo de Recuperación («Recovery») de Lineage.</string>
<string name="snack_updates_found">Se encontraron nuevas actualizaciones</string>
<string name="snack_no_updates_found">No se encontraron nuevas actualizaciones</string>
<string name="snack_updates_check_failed">Error en la comprobación de actualizaciones. Por favor, verifique la conexión a Internet e inténtalo nuevamente.</string>
<string name="snack_download_failed">Descarga fallida. Compruebe la conexión a Internet e inténtelo nuevamente.</string>
<string name="snack_download_verification_failed">La verificación de la actualización falló.</string>
<string name="snack_download_verified">Descarga completada.</string>
<string name="snack_update_not_installable">Esta actualización no puede instalarse encima de la versión actual.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Última comprobación: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verificando actualización</string>
<string name="list_no_updates">Sin nuevas actualizaciones disponibles. Para comprobar manualmente, pulsa el botón «Actualizar».</string>
<string name="action_download">Descargar</string>
<string name="action_pause">Pausar</string>
<string name="action_resume">Reanudar</string>
<string name="action_install">Instalar</string>
<string name="action_info">Información</string>
<string name="action_delete">Borrar</string>
<string name="action_cancel">Cancelar</string>
<string name="confirm_delete_dialog_title">Borrar archivo</string>
<string name="confirm_delete_dialog_message">¿Borrar el archivo de actualización seleccionado?</string>
<string name="apply_update_dialog_title">Aplicar actualización</string>
<string name="apply_update_dialog_message">Estás a punto de instalar <xliff:g id="update_name">%1$s</xliff:g>.\n\nSi pulsas <xliff:g id="ok">%2$s</xliff:g>, el dispositivo se reiniciará en modo de recuperación para instalar la actualización.\n\nNota: esta característica requiere una partición de recuperación compatible o las actualizaciones tendrán que ser instaladas manualmente.</string>
<string name="apply_update_dialog_message_ab">Actualizarás a <xliff:g id="filename">%1$s</xliff:g>.\n\nAl pulsar en <xliff:g id="ok">%2$s</xliff:g>, el dispositivo comenzará a instalar en segundo plano.\n\nUna vez terminado el proceso, se te pedirá que reinicies.</string>
<string name="cancel_installation_dialog_message">¿Cancelar la instalación?</string>
<string name="label_download_url">URL de descarga</string>
<string name="toast_download_url_copied">URL copiada</string>
<string name="dialog_export_title">Exportando actualización</string>
<string name="notification_export_success">Actualización exportada</string>
<string name="notification_export_fail">Error de exportación</string>
<string name="toast_already_exporting">Ya se está exportando una actualización</string>
<string name="toast_export_started">Exportación iniciada</string>
<plurals name="eta_seconds">
<item quantity="one">Queda 1 segundo</item>
<item quantity="other">Quedan <xliff:g id="count">%d</xliff:g> segundos</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">Queda 1 minuto</item>
<item quantity="other">Quedan <xliff:g id="count">%d</xliff:g> minutos</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">Queda 1 hora</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> horas restantes</item>
</plurals>
<string name="update_over_metered_network_title">Advertencia</string>
<string name="update_over_metered_network_message">Estás a punto de descargar un paquete de actualización utilizando datos móviles, lo que probablemente va a causar un alto consumo de datos. ¿Deseas continuar?</string>
<string name="checkbox_metered_network_warning">No mostrar de nuevo</string>
<string name="menu_metered_network_warning">Aviso de consumo de datos</string>
<string name="blocked_update_dialog_title">Actualización bloqueada</string>
<string name="blocked_update_dialog_message">Esta actualización no puede instalarse usando la aplicación «Actualizador». Lea <xliff:g id="info_url">%1$s</xliff:g> para más información.</string>
<string name="export_channel_title">Exportación finalizada</string>
<string name="new_updates_channel_title">Nuevas actualizaciones</string>
<string name="ongoing_channel_title">Descargas en curso</string>
<string name="update_failed_channel_title">Se produjo un error en la actualización</string>
<string name="info_dialog_title">¿Sabías que...</string>
<string name="info_dialog_message">Las actualizaciones de LineageOS son paquetes de instalación completos, lo que significa que siempre puedes instalar la última actualización, ¡incluso si has saltado algunas de las intermedias!</string>
<string name="info_dialog_ok">¡Gracias por la información!</string>
<string name="local_update_import">Actualización local</string>
<string name="local_update_import_progress">Importando actualización local\u2026</string>
<string name="local_update_import_success">%1$s ha sido importado. ¿Deseas instalarlo?</string>
<string name="local_update_import_failure">Error al importar actualización local</string>
<string name="local_update_import_install">Instalar</string>
<string name="local_update_name">Actualización local</string>
</resources>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Uuendaja</string>
<string name="display_name">Uuendaja</string>
<string name="installation_suspended_notification">Installimine peatati</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="suspend_button">Peata</string>
<string name="dialog_battery_low_title">Madal akutase</string>
<string name="dialog_battery_low_message_pct">Akutase on liiga madal, jätkamiseks on vaja akut vähemalt <xliff:g id="percent_discharging">%1$d</xliff:g>%%, laadimise korral <xliff:g id="percent_charging">%2$d</xliff:g>%%.</string>
<string name="menu_auto_updates_check_interval_daily">Kord päevas</string>
<string name="menu_auto_updates_check_interval_weekly">Kord nädalas</string>
<string name="menu_auto_updates_check_interval_monthly">Kord kuus</string>
<string name="menu_auto_updates_check_interval_never">Mitte kunagi</string>
<string name="menu_show_changelog">Näita muutuste nimekirja</string>
<string name="menu_ab_perf_mode">Eelista uuendusprotsessi</string>
<string name="menu_update_recovery">Uuenda taastust</string>
<string name="toast_forced_update_recovery">Lineage Recovery taastevärskendusi pole selles seadmes võimalik keelata.</string>
<plurals name="eta_seconds">
<item quantity="one">1 sekund jäänud</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> sekundit jäänud</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minut jäänud</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutit jäänud</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 tund jäänud</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> tundi jäänud</item>
</plurals>
<string name="export_channel_title">Ekspordi lõpuleviimine</string>
<string name="ongoing_channel_title">Käimasolevad allalaadimised</string>
</resources>

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Eguneratzailea</string>
<string name="display_name">Eguneratzailea</string>
<string name="verification_failed_notification">Egiaztapenak huts egin du</string>
<string name="verifying_download_notification">Eguneraketa egiaztatzen</string>
<string name="downloading_notification">Deskargatzen</string>
<string name="download_paused_notification">Deskarga pausatuta</string>
<string name="download_paused_error_notification">Deskarga-errorea</string>
<string name="download_completed_notification">Deskarga osatuta</string>
<string name="download_starting_notification">Deskarga hasten</string>
<string name="update_failed_notification">Eguneraketak huts egin du</string>
<string name="installation_suspended_notification">Instalazioa eten da</string>
<string name="new_updates_found_title">Eguneraketa berriak</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pausatu</string>
<string name="resume_button">Berrekin</string>
<string name="suspend_button">Eten</string>
<string name="installing_update">Eguneraketa-paketea instalatzen</string>
<string name="installing_update_error">Instalazio-errorea</string>
<string name="installing_update_finished">Eguneraketa instalatuta</string>
<string name="finalizing_package">Paketearen instalazioarekin bukatzen</string>
<string name="preparing_ota_first_boot">Lehen abiorako prestatzen</string>
<string name="dialog_prepare_zip_message">Aldez aurreko eguneraketaren prestaketa</string>
<string name="dialog_battery_low_title">Bateria gutxi</string>
<string name="dialog_battery_low_message_pct">Bateria maila baxuegia da, gutxienez bateriaren %% <xliff:g id="percent_discharging">%1$d</xliff:g> behar da jarraitzeko, %% <xliff:g id="percent_charging">%2$d</xliff:g> kargatzen badago.</string>
<string name="reboot">Berrabiarazi</string>
<string name="menu_refresh">Freskatu</string>
<string name="menu_preferences">Hobespenak</string>
<string name="menu_auto_updates_check">Eguneraketen egiaztaketa automatikoa</string>
<string name="menu_auto_updates_check_interval_daily">Egunean behin</string>
<string name="menu_auto_updates_check_interval_weekly">Astean behin</string>
<string name="menu_auto_updates_check_interval_monthly">Hilabetean behin</string>
<string name="menu_auto_updates_check_interval_never">Inoiz ez</string>
<string name="menu_auto_delete_updates">Ezabatu eguneraketak instalatutakoan</string>
<string name="menu_delete_update">Ezabatu</string>
<string name="menu_copy_url">Kopiatu URL-a</string>
<string name="menu_export_update">Esportatu eguneraketa</string>
<string name="menu_show_changelog">Erakutsi aldaketa-egunkaria</string>
<string name="menu_ab_perf_mode">Eman lehentasuna eguneraketa prozesuari</string>
<string name="snack_updates_found">Eguneraketa berriak aurkitu dira</string>
<string name="snack_no_updates_found">Ez da eguneraketa berririk aurkitu</string>
<string name="snack_updates_check_failed">Eguneraketa bilaketak huts egin du. Interneterako konexioa egiaztatu eta berriro saiatu, mesedez.</string>
<string name="snack_download_verification_failed">Eguneraketaren egiaztaketak huts egin du.</string>
<string name="snack_download_verified">Deskarga osatuta.</string>
<string name="snack_update_not_installable">Eguneraketa hau ezin da instalatu uneko konpilazioaren gainean.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Azken egiaztaketa: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">Eguneraketa egiaztatzen</string>
<string name="list_no_updates">Ez da eguneraketa berririk aurkitu. Eguneraketak eskuz egiaztatzeko, erabili freskatze botoia.</string>
<string name="action_download">Deskargatu</string>
<string name="action_pause">Pausatu</string>
<string name="action_resume">Berrekin</string>
<string name="action_install">Instalatu</string>
<string name="action_info">Informazioa</string>
<string name="action_delete">Ezabatu</string>
<string name="action_cancel">Utzi</string>
<string name="confirm_delete_dialog_title">Ezabatu fitxategia</string>
<string name="confirm_delete_dialog_message">Ezabatu hautatutako eguneraketa fitxategia?</string>
<string name="apply_update_dialog_title">Aplikatu eguneraketa</string>
<string name="cancel_installation_dialog_message">Ezeztatu instalazioa?</string>
<string name="label_download_url">Deskargaren URL-s</string>
<string name="toast_download_url_copied">URL-a kopiatuta</string>
<string name="dialog_export_title">Eguneraketa esportatzen</string>
<string name="notification_export_success">Eguneraketa esportatuta</string>
<string name="notification_export_fail">Esportazio errorea</string>
<string name="toast_already_exporting">Eguneraketa bat esportatzen dagoeneko</string>
<plurals name="eta_seconds">
<item quantity="one">Segundo 1 geratzen da</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> segundo geratzen dira</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">Minutu 1 geratzen da</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutu geratzen dira</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">Ordu 1 geratzen da</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> ordu geratzen dira</item>
</plurals>
<string name="update_over_metered_network_title">Abisua</string>
<string name="checkbox_metered_network_warning">Ez erakutsi berriro</string>
<string name="blocked_update_dialog_title">Eguneraketa blokeatuta</string>
<string name="blocked_update_dialog_message">Eguneraketa hau ezin da eguneratze-aplikazioarekin instalatu. Irakurri <xliff:g id="info_url">%1$s</xliff:g> informazio gehiagorako.</string>
<string name="export_channel_title">Esportazioaren osaketa</string>
<string name="new_updates_channel_title">Eguneraketa berriak</string>
<string name="ongoing_channel_title">Deskargak abian</string>
<string name="update_failed_channel_title">Eguneraketak huts egin du</string>
</resources>

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Päivittäjä</string>
<string name="display_name">Päivittäjä</string>
<string name="verification_failed_notification">Vahvistus epäonnistui</string>
<string name="verifying_download_notification">Todentaa päivitystä</string>
<string name="downloading_notification">Ladataan</string>
<string name="download_paused_notification">Lataus keskeytetty</string>
<string name="download_paused_error_notification">Latausvirhe</string>
<string name="download_completed_notification">Lataus suoritettu</string>
<string name="download_starting_notification">Aloitetaan latausta</string>
<string name="update_failed_notification">Päivitys epäonnistui</string>
<string name="installation_suspended_notification">Asennus keskeytetty</string>
<string name="new_updates_found_title">Uudet päivitykset</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Tauko</string>
<string name="resume_button">Jatka</string>
<string name="suspend_button">Keskeytä</string>
<string name="installing_update">Asennetaan päivitystä</string>
<string name="installing_update_error">Asennusvirhe</string>
<string name="installing_update_finished">Päivitys asennettu</string>
<string name="finalizing_package">Viimeistellään päivityksen asennusta</string>
<string name="preparing_ota_first_boot">Valmistellaan ensimmäistä käynnistystä</string>
<string name="dialog_prepare_zip_message">Alustava päivityksen valmistelu</string>
<string name="dialog_battery_low_title">Akku vähissä</string>
<string name="dialog_battery_low_message_pct">Akun varaus on liian matala, tarvitset vähintään <xliff:g id="percent_discharging">%1$d</xliff:g>%% jatkaaksesi, <xliff:g id="percent_charging">%2$d</xliff:g>%% jos laite on latauksessa.</string>
<string name="reboot">Käynnistä uudelleen</string>
<string name="menu_refresh">Päivitä</string>
<string name="menu_preferences">Ominaisuudet</string>
<string name="menu_auto_updates_check">Automaattinen päivitysten tarkistus</string>
<string name="menu_auto_updates_check_interval_daily">Kerran päivässä</string>
<string name="menu_auto_updates_check_interval_weekly">Kerran viikossa</string>
<string name="menu_auto_updates_check_interval_monthly">Kerran kuukaudessa</string>
<string name="menu_auto_updates_check_interval_never">Ei koskaan</string>
<string name="menu_auto_delete_updates">Poista päivitykset asennuksen jälkeen</string>
<string name="menu_delete_update">Poista</string>
<string name="menu_copy_url">Kopioi URL-osoite</string>
<string name="menu_export_update">Vie päivitys</string>
<string name="menu_show_changelog">Näytä muutosloki</string>
<string name="menu_ab_perf_mode">Priorisoi päivitysprosessi</string>
<string name="menu_update_recovery">Päivitä recovery-tila</string>
<string name="toast_forced_update_recovery">Tällä laitteella ei voi poistaa Lineage Recovery-päivityksiä käytöstä.</string>
<string name="snack_updates_found">Uusia päivityksiä löytyi</string>
<string name="snack_no_updates_found">Uusia päivityksiä ei löytynyt</string>
<string name="snack_updates_check_failed">Päivitysten tarkistaminen epäonnistui. Tarkista internet-yhteytesi ja yritä uudelleen.</string>
<string name="snack_download_failed">Lataaminen epäonnistui. Tarkista internet-yhteytesi ja yritä uudelleen.</string>
<string name="snack_download_verification_failed">Päivityksen vahvistaminen epäonnistui.</string>
<string name="snack_download_verified">Lataus suoritettu.</string>
<string name="snack_update_not_installable">Tätä päivitystä ei voida asentaa nykyisen version päälle.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Viimeksi tarkistettu: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">Todentaa päivitystä</string>
<string name="list_no_updates">Uusia päivityksiä ei löytynyt. Tarkistaaksesi päivitykset manuaalisesti, paina Päivitä-painiketta.</string>
<string name="action_download">Lataa</string>
<string name="action_pause">Tauko</string>
<string name="action_resume">Jatka</string>
<string name="action_install">Asenna</string>
<string name="action_info">Info</string>
<string name="action_delete">Poista</string>
<string name="action_cancel">Peruuta</string>
<string name="confirm_delete_dialog_title">Poista tiedosto</string>
<string name="confirm_delete_dialog_message">Poista valittu päivitystiedosto?</string>
<string name="apply_update_dialog_title">Asenna päivitys</string>
<string name="cancel_installation_dialog_message">Peruuta asennus?</string>
<string name="label_download_url">Lataussivun URL-osoite</string>
<string name="toast_download_url_copied">URL-osoite kopioitu</string>
<string name="dialog_export_title">Viedään päivitystä</string>
<string name="notification_export_success">Päivitys viety</string>
<string name="notification_export_fail">Vienti epäonnistui</string>
<string name="toast_already_exporting">Päivityksen vieminen jo käynnissä</string>
<plurals name="eta_seconds">
<item quantity="one">1 sekunti jäljellä</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> sekuntia jäljellä</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minuutti jäljellä</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minuuttia jäljellä</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 tunti jäljellä</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> tuntia jäljellä</item>
</plurals>
<string name="update_over_metered_network_title">Varoitus</string>
<string name="checkbox_metered_network_warning">Älä näytä uudelleen</string>
<string name="blocked_update_dialog_title">Päivitys estetty</string>
<string name="blocked_update_dialog_message">Tätä päivitystä ei voida asentaa päivitys-sovelluksella. Lue <xliff:g id="info_url">%1$s</xliff:g> saadaksesi lisätietoja.</string>
<string name="export_channel_title">Vienti valmis</string>
<string name="new_updates_channel_title">Uudet päivitykset</string>
<string name="ongoing_channel_title">Käynnissä olevat lataukset</string>
<string name="update_failed_channel_title">Päivitys epäonnistui</string>
<string name="info_dialog_title">Tiesitkö?</string>
<string name="info_dialog_message">LineageOS-päivitykset ovat täydellisiä asennuspaketteja, jonka ansiosta voit aina asentaa vain viimeisimmän päivityksen, vaikka ohittaisitkin välillä joitakin versioita!</string>
<string name="local_update_import">Paikallinen päivitys</string>
<string name="local_update_import_progress">Tuodaan paikallista päivitystä\u2026</string>
<string name="local_update_import_success">%1$s on tuotu. Haluatko asentaa sen?</string>
<string name="local_update_import_failure">Paikallisen päivityksen tuonti epäonnistui</string>
<string name="local_update_import_install">Asenna</string>
<string name="local_update_name">Paikallinen päivitys</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Gestionnaire de mise à jour</string>
<string name="display_name">Gestionnaire de mise à jour</string>
<string name="verification_failed_notification">Échec de la vérification</string>
<string name="verifying_download_notification">Vérification de la mise à jour en cours</string>
<string name="downloading_notification">Téléchargement en cours</string>
<string name="download_paused_notification">Téléchargement mis en pause</string>
<string name="download_paused_error_notification">Erreur de téléchargement</string>
<string name="download_completed_notification">Téléchargement terminé</string>
<string name="download_starting_notification">Début du téléchargement</string>
<string name="update_failed_notification">Échec de la mise à jour</string>
<string name="installation_suspended_notification">Installation suspendue</string>
<string name="new_updates_found_title">Nouvelles mises à jour</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pause</string>
<string name="resume_button">Reprendre</string>
<string name="suspend_button">Suspendre</string>
<string name="installing_update">Installation du paquet de mise à jour en cours</string>
<string name="installing_update_error">Erreur d\'installation</string>
<string name="installing_update_finished">Mise à jour installée</string>
<string name="finalizing_package">Finalisation de linstallation du paquet</string>
<string name="preparing_ota_first_boot">Préparation pour le premier démarrage</string>
<string name="dialog_prepare_zip_message">Préparation de la mise à jour préliminaire</string>
<string name="dialog_battery_low_title">Batterie faible</string>
<string name="dialog_battery_low_message_pct">Le niveau de batterie est trop faible. Pour continuer, vous devez avoir au moins <xliff:g id="percent_discharging">%1$d</xliff:g> %% de batterie restante, ou <xliff:g id="percent_charging">%2$d</xliff:g> %% si l\'appareil est en charge.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Merci d\'exécuter les commandes suivantes et de retenter la mise à jour :\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Impossible d\'installer la mise à jour avec OverlayFS monté</string>
<string name="reboot">Redémarrer</string>
<string name="menu_refresh">Actualiser</string>
<string name="menu_preferences">Préférences</string>
<string name="menu_auto_updates_check">Vérification des mises à jour automatique</string>
<string name="menu_auto_updates_check_interval_daily">Une fois par jour</string>
<string name="menu_auto_updates_check_interval_weekly">Une fois par semaine</string>
<string name="menu_auto_updates_check_interval_monthly">Une fois par mois</string>
<string name="menu_auto_updates_check_interval_never">Jamais</string>
<string name="menu_auto_delete_updates">Supprimer les mises à jour une fois installées</string>
<string name="menu_delete_update">Supprimer</string>
<string name="menu_copy_url">Copier l\'URL</string>
<string name="menu_export_update">Exporter la mise à jour</string>
<string name="menu_show_changelog">Afficher l\'historique des modifications</string>
<string name="menu_ab_perf_mode">Privilégier le processus de mise à jour</string>
<string name="menu_update_recovery">Mettre à jour la récupération</string>
<string name="toast_forced_update_recovery">Il est impossible de désactiver les mises à jour de la récupération de Lineage sur cet appareil.</string>
<string name="snack_updates_found">Nouvelles mises à jour disponibles</string>
<string name="snack_no_updates_found">Aucune nouvelle mise à jour disponible</string>
<string name="snack_updates_check_failed">La vérification de nouvelles mises à jour a échoué. Vérifiez votre connexion internet et réessayez ultérieurement.</string>
<string name="snack_download_failed">Le téléchargement a échoué. Vérifiez votre connexion internet et réessayez ultérieurement.</string>
<string name="snack_download_verification_failed">La vérification de la mise à jour a échoué.</string>
<string name="snack_download_verified">Téléchargement terminé.</string>
<string name="snack_update_not_installable">Cette mise à jour ne peut pas être installée sur votre version actuelle.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Dernière vérification : <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> sur <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> sur <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Vérification de la mise à jour en cours</string>
<string name="list_no_updates">Aucune nouvelle mise à jour trouvée. Pour vérifier manuellement la présence de mises à jour, utiliser le bouton Actualiser.</string>
<string name="action_download">Télécharger</string>
<string name="action_pause">Mettre en pause</string>
<string name="action_resume">Reprendre</string>
<string name="action_install">Installer</string>
<string name="action_info">Informations</string>
<string name="action_delete">Supprimer</string>
<string name="action_cancel">Annuler</string>
<string name="confirm_delete_dialog_title">Supprimer le fichier</string>
<string name="confirm_delete_dialog_message">Supprimer le fichier de mise à jour sélectionné ?</string>
<string name="apply_update_dialog_title">Appliquer la mise à jour</string>
<string name="apply_update_dialog_message">Vous êtes sur le point d\'installer <xliff:g id="update_name">%1$s</xliff:g>.\n\nSi vous appuyez sur <xliff:g id="ok">%2$s</xliff:g>, votre appareil redémarrera automatiquement en mode récupération pour installer la mise à jour.\n\nRemarque : Cette opération nécessite un système de récupération compatible, sans quoi les mises à jour devront être installées manuellement.</string>
<string name="apply_update_dialog_message_ab">Vous êtes sur le point d\'installer <xliff:g id="update_name">%1$s</xliff:g>.\n\nSi vous appuyez sur <xliff:g id="ok">%2$s</xliff:g>, lappareil commencera l\'installation en arrière-plan.\n\nUne fois celle-ci terminée, il vous sera demandé de redémarrer.</string>
<string name="cancel_installation_dialog_message">Annuler l\'installation ?</string>
<string name="label_download_url">URL de téléchargement</string>
<string name="toast_download_url_copied">URL copiée</string>
<string name="dialog_export_title">Exportation de la mise à jour en cours</string>
<string name="notification_export_success">Mise à jour exportée</string>
<string name="notification_export_fail">Erreur lors de l\'exportation</string>
<string name="toast_already_exporting">Une mise à jour est déjà en cours d\'export</string>
<string name="toast_export_started">Export démarré</string>
<plurals name="eta_seconds">
<item quantity="one">temps restant : 1 seconde</item>
<item quantity="other">temps restant : <xliff:g id="count">%d</xliff:g> secondes</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">temps restant : 1 minute</item>
<item quantity="other">temps restant : <xliff:g id="count">%d</xliff:g> minutes</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">temps restant : 1 heure</item>
<item quantity="other">temps restant : <xliff:g id="count">%d</xliff:g> heures</item>
</plurals>
<string name="update_over_metered_network_title">Avertissement</string>
<string name="update_over_metered_network_message">Vous allez télécharger une mise à jour nécessitant un important volume de données en utilisant un réseau forfaitaire. Souhaitez-vous continuer ?</string>
<string name="checkbox_metered_network_warning">Ne plus afficher</string>
<string name="menu_metered_network_warning">Avertissement de réseau forfaitaire</string>
<string name="blocked_update_dialog_title">Mise à jour bloquée</string>
<string name="blocked_update_dialog_message">Cette mise à jour ne peut pas être installée en utilisant le gestionnaire de mise à jour. Veuillez lire <xliff:g id="info_url">%1$s</xliff:g> pour plus dinformation.</string>
<string name="export_channel_title">Fin de l\'exportation</string>
<string name="new_updates_channel_title">Nouvelles mises à jour</string>
<string name="ongoing_channel_title">Téléchargements en cours</string>
<string name="update_failed_channel_title">Échec de la mise à jour</string>
<string name="info_dialog_title">Le saviez-vous ?</string>
<string name="info_dialog_message">Les mises à jour de LineageOS sont des paquets d\'installation complets. Cela signifie que vous ne pouvez installer que la dernière mise à jour, même si vous en avez ignorées entre temps !</string>
<string name="info_dialog_ok">Merci pour l\'information !</string>
<string name="local_update_import">Mise à jour locale</string>
<string name="local_update_import_progress">Importation de la mise à jour locale\u2026</string>
<string name="local_update_import_success">%1$s a été importée. Voulez-vous l\'installer ?</string>
<string name="local_update_import_failure">Impossible d\'importer la mise à jour locale</string>
<string name="local_update_import_install">Installer</string>
<string name="local_update_name">Mise à jour locale</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Inzornaments</string>
<string name="display_name">Inzornaments</string>
<string name="verification_failed_notification">Verifiche falide</string>
<string name="verifying_download_notification">Verifiche inzornaments</string>
<string name="downloading_notification">Daûr a discjariâ</string>
<string name="download_paused_notification">Discjariament in pause</string>
<string name="download_paused_error_notification">Erôr tal discjariâ</string>
<string name="download_completed_notification">Discjariament completât</string>
<string name="download_starting_notification">Daûr a scomençâ il discjariament</string>
<string name="update_failed_notification">Inzornament falît</string>
<string name="installation_suspended_notification">Instalazion sospindude</string>
<string name="new_updates_found_title">Gnûfs inzornaments</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pause</string>
<string name="resume_button">Ripie</string>
<string name="suspend_button">Sospint</string>
<string name="installing_update">Instalazion dal pachet di inzornament</string>
<string name="installing_update_error">Erôr di instalazion</string>
<string name="installing_update_finished">Inzornament instalât</string>
<string name="finalizing_package">Daûr a completâ la instalazion dal pachet</string>
<string name="preparing_ota_first_boot">Preparazion pal prin inviament</string>
<string name="dialog_prepare_zip_message">Preparazion dal inzornament preliminâr</string>
<string name="dialog_battery_low_title">Batarie basse</string>
<string name="dialog_battery_low_message_pct">Il nivel de batarie al è masse bas, tu scugnis vê almancul il <xliff:g id="percent_discharging">%1$d</xliff:g>%% par continuâ, <xliff:g id="percent_charging">%2$d</xliff:g>%% se e je in cjame.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Eseguìs chescj comants e torne prove l\'inzornament:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Impussibil instalâ l\'inzornament cun OverlayFS montât</string>
<string name="reboot">Torne invie</string>
<string name="menu_refresh">Torne cjame</string>
<string name="menu_preferences">Preferencis</string>
<string name="menu_auto_updates_check">Ricercje inzornaments in automatic</string>
<string name="menu_auto_updates_check_interval_daily">Une volte par dì</string>
<string name="menu_auto_updates_check_interval_weekly">Une volte par setemane</string>
<string name="menu_auto_updates_check_interval_monthly">Une volte par mês</string>
<string name="menu_auto_updates_check_interval_never">Mai</string>
<string name="menu_auto_delete_updates">Elimine i inzornaments se instalâts</string>
<string name="menu_delete_update">Elimine</string>
<string name="menu_copy_url">Copie l\'URL</string>
<string name="menu_export_update">Espuarte inzornament</string>
<string name="menu_show_changelog">Mostre regjisti modifichis</string>
<string name="menu_ab_perf_mode">Inzornaments cun prioritât</string>
<string name="menu_update_recovery">Inzorne Recovery</string>
<string name="toast_forced_update_recovery">Nol è pussibil disativâ i inzornaments di Lineage Recovery su chest dispositîf.</string>
<string name="snack_updates_found">Cjatâts gnûfs inzornaments</string>
<string name="snack_no_updates_found">Nissun gnûf inzornament cjatât</string>
<string name="snack_updates_check_failed">La verifiche di gnûfs inzornaments e je falide. Controle la conession internet e torne prove plui indenant.</string>
<string name="snack_download_failed">Il discjariament dal inzornament al è falît. Controle la conession a internet e torne prove plui indenant.</string>
<string name="snack_download_verification_failed">Verifiche dal inzornament falide.</string>
<string name="snack_download_verified">Discjariament completât.</string>
<string name="snack_update_not_installable">Nol è pussibil instalâ chest inzornament sore di cheste version.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Ultime verifiche: <xliff:g id="date" example="2 di Zenâr dal 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="Lui 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> di <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> di <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verifiche inzornament</string>
<string name="list_no_updates">Nissun gnûf inzornament cjatât. Par controlâ a man i gnûfs inzornaments, tocje il boton Inzorne.</string>
<string name="action_download">Discjame</string>
<string name="action_pause">Pause</string>
<string name="action_resume">Ripie</string>
<string name="action_install">Instale</string>
<string name="action_info">Informazions</string>
<string name="action_delete">Elimine</string>
<string name="action_cancel">Anule</string>
<string name="confirm_delete_dialog_title">Elimine file</string>
<string name="confirm_delete_dialog_message">Eliminâ il file di inzornament selezionât?</string>
<string name="apply_update_dialog_title">Apliche inzornament</string>
<string name="apply_update_dialog_message">Tu stâs par instalâ <xliff:g id="update_name">%1$s</xliff:g>.\n\nSe tu frachis <xliff:g id="ok">%2$s</xliff:g>, il dispositîf al tornarà a inviâsi in modalitât recovery par instalâ in automatic l\'inzornament.\n\nNote: Cheste funzion e domande une Recovery compatibile, in câs contrari tu varâs di procedi ae instalazion manuâl.</string>
<string name="apply_update_dialog_message_ab">Tu stâs par instalâ <xliff:g id="update_name">%1$s</xliff:g>.\n\nSe tu frachis <xliff:g id="ok">%2$s</xliff:g>, il dispositîf al scomençarà la instalazion in sotfont.\n\nUne volte completade, ti vignarà domandât di tornâ a inviâ il dispositîf.</string>
<string name="cancel_installation_dialog_message">Anulâ la instalazion?</string>
<string name="label_download_url">URL dal discjariament</string>
<string name="toast_download_url_copied">URL copiât</string>
<string name="dialog_export_title">Esportazion inzornament</string>
<string name="notification_export_success">Inzornament espuartât</string>
<string name="notification_export_fail">Erôr de esportazion</string>
<string name="toast_already_exporting">Si sta za espuartant un inzornament</string>
<string name="toast_export_started">Esportazion scomençade</string>
<plurals name="eta_seconds">
<item quantity="one">Al mancje 1 secont</item>
<item quantity="other">A mancjin <xliff:g id="count">%d</xliff:g> seconts</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">Al mancje 1 minût</item>
<item quantity="other">A mancjin <xliff:g id="count">%d</xliff:g> minûts</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">E mancje 1 ore</item>
<item quantity="other">A mancjin <xliff:g id="count">%d</xliff:g> oris</item>
</plurals>
<string name="update_over_metered_network_title">Atenzion</string>
<string name="update_over_metered_network_message">Tu stâs par discjariâ un pachet di inzornament doprant une rêt a consum, chest al podarès puartâ a consumâ une vore di dâts. Procedi?</string>
<string name="checkbox_metered_network_warning">No sta mostrâ plui</string>
<string name="menu_metered_network_warning">Avîs di rêt a consum</string>
<string name="blocked_update_dialog_title">Inzornament blocât</string>
<string name="blocked_update_dialog_message">Nol è pussibil instalâ chest inzornament cu la aplicazion di inzornament. Lei <xliff:g id="info_url">%1$s</xliff:g> par vê plui informazions.</string>
<string name="export_channel_title">Completament de esportazion</string>
<string name="new_updates_channel_title">Gnûfs inzornaments</string>
<string name="ongoing_channel_title">Discjariaments in vore</string>
<string name="update_failed_channel_title">Inzornament falît</string>
<string name="info_dialog_title">Savevistu?</string>
<string name="info_dialog_message">I inzornaments di LineageOS a son pachets di instalazion complets. Chest al significhe che tu puedis simpri instalâ l\'ultin inzornament, ancje se prime tu\'nd âs saltât cualchidun!</string>
<string name="info_dialog_ok">Graciis pe informazion!</string>
<string name="local_update_import">Inzornament locâl</string>
<string name="local_update_import_progress">Daûr a impuartâ l\'inzornament locâl\u2026</string>
<string name="local_update_import_success">%1$s al è stât impuartât. Desideristu instalâlu?</string>
<string name="local_update_import_failure">Importazion inzornament locâl falide</string>
<string name="local_update_import_install">Instale</string>
<string name="local_update_name">Inzornament locâl</string>
</resources>

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Fernijer</string>
<string name="display_name">Fernijer</string>
<string name="verification_failed_notification">Ferifikaasje mislearre</string>
<string name="verifying_download_notification">Fernijing ferifiearje</string>
<string name="downloading_notification">Downloade</string>
<string name="download_paused_notification">Download pauzearre</string>
<string name="download_paused_error_notification">Flater by downloaden</string>
<string name="download_completed_notification">Downloaden foltôge</string>
<string name="download_starting_notification">Download starte</string>
<string name="update_failed_notification">Fernijing mislearre</string>
<string name="installation_suspended_notification">Ynstallaasje ûnderbrutsen</string>
<string name="new_updates_found_title">Nije fernijingen</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pauze</string>
<string name="resume_button">Ferfetsje</string>
<string name="suspend_button">Underbrekke</string>
<string name="installing_update">Fernijing ynstallearje</string>
<string name="installing_update_error">Ynstallaasjeflater</string>
<string name="installing_update_finished">Fernijing ynstallearre</string>
<string name="finalizing_package">Ynstallaasje fan het pakket foltôgje</string>
<string name="preparing_ota_first_boot">Earste start tariede</string>
<string name="dialog_prepare_zip_message">Fernijing tariede</string>
<string name="dialog_battery_low_title">Lege batterijspanning</string>
<string name="dialog_battery_low_message_pct">Jo batterijnivo is te leech, jo moatte op syn minst <xliff:g id="percent_discharging">%1$d</xliff:g>%% batterijkapasiteit hawwe om troch te gean of <xliff:g id="percent_charging">%2$d</xliff:g>%% wylst it opladen.</string>
<string name="reboot">Opnij starte</string>
<string name="menu_refresh">Fernije</string>
<string name="menu_preferences">Foarkarren</string>
<string name="menu_auto_updates_check">Automatysk kontrolearje op fernijingen</string>
<string name="menu_auto_updates_check_interval_daily">Ien kear deis</string>
<string name="menu_auto_updates_check_interval_weekly">Ien kear yn de wike</string>
<string name="menu_auto_updates_check_interval_monthly">Ien kear yn de moanne</string>
<string name="menu_auto_updates_check_interval_never">Nea</string>
<string name="menu_auto_delete_updates">Fernijingen fuortsmite neidat se ynstallearre binne</string>
<string name="menu_delete_update">Fuortsmite</string>
<string name="menu_copy_url">URL kopiearje</string>
<string name="menu_export_update">Fernijing eksportearje</string>
<string name="menu_show_changelog">Changelog toane</string>
<string name="menu_ab_perf_mode">Fernijingsproses prioriteit jaan</string>
<string name="snack_updates_found">Nije fernijingen fûn</string>
<string name="snack_no_updates_found">Gjin nije fernijingen fûn</string>
<string name="snack_updates_check_failed">Kin net kontrolearje op fernijingen. Kontrolearje jo ynternetferbining en probearje it letter opnij.</string>
<string name="snack_download_failed">Downloaden mislearre. Kontrolearje jo ynternetferbining en probearje it letter opnij.</string>
<string name="snack_download_verification_failed">Ferifikaasje fan de fernijing mislearre.</string>
<string name="snack_download_verified">Downloaden foltôge.</string>
<string name="snack_update_not_installable">Dizze fernijing kin net ynstallearre wurde boppe-op de aktuele ferzje.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Lêst kontrolearre: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">Fernijing ferifiearje</string>
<string name="list_no_updates">Gjin nije fernijingen fûn. Brûk de knop Fernije om hânmjittich te kontrolearjen op nije fernijingen.</string>
<string name="action_download">Downloade</string>
<string name="action_pause">Pauzeearje</string>
<string name="action_resume">Ferfetsje</string>
<string name="action_install">Ynstallearje</string>
<string name="action_info">Ynformaasje</string>
<string name="action_delete">Fuortsmite</string>
<string name="action_cancel">Annulearje</string>
<string name="confirm_delete_dialog_title">Bestân fuortsmite</string>
<string name="confirm_delete_dialog_message">Selektearre fernijingsbestân fuortsmite?</string>
<string name="apply_update_dialog_title">Fernijing tapasse</string>
<string name="cancel_installation_dialog_message">Ynstallaasje annulearje?</string>
<string name="label_download_url">Download-URL</string>
<string name="toast_download_url_copied">URL kopiearre</string>
<string name="dialog_export_title">Fernijing eksportearje</string>
<string name="notification_export_success">Fernijing eksportearre</string>
<string name="notification_export_fail">Flater by eksportearjen</string>
<string name="toast_already_exporting">Der wurdt al in fernijing eksportearre</string>
<plurals name="eta_seconds">
<item quantity="one">1 sekonde restearjend</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> sekonden restearjend</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minút restearjend</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minuten restearjend</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 oer restearjend</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> oer restearjend</item>
</plurals>
<string name="update_over_metered_network_title">Warskôging</string>
<string name="checkbox_metered_network_warning">Net opnij toane</string>
<string name="blocked_update_dialog_title">Fernijing blokkearre</string>
<string name="blocked_update_dialog_message">Dizze fernijing kin net ynstallearre wurde mei heulp fan de fernijings-app. Lês <xliff:g id="info_url">%1$s</xliff:g> foar mear ynformaasje.</string>
<string name="export_channel_title">Eksportearjen foltôge</string>
<string name="new_updates_channel_title">Nije fernijingen</string>
<string name="ongoing_channel_title">Aktuele downloads</string>
<string name="update_failed_channel_title">Fernijing mislearre</string>
</resources>

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Nuashonróir</string>
<string name="display_name">Nuashonróir</string>
<string name="verification_failed_notification">Theip ar an bhfíorú</string>
<string name="verifying_download_notification">Nuashonrú á fhíorú</string>
<string name="downloading_notification">Ag íosluchtú</string>
<string name="download_paused_notification">Íoslódáil ar sos</string>
<string name="download_paused_error_notification">Earráid íoslódáil</string>
<string name="download_completed_notification">Íoslódáil críochnaithe</string>
<string name="download_starting_notification">Ag tosú íoslódáil</string>
<string name="update_failed_notification">Theip ar an nuashonrú</string>
<string name="installation_suspended_notification">Suiteáil ar fionraí</string>
<string name="new_updates_found_title">Nuashonruithe nua</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Sos</string>
<string name="resume_button">Tosaigh arís</string>
<string name="suspend_button">Fionraí</string>
<string name="installing_update">Ag suiteáil pacáiste nuashonraithe</string>
<string name="installing_update_error">Earráid a shuiteáil</string>
<string name="installing_update_finished">Nuashonrú suiteáilte</string>
<string name="finalizing_package">Ag suiteáil pacáiste a thabhairt chun críche</string>
<string name="preparing_ota_first_boot">Ag ullmhú don chéad tosaithe</string>
<string name="dialog_prepare_zip_message">Réamh-ullmhúchán nuashonraithe</string>
<string name="dialog_battery_low_title">Ceallraí íseal</string>
<string name="dialog_battery_low_message_pct">Tá leibhéal an cheallraí ró-íseal, ní mór duit ar a laghad <xliff:g id="percent_discharging">%1$d</xliff:g> %% den cheallraí chun leanúint ar aghaidh, <xliff:g id="percent_charging">%2$d</xliff:g>%% má tá tú ag muirearú.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[Rith na horduithe seo a leanas agus bain triail eile as an nuashonrú:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Ní féidir an nuashonrú a shuiteáil le OverlayFS suite</string>
<string name="reboot">Atosaigh</string>
<string name="menu_refresh">Athnuaigh</string>
<string name="menu_preferences">Roghanna</string>
<string name="menu_auto_updates_check">Seiceáil nuashonruithe uathoibríoch</string>
<string name="menu_auto_updates_check_interval_daily">Uair sa lá</string>
<string name="menu_auto_updates_check_interval_weekly">Uair sa tseachtain</string>
<string name="menu_auto_updates_check_interval_monthly">Uair sa mhí</string>
<string name="menu_auto_updates_check_interval_never">Riamh</string>
<string name="menu_auto_delete_updates">Scrios nuashonruithe nuair a shuiteáiltear iad</string>
<string name="menu_delete_update">Scrios</string>
<string name="menu_copy_url">Cóipeáil URL</string>
<string name="menu_export_update">Easpórtáil nuashonrú</string>
<string name="menu_show_changelog">Taispeáin loga na n-athruithe</string>
<string name="menu_ab_perf_mode">Tabhair tosaíocht don phróiseas nuashonraithe</string>
<string name="menu_update_recovery">Nuashonraigh aisghabháil</string>
<string name="toast_forced_update_recovery">Tá sé dodhéanta nuashonruithe Lineage Recovery a dhíchumasú ar an ngléas seo.</string>
<string name="snack_updates_found">Nuashonruithe nua aimsithe</string>
<string name="snack_no_updates_found">Níor aimsíodh aon nuashonruithe nua</string>
<string name="snack_updates_check_failed">Theip ar an tseiceáil nuashonraithe. Seiceáil do cheangal idirlín agus bain triail eile as ar ball.</string>
<string name="snack_download_failed">Theip ar an íoslódáil. Seiceáil do cheangal idirlín agus bain triail eile as ar ball.</string>
<string name="snack_download_verification_failed">Theip ar fhíorú an nuashonraithe.</string>
<string name="snack_download_verified">Íoslódáil críochnaithe.</string>
<string name="snack_update_not_installable">Ní féidir an nuashonrú seo a shuiteáil ar bharr an leagan reatha.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" sampla="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Seiceáladh seo caite: <xliff:g id="date" example="1 Eanáir 1970">%1$s</xliff:g> (<xliff:g id="time" sampla="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Nuashonrú á fhíorú</string>
<string name="list_no_updates">Níor aimsíodh aon nuashonruithe nua. Chun seiceáil de láimh le haghaidh nuashonruithe nua, úsáid an cnaipe Athnuaigh.</string>
<string name="action_download">Íosluchtaigh</string>
<string name="action_pause">Sos</string>
<string name="action_resume">Tosaigh arís</string>
<string name="action_install">Suiteáil</string>
<string name="action_info">Eolas</string>
<string name="action_delete">Scrios</string>
<string name="action_cancel">Cealaigh</string>
<string name="confirm_delete_dialog_title">Scrios an comhad</string>
<string name="confirm_delete_dialog_message">Scrios comhad uasdátaigh ?</string>
<string name="apply_update_dialog_title">Cuir nuashonrú</string>
<string name="apply_update_dialog_message">Tá tú ar tí &lt;xliff:g id="update_name"&gt;%1$s&lt;/xliff:g&gt; a shuiteáil.\n\nMá bhrúíonn tú &lt;xliff:g id="ok"&gt;%2$s&lt;/xliff: g&gt;, atosóidh an gléas é féin sa mhodh athshlánaithe chun an nuashonrú a shuiteáil.\n\nNóta: Teastaíonn Aisghabháil comhoiriúnach don ghné seo nó beidh gá le nuashonruithe a shuiteáil de láimh.</string>
<string name="apply_update_dialog_message_ab">Tá tú ar tí &lt;xliff:g id="update_name"&gt;%1$s&lt;/xliff:g&gt; a shuiteáil.\n\nMá bhrúíonn tú &lt;xliff:g id="ok"&gt;%2$s&lt;/xliff: g&gt;, cuirfear tús leis an ngléas a shuiteáil sa chúlra.\n\nNuair a bheidh sé críochnaithe, tabharfar leid duit é a atosú.</string>
<string name="cancel_installation_dialog_message">Cealaigh an tsuiteáil?</string>
<string name="label_download_url">Íoslódáil URL</string>
<string name="toast_download_url_copied">URL Chóipeáil</string>
<string name="dialog_export_title">Nuashonrú easpórtála</string>
<string name="notification_export_success">Easpórtáil an nuashonrú</string>
<string name="notification_export_fail">Earráid easpórtála</string>
<string name="toast_already_exporting">Ag easpórtáil nuashonrú cheana féin</string>
<string name="toast_export_started">Thosaigh easpórtáil</string>
<plurals name="eta_seconds">
<item quantity="one">1 soicind fágtha</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> soicind fágtha</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> soicind fágtha</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> soicind fágtha</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> soicind fágtha</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 nóiméad fágtha</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> nóiméad fágtha</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> nóiméad fágtha</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> nóiméad fágtha</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> nóiméad fágtha</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 uair fágtha</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> uair fágtha</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> uair fágtha</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> uair fágtha</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> uair fágtha</item>
</plurals>
<string name="update_over_metered_network_title">Rabhadh</string>
<string name="update_over_metered_network_message">Tá tú ar tí pacáiste nuashonraithe a íoslódáil thar líonra méadraithe agus is dócha go mbeidh sé ina chúis le húsáid ard sonraí. Ar mhaith leat dul ar aghaidh?</string>
<string name="checkbox_metered_network_warning">Ná taispeáin arís</string>
<string name="menu_metered_network_warning">Rabhadh líonra méadraithe</string>
<string name="blocked_update_dialog_title">Nuashonrú bactha</string>
<string name="blocked_update_dialog_message">Ní féidir an nuashonrú seo a shuiteáil leis an aip nuashonraithe. Léigh <xliff:g id="info_url">%1$s</xliff:g> le haghaidh tuilleadh eolais.</string>
<string name="export_channel_title">Críochnú onnmhairithe</string>
<string name="new_updates_channel_title">Nuashonruithe nua</string>
<string name="ongoing_channel_title">Íoslódálacha leanúnacha</string>
<string name="update_failed_channel_title">Theip ar an nuashonrú</string>
<string name="info_dialog_title">An raibh a fhios agat?</string>
<string name="info_dialog_message">Is pacáistí suiteála iomlána iad nuashonruithe LineageOS. Ciallaíonn sé sin nach féidir leat ach an nuashonrú is déanaí a shuiteáil i gcónaí, fiú mura ndearna tú roinnt eatarthu!</string>
<string name="info_dialog_ok">Go raibh maith agat as an eolas!</string>
<string name="local_update_import">Nuashonrú áitiúil</string>
<string name="local_update_import_progress">Nuashonrú logánta á iompórtáil\u2026</string>
<string name="local_update_import_success">Iompórtáladh %1$s. Ar mhaith leat é a shuiteáil?</string>
<string name="local_update_import_failure">Theip ar iompórtáil an nuashonrú áitiúil</string>
<string name="local_update_import_install">Suiteáil</string>
<string name="local_update_name">Nuashonrú áitiúil</string>
</resources>

View File

@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">An t-ùraichear</string>
<string name="display_name">An t-ùraichear</string>
<string name="verification_failed_notification">Dhfhàillig an dearbhadh</string>
<string name="verifying_download_notification">A dearbhadh an ùrachaidh</string>
<string name="downloading_notification">Ga luchdadh a-nuas</string>
<string name="download_paused_notification">Tha an luchdadh a-nuas na stad</string>
<string name="download_paused_error_notification">Mearachd leis an luchdadh a-nuas</string>
<string name="download_completed_notification">Tha an luchdadh a-nuas deiseil</string>
<string name="download_starting_notification">A tòiseachadh air an luchdadh a-nuas</string>
<string name="update_failed_notification">Dhfhàillig leis an ùrachadh</string>
<string name="installation_suspended_notification">Chaidh an stàladh a chur na dhàil</string>
<string name="new_updates_found_title">Ùrachaidhean</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Cuir na stad</string>
<string name="resume_button">Lean air</string>
<string name="suspend_button">Cuir na dhàil</string>
<string name="installing_update">A stàladh pacaid ùrachaidh</string>
<string name="installing_update_error">Mearachd leis an stàladh</string>
<string name="installing_update_finished">Chaidh an t-ùrachadh a stàladh</string>
<string name="finalizing_package">A crìochnachadh stàladh na pacaid</string>
<string name="preparing_ota_first_boot">Ag ullachadh a chiad tòiseachaidh</string>
<string name="dialog_prepare_zip_message">Ullachadh an ùrachaidh</string>
<string name="dialog_battery_low_title">Bataraidh fann</string>
<string name="dialog_battery_low_message_pct">Tha am bataraidh ro fhann, feumaidh tu co-dhiù <xliff:g id="percent_discharging">%1$d</xliff:g>%% dhen bhataraidh mus lean thu air adhart no <xliff:g id="percent_charging">%2$d</xliff:g>%% fhad s a bhios tu ga theàirrdseadh.</string>
<string name="reboot">Dèan ath-thòiseachadh</string>
<string name="menu_refresh">Ath-nuadhaich</string>
<string name="menu_preferences">Roghainnean</string>
<string name="menu_auto_updates_check">Thoir sùil airson ùrachaidhean gu fèin-obrachail</string>
<string name="menu_auto_updates_check_interval_daily">Gach latha</string>
<string name="menu_auto_updates_check_interval_weekly">Gach seachdain</string>
<string name="menu_auto_updates_check_interval_monthly">Gach mìos</string>
<string name="menu_auto_updates_check_interval_never">Chan ann idir</string>
<string name="menu_auto_delete_updates">Sguab às na h-ùrachaidhean às dèidh an stàlaidh</string>
<string name="menu_delete_update">Sguab às</string>
<string name="menu_copy_url">Dèan lethbhreac dhen URL</string>
<string name="menu_export_update">Às-phortaich an t-ùrachadh</string>
<string name="menu_show_changelog">Seall loga nan atharraichean</string>
<string name="menu_ab_perf_mode">Cuir prìomhachas air pròiseas an ùrachaidh</string>
<string name="menu_update_recovery">Ùraich an t-aiseag</string>
<string name="toast_forced_update_recovery">Cha ghabh ùrachadh air aiseag Lineage a chur à comas air an uidheam seo.</string>
<string name="snack_updates_found">Chaidh ùrachadh a lorg</string>
<string name="snack_no_updates_found">Cha deach ùrachadh a lorg</string>
<string name="snack_updates_check_failed">Cha b urrainn dhuinn sùil a thoirt airson ùrachaidhean. Thoir sùil air a cheangal agad ris an eadar-lìon is feuch ris a-rithist an ceann greis.</string>
<string name="snack_download_failed">Dhfhàillig an luchdadh a-nuas. Thoir sùil air a cheangal ris an eadar-lìon agad is feuch ris a-rithist an ceann greis.</string>
<string name="snack_download_verification_failed">Dhfhàillig le dearbhadh an ùrachaidh.</string>
<string name="snack_download_verified">Tha an luchdadh a-nuas deiseil.</string>
<string name="snack_update_not_installable">Chan urrainn dhut an t-ùrachadh seo a stàladh air an togail làithreach agad.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">An sgrùdadh mu dheireadh: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">A dearbhadh an ùrachaidh</string>
<string name="list_no_updates">Cha deach ùrachadh a lorg. Airson sùil a thoirt airson ùrachaidhean a làimh, cleachd am putan “Ath-nuadhaich”.</string>
<string name="action_download">Luchdaich a-nuas</string>
<string name="action_pause">Cuir na stad</string>
<string name="action_resume">Lean air</string>
<string name="action_install">Stàlaich</string>
<string name="action_info">Fiosrachadh</string>
<string name="action_delete">Sguab às</string>
<string name="action_cancel">Sguir dheth</string>
<string name="confirm_delete_dialog_title">Sguab às am faidhle</string>
<string name="confirm_delete_dialog_message">A bheil thu airson faidhle an ùrachaidh a thagh thu a sguabadh às?</string>
<string name="apply_update_dialog_title">Cuir an t-ùrachadh an sàs</string>
<string name="cancel_installation_dialog_message">An sguir thu dhen stàladh?</string>
<string name="label_download_url">Luchdaich a-nuas URL</string>
<string name="toast_download_url_copied">Chaidh lethbhreac dhen URL a dhèanamh</string>
<string name="dialog_export_title">Ag às-phortadh an ùrachaidh</string>
<string name="notification_export_success">Chaidh an t-ùrachadh às-phortadh</string>
<string name="notification_export_fail">Mearachd leis an às-phortadh</string>
<string name="toast_already_exporting">Tha thu ag às-phortadh ùrachadh mu thràth</string>
<plurals name="eta_seconds">
<item quantity="one"><xliff:g id="count">%d</xliff:g> diog air fhàgail</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> dhiog air fhàgail</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> diogan air fhàgail</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> diog air fhàgail</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one"><xliff:g id="count">%d</xliff:g> mhion. air fhàgail</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> mhion. air fhàgail</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> mion. air fhàgail</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> mion. air fhàgail</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one"><xliff:g id="count">%d</xliff:g> uair a thìde air fhàgail</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> uair a thìde air fhàgail</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> uairean a thìde air fhàgail</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> uair a thìde air fhàgail</item>
</plurals>
<string name="update_over_metered_network_title">Rabhadh</string>
<string name="checkbox_metered_network_warning">Na seall seo a-rithist</string>
<string name="blocked_update_dialog_title">Chaidh an t-ùrachadh a bhacadh</string>
<string name="blocked_update_dialog_message">Cha ghabh an t-ùrachadh seo stàladh le aplacaid an ùraicheir. Leugh <xliff:g id="info_url">%1$s</xliff:g> airson barrachd fiosrachaidh.</string>
<string name="export_channel_title">Coileanadh an às-phortaidh</string>
<string name="new_updates_channel_title">Ùrachaidhean</string>
<string name="ongoing_channel_title">Ga luchdadh a-nuas</string>
<string name="update_failed_channel_title">Dhfhàillig leis an ùrachadh</string>
</resources>

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Actualizador</string>
<string name="display_name">Actualizador</string>
<string name="verification_failed_notification">Fallou a comprobación</string>
<string name="verifying_download_notification">Comprobando actualización</string>
<string name="downloading_notification">Descargando</string>
<string name="download_paused_notification">Descarga en pausa</string>
<string name="download_paused_error_notification">Erro na descarga</string>
<string name="download_completed_notification">Descarga completada</string>
<string name="download_starting_notification">Iniciando descarga</string>
<string name="update_failed_notification">Erro ao actualizar</string>
<string name="installation_suspended_notification">Instalación suspendida</string>
<string name="new_updates_found_title">Novas actualizacións</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pausar</string>
<string name="resume_button">Continuar</string>
<string name="suspend_button">Suspender</string>
<string name="installing_update">Instalando paquete de actualización</string>
<string name="installing_update_error">Erro de instalación</string>
<string name="installing_update_finished">Actualización instalada</string>
<string name="finalizing_package">Rematando a instalación do paquete</string>
<string name="preparing_ota_first_boot">Preparando o primeiro arranque</string>
<string name="dialog_prepare_zip_message">Preparación preliminar da actualización</string>
<string name="dialog_battery_low_title">Batería baixa</string>
<string name="dialog_battery_low_message_pct">O nivel da batería é demasiado baixo, necesita ao menos <xliff:g id="percent_discharging">%1$d</xliff:g>%% de batería para continuar, <xliff:g id="percent_charging">%2$d</xliff:g>%% se o dispositivo estase a cargar.</string>
<string name="reboot">Reiniciar</string>
<string name="menu_refresh">Actualizar</string>
<string name="menu_preferences">Preferencias</string>
<string name="menu_auto_updates_check">Buscar actualizacións automaticamente</string>
<string name="menu_auto_updates_check_interval_daily">Unha vez ao día</string>
<string name="menu_auto_updates_check_interval_weekly">Unha vez á semana</string>
<string name="menu_auto_updates_check_interval_monthly">Unha vez ao mes</string>
<string name="menu_auto_updates_check_interval_never">Nunca</string>
<string name="menu_auto_delete_updates">Eliminar a actualización cando estea instalada</string>
<string name="menu_delete_update">Eliminar</string>
<string name="menu_copy_url">Copiar URL</string>
<string name="menu_export_update">Exportar actualización</string>
<string name="menu_show_changelog">Amosar o rexistro de cambios</string>
<string name="menu_ab_perf_mode">Dar prioridade ao proceso de actualización</string>
<string name="menu_update_recovery">Actualizar recuperador</string>
<string name="toast_forced_update_recovery">Non é posible desactivar as actualizacións do recuperador do Lineage neste dispositivo.</string>
<string name="snack_updates_found">Atopáronse novas actualizacións</string>
<string name="snack_no_updates_found">Non se atoparon novas actualizacións</string>
<string name="snack_updates_check_failed">A verificación da descarga fallou. Comproba a túa conexión a internet e téntao de novo.</string>
<string name="snack_download_failed">Produciuse un erro na descarga. Comproba a túa conexión a internet e téntao de novo.</string>
<string name="snack_download_verification_failed">Fallou a verificación da actualización.</string>
<string name="snack_download_verified">Descarga completada.</string>
<string name="snack_update_not_installable">Non é posíbel instalar esta actualización sobre a compilación actual.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Última comprobación: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">Comprobando actualización</string>
<string name="list_no_updates">Non se atoparon novas actualizacións. Para buscar manualmente, preme no botón Actualizar.</string>
<string name="action_download">Descarga</string>
<string name="action_pause">Pausar</string>
<string name="action_resume">Continuar</string>
<string name="action_install">Instalar</string>
<string name="action_info">Información</string>
<string name="action_delete">Borrar</string>
<string name="action_cancel">Anular</string>
<string name="confirm_delete_dialog_title">Eliminar ficheiro</string>
<string name="confirm_delete_dialog_message">Eliminar o ficheiro de actualización seleccionado?</string>
<string name="apply_update_dialog_title">Aplicar a actualización</string>
<string name="cancel_installation_dialog_message">Cancelar a instalación?</string>
<string name="label_download_url">URL da descarga</string>
<string name="toast_download_url_copied">URL copiado</string>
<string name="dialog_export_title">Exportando actualización</string>
<string name="notification_export_success">Actualización exportada</string>
<string name="notification_export_fail">Exportar erro</string>
<string name="toast_already_exporting">Xa se está a exportar unha actualización</string>
<plurals name="eta_seconds">
<item quantity="one">resta 1 segundo</item>
<item quantity="other">restan <xliff:g id="count">%d</xliff:g> segundos</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">resta 1 minuto</item>
<item quantity="other">restan <xliff:g id="count">%d</xliff:g> minutos</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">resta 1 hora</item>
<item quantity="other">restan <xliff:g id="count">%d</xliff:g> horas</item>
</plurals>
<string name="update_over_metered_network_title">Aviso</string>
<string name="checkbox_metered_network_warning">Non amosar máis</string>
<string name="blocked_update_dialog_title">Actualización bloqueada</string>
<string name="blocked_update_dialog_message">Esta actualización non se pode instalar empregando este actualizador. Por favor, le <xliff:g id="info_url">%1$s</xliff:g> para máis información.</string>
<string name="export_channel_title">Exportación completada</string>
<string name="new_updates_channel_title">Novas actualizacións</string>
<string name="ongoing_channel_title">Descargas en curso</string>
<string name="update_failed_channel_title">Erro ao actualizar</string>
</resources>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Ažuriranje</string>
<string name="display_name">Ažuriranje</string>
<string name="verification_failed_notification">Potvrda neuspješna</string>
<string name="verifying_download_notification">Provjera ažuriranja</string>
<string name="downloading_notification">Preuzimanje</string>
<string name="download_paused_notification">Preuzimanje pauzirano</string>
<string name="download_paused_error_notification">Pogreška preuzimanja</string>
<string name="download_completed_notification">Preuzimanje je završeno</string>
<string name="download_starting_notification">Početak preuzimanja</string>
<string name="new_updates_found_title">Nova ažuriranja</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pauziraj</string>
<string name="resume_button">Nastavi</string>
<string name="installing_update">Instaliranje paketa ažuriranja</string>
<string name="installing_update_error">Pogreška prilikom instalacije</string>
<string name="installing_update_finished">Ažuriranje instalirano</string>
<string name="finalizing_package">Finaliziranje paketa instaliranja</string>
<string name="preparing_ota_first_boot">Priprema za prvo pokretanje</string>
<string name="dialog_prepare_zip_message">Preliminarna priprema ažuriranja</string>
<string name="reboot">Ponovno pokreni</string>
<string name="menu_refresh">Osvježi</string>
<string name="menu_auto_updates_check">Provjeri ažuriranja automatski</string>
<string name="menu_auto_delete_updates">Izbriši ažuriranja nakon instalacije</string>
<string name="menu_delete_update">Izbriši</string>
<string name="menu_copy_url">Kopiraj URL</string>
<string name="menu_export_update">Izvezi ažuriranje</string>
<string name="menu_show_changelog">Prikaži promjene</string>
<string name="menu_update_recovery">Ažuriraj recovery</string>
<string name="toast_forced_update_recovery">Nemoguće je onemogućiti ažuriranja Lineage Recovery na ovom uređaju.</string>
<string name="snack_updates_found">Pronađena su nova ažuriranja</string>
<string name="snack_no_updates_found">Nema pronađenih novih ažuriranja</string>
<string name="snack_updates_check_failed">Provjera ažuriranja nije uspjela. Provjerite internetsku vezu i pokušajte ponovo kasnije.</string>
<string name="snack_download_failed">Preuzimanje nije uspjelo. Provjerite internetsku vezu i pokušajte ponovo kasnije.</string>
<string name="snack_download_verification_failed">Provjera ažuriranja nije uspjela.</string>
<string name="snack_download_verified">Preuzimanje je završeno.</string>
<string name="snack_update_not_installable">Ovo se ažuriranje ne može instalirati na trenutnu verziju.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Zadnja provjera: <xliff:g id="date" example="1 January 1970">%1$s </xliff:g> (<xliff:g id="time" example="01:23">%2$s </xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s </xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s </xliff:g></string>
<string name="list_verifying_update">Provjera ažuriranja</string>
<string name="list_no_updates">Nema pronađenih novih ažuriranja. Za ručnu provjeru novih ažuriranja upotrijebite gumb Osvježi.</string>
<string name="action_download">Preuzmi</string>
<string name="confirm_delete_dialog_title">Izbriši datoteku</string>
<string name="confirm_delete_dialog_message">Želite li izbrisati odabranu datoteku ažuriranja?</string>
<string name="apply_update_dialog_title">Primjeni ažuriranje</string>
<string name="cancel_installation_dialog_message">Prekinuti instalaciju?</string>
<string name="label_download_url">Preuzmi URL</string>
<string name="toast_download_url_copied">URL kopiran</string>
<string name="dialog_export_title">Izvoz ažuriranja</string>
<string name="notification_export_success">Ažuriranje je izvezeno</string>
<string name="notification_export_fail">Pogreška izvoza</string>
<string name="toast_already_exporting">Ažuriranje se već izvozi</string>
<string name="update_over_metered_network_title">Upozorenje</string>
<string name="checkbox_metered_network_warning">Ne prikazuj ponovno</string>
<string name="blocked_update_dialog_title">Ažuriranje je blokirano</string>
<string name="blocked_update_dialog_message">Ovo se ažuriranje ne može instalirati pomoću aplikacije za ažuriranje. Molimo pročitajte <xliff:g id="info_url">%1$s</xliff:g> za više informacija.</string>
<string name="export_channel_title">Kraj izvoza</string>
<string name="new_updates_channel_title">Nova ažuriranja</string>
<string name="ongoing_channel_title">Preuzimanja u tijeku</string>
</resources>

View File

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Frissítés</string>
<string name="display_name">Frissítés</string>
<string name="verification_failed_notification">Az ellenőrzés sikertelen</string>
<string name="verifying_download_notification">Frissítésellenőrzés</string>
<string name="downloading_notification">Letöltés</string>
<string name="download_paused_notification">A letöltés szüneteltetve</string>
<string name="download_paused_error_notification">Letöltési hiba</string>
<string name="download_completed_notification">A letöltés befejeződött</string>
<string name="download_starting_notification">A letöltés indítása</string>
<string name="update_failed_notification">A frissítés sikertelen</string>
<string name="installation_suspended_notification">A telepítés felfüggesztve</string>
<string name="new_updates_found_title">Új frissítések</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Szüneteltetés</string>
<string name="resume_button">Folytatás</string>
<string name="suspend_button">Felfüggesztés</string>
<string name="installing_update">Frissítőcsomag-telepítés</string>
<string name="installing_update_error">Telepítési hiba</string>
<string name="installing_update_finished">A frissítés telepítve</string>
<string name="finalizing_package">A csomagtelepítés véglegesítése</string>
<string name="preparing_ota_first_boot">Felkészülés az első indításra</string>
<string name="dialog_prepare_zip_message">A frissítés előzetes előkészítése</string>
<string name="dialog_battery_low_title">Alacsony akkumulátorszint</string>
<string name="dialog_battery_low_message_pct">Az akkumulátortöltöttség túl alacsony, szüksége van legalább <xliff:g id="percent_discharging">%1$d</xliff:g>%% töltöttségre a folytatáshoz,
illetve, ha éppen tölt, akkor még <xliff:g id="percent_charging">%2$d</xliff:g>%% töltés szükséges.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Futtassa az alábbi parancsokat, majd próbálja újra a frissítést:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Nem telepíthet frissítést a felcsatlakoztatott OverlayFS miatt</string>
<string name="reboot">Újraindítás</string>
<string name="menu_refresh">Frissítés</string>
<string name="menu_preferences">Testreszabás</string>
<string name="menu_auto_updates_check">Automatikus frissítésellenőrzés</string>
<string name="menu_auto_updates_check_interval_daily">Naponta egyszer</string>
<string name="menu_auto_updates_check_interval_weekly">Hetente egyszer</string>
<string name="menu_auto_updates_check_interval_monthly">Havonta egyszer</string>
<string name="menu_auto_updates_check_interval_never">Soha</string>
<string name="menu_auto_delete_updates">A frissítőcsomag törlése telepítés után</string>
<string name="menu_delete_update">Törlés</string>
<string name="menu_copy_url">A webcím másolása</string>
<string name="menu_export_update">A frissítés exportálása</string>
<string name="menu_show_changelog">A változások listájának megjelenítése</string>
<string name="menu_ab_perf_mode">Állítsa fontossági sorrendbe a frissítési folyamatot</string>
<string name="menu_update_recovery">Recovery-frissítés</string>
<string name="toast_forced_update_recovery">Ezen a készüléken nem lehet letiltani a Lineage Recovery frissítéseket.</string>
<string name="snack_updates_found">Új frissítés érhető el</string>
<string name="snack_no_updates_found">Nem található új frissítés</string>
<string name="snack_updates_check_failed">Nem sikerült a frissítéskeresés. Ellenőrizze az internetkapcsolatát, majd próbálja újra.</string>
<string name="snack_download_failed">A letöltés meghiúsult. Ellenőrizze az internetkapcsolatát, majd próbálja újra.</string>
<string name="snack_download_verification_failed">A frissítés ellenőrzése sikertelen.</string>
<string name="snack_download_verified">A letöltés befejeződött.</string>
<string name="snack_update_not_installable">Ez a frissítés nem telepíthető a jelenlegi verzióra.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Utolsó ellenőrzés: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> / <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> / <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Frissítésellenőrzés</string>
<string name="list_no_updates">Nem található új frissítés. A manuális ellenőrzéshez használja a Frissítés gombot.</string>
<string name="action_download">Letöltés</string>
<string name="action_pause">Szüneteltetés</string>
<string name="action_resume">Folytatás</string>
<string name="action_install">Telepítés</string>
<string name="action_info">Információ</string>
<string name="action_delete">Törlés</string>
<string name="action_cancel">Mégse</string>
<string name="confirm_delete_dialog_title">Fájltörlés</string>
<string name="confirm_delete_dialog_message">Biztosan törölni szeretné a letöltött frissítőfájlt?</string>
<string name="apply_update_dialog_title">A frissítés telepítése</string>
<string name="apply_update_dialog_message">Ön a következőt kívánja telepiteni: <xliff:g id="update_name">%1$s</xliff:g>\n\nAmennyiben megnyomja az <xliff:g id="ok">%2$s</xliff:g> gombot, a készülék újraindul recovery-módban és telepíti a frissítést.\n\nFigyelmeztetés: a telepítéshez a készülékkel kompatibilis Recovery szükséges</string>
<string name="apply_update_dialog_message_ab">A következő telepítésre készül: <xliff:g id="update_name">%1$s</xliff:g>.\n\nAmennyiben megnyomja az <xliff:g id="ok">%2$s</xliff:g> gombot, a készülék elkezdi a telepítést a háttérben.\n\nAmint kész, újraindításra lesz szükség.</string>
<string name="cancel_installation_dialog_message">Megszakítja a telepítést?</string>
<string name="label_download_url">Az URL letöltése</string>
<string name="toast_download_url_copied">Az URL másolva</string>
<string name="dialog_export_title">A frissítés exportálása</string>
<string name="notification_export_success">A frissítés exportálva</string>
<string name="notification_export_fail">Exportálás hiba</string>
<string name="toast_already_exporting">Egy frissítés exportálása már folyamatban van</string>
<string name="toast_export_started">Az exportálás elindult</string>
<plurals name="eta_seconds">
<item quantity="one">1 másodperc van hátra</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> másodperc van hátra</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 perc van hátra</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> perc van hátra</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 óra van hátra</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> óra van hátra</item>
</plurals>
<string name="update_over_metered_network_title">Figyelmeztetés</string>
<string name="update_over_metered_network_message">Úgy tűnik mobiladat-forgalmat használva kíván letölteni egy nagyméretű frissítési csomagot, ami nagy költséggel járhat. Biztos benne hogy engedélyezi ezt?</string>
<string name="checkbox_metered_network_warning">Ne jelenjen meg többet</string>
<string name="menu_metered_network_warning">Mobiladat-költség figyelmeztetés</string>
<string name="blocked_update_dialog_title">A frissítés blokkolva</string>
<string name="blocked_update_dialog_message">Ez a frissítés nem telepíthető a Frissítés alkalmazással. További információért olvassa el a következőt: <xliff:g id="info_url">%1$s</xliff:g></string>
<string name="export_channel_title">Exportálás-véglegesítés</string>
<string name="new_updates_channel_title">Új frissítések</string>
<string name="ongoing_channel_title">Folyamatban lévő letöltések</string>
<string name="update_failed_channel_title">A frissítés sikertelen</string>
<string name="info_dialog_title">Tudta Ön?</string>
<string name="info_dialog_message">A LineageOS frissítései teljes telepítőcsomagok. Ez azt jelenti, hogy mindig elég a legfrissebb csomagot telepítenie, nem baj ha korábban kihagyott párat!</string>
<string name="info_dialog_ok">Köszönet az információért!</string>
<string name="local_update_import">Helyi frissítés</string>
<string name="local_update_import_progress">Helyi frissítés importálása\u2026</string>
<string name="local_update_import_success">%1$s importálva lett. Kívánja telepíteni?</string>
<string name="local_update_import_failure">Nem sikerült importálni a helyi frissítést</string>
<string name="local_update_import_install">Telepítés</string>
<string name="local_update_name">Helyi frissítés</string>
</resources>

View File

@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Pembaruan</string>
<string name="display_name">Pembaruan</string>
<string name="verification_failed_notification">Verifikasi gagal</string>
<string name="verifying_download_notification">Memverifikasi pembaruan</string>
<string name="downloading_notification">Mengunduh</string>
<string name="download_paused_notification">Unduhan dijeda</string>
<string name="download_paused_error_notification">Kesalahan pengunduhan</string>
<string name="download_completed_notification">Unduhan selesai</string>
<string name="download_starting_notification">Memulai unduhan</string>
<string name="update_failed_notification">Pembaruan gagal</string>
<string name="installation_suspended_notification">Pemasangan ditunda</string>
<string name="new_updates_found_title">Pembaruan baru</string>
<string name="text_download_speed">%1$s, %2$s/d</string>
<string name="pause_button">Jeda</string>
<string name="resume_button">Lanjutkan</string>
<string name="suspend_button">Tunda</string>
<string name="installing_update">Memasang paket pembaruan</string>
<string name="installing_update_error">Kesalahan pemasangan</string>
<string name="installing_update_finished">Pembaruan dipasang</string>
<string name="finalizing_package">Menyelesaikan pemasangan paket</string>
<string name="preparing_ota_first_boot">Mempersiapkan untuk boot pertama</string>
<string name="dialog_prepare_zip_message">Persiapan awal pembaruan</string>
<string name="dialog_battery_low_title">Baterai lemah</string>
<string name="dialog_battery_low_message_pct">Tingkat baterai terlalu rendah, Anda memerlukan setidaknya <xliff:g id="percent_discharging">%1$d</xliff:g>%% baterai untuk melanjutkan, <xliff:g id="percent_charging">%2$d</xliff:g>%% jika saat pengisian.</string>
<string name="reboot">Mulai ulang</string>
<string name="menu_refresh">Segarkan</string>
<string name="menu_preferences">Preferensi</string>
<string name="menu_auto_updates_check">Periksa pembaruan otomatis</string>
<string name="menu_auto_updates_check_interval_daily">Sehari sekali</string>
<string name="menu_auto_updates_check_interval_weekly">Seminggu sekali</string>
<string name="menu_auto_updates_check_interval_monthly">Sebulan sekali</string>
<string name="menu_auto_updates_check_interval_never">Jangan pernah</string>
<string name="menu_auto_delete_updates">Hapus pembaruan saat dipasang</string>
<string name="menu_delete_update">Hapus</string>
<string name="menu_copy_url">Salin URL</string>
<string name="menu_export_update">Ekspor pembaruan</string>
<string name="menu_show_changelog">Tampilkan catatan perubahan</string>
<string name="menu_ab_perf_mode">Prioritaskan proses pembaruan</string>
<string name="menu_update_recovery">Perbarui Recovery</string>
<string name="toast_forced_update_recovery">Tidak mungkin untuk menonaktifkan pembaruan Lineage Recovery di perangkat ini.</string>
<string name="snack_updates_found">Pembaruan baru ditemukan</string>
<string name="snack_no_updates_found">Tidak ada pembaruan baru ditemukan</string>
<string name="snack_updates_check_failed">Pemeriksaan pembaruan gagal. Silakan periksa koneksi Internet Anda dan coba lagi nanti.</string>
<string name="snack_download_failed">Unduhan gagal. Silakan periksa koneksi Internet Anda dan coba lagi nanti.</string>
<string name="snack_download_verification_failed">Verifikasi pembaruan gagal.</string>
<string name="snack_download_verified">Unduhan selesai.</string>
<string name="snack_update_not_installable">Pembaruan ini tidak dapat dipasang di atas pembuatan saat ini.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s </xliff:g></string>
<string name="header_last_updates_check">Terakhir diperiksa: <xliff:g id="date" example="1 January 1970">%1$s </xliff:g> (<xliff:g id="time" example="01:23">%2$s </xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> dari <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> dari <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Memverifikasi pembaruan</string>
<string name="list_no_updates">Pembaruan tidak ditemukan. Untuk memeriksa pembaruan secara manual, gunakan tombol Segarkan.</string>
<string name="action_download">Unduh</string>
<string name="action_pause">Jeda</string>
<string name="action_resume">Lanjutkan</string>
<string name="action_install">Pasang</string>
<string name="action_info">Info</string>
<string name="action_delete">Hapus</string>
<string name="action_cancel">Batal</string>
<string name="confirm_delete_dialog_title">Hapus berkas</string>
<string name="confirm_delete_dialog_message">Hapus berkas pembaruan yang terpilih?</string>
<string name="apply_update_dialog_title">Terapkan pembaruan</string>
<string name="apply_update_dialog_message">Anda akan memasang <xliff:g id="update_name">%1$s</xliff:g>.\n\nJika Anda menekan <xliff:g id="ok">%2$s</xliff:g>, perangkat akan mulai ulang sendiri dalam mode recovery untuk memasang pembaruan.\n\nPerhatian: Fitur ini memerlukan Recovery yang kompatibel atau pembaruan perlu dipasang secara manual.</string>
<string name="apply_update_dialog_message_ab">Anda akan memasang <xliff:g id="update_name">%1$s</xliff:g>.\n\nJika Anda menekan <xliff:g id="ok">%2$s</xliff:g>, perangkat akan mulai memasang di latar belakang.\n\nSetelah selesai, Anda akan diminta untuk memulai ulang perangkat.</string>
<string name="cancel_installation_dialog_message">Batalkan pemasangan?</string>
<string name="label_download_url">URL Unduh</string>
<string name="toast_download_url_copied">URL disalin</string>
<string name="dialog_export_title">Mengekspor pembaruan</string>
<string name="notification_export_success">Pembaruan diekspor</string>
<string name="notification_export_fail">Kesalahan saat mengekspor</string>
<string name="toast_already_exporting">Sudah mengekspor pembaruan</string>
<string name="toast_export_started">Ekspor dimulai</string>
<plurals name="eta_seconds">
<item quantity="other"><xliff:g id="count">%d</xliff:g> detik tersisa</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="other"><xliff:g id="count">%d</xliff:g> menit tersisa</item>
</plurals>
<plurals name="eta_hours">
<item quantity="other"><xliff:g id="count">%d</xliff:g> jam tersisa</item>
</plurals>
<string name="update_over_metered_network_title">Peringatan</string>
<string name="update_over_metered_network_message">Anda akan mengunduh paket pembaruan melalui jaringan terukur yang kemungkinan besar akan menyebabkan penggunaan data yang tinggi. Apakah Anda ingin melanjutkan?</string>
<string name="checkbox_metered_network_warning">Jangan tampilkan lagi</string>
<string name="menu_metered_network_warning">Peringatan jaringan terukur</string>
<string name="blocked_update_dialog_title">Pembaruan diblokir</string>
<string name="blocked_update_dialog_message">Pembaruan ini tidak dapat dipasang menggunakan aplikasi pembaruan. Baca <xliff:g id="info_url">%1$s</xliff:g> untuk informasi lebih lanjut.</string>
<string name="export_channel_title">Penyelesaian ekspor</string>
<string name="new_updates_channel_title">Pembaruan baru</string>
<string name="ongoing_channel_title">Unduhan sedang berlangsung</string>
<string name="update_failed_channel_title">Pembaruan gagal</string>
<string name="info_dialog_title">Tahukah Anda?</string>
<string name="info_dialog_message">Pembaruan LineageOS adalah paket instalasi lengkap. Itu berarti Anda selalu dapat menginstal hanya pembaruan terbaru, bahkan jika Anda melewatkan beberapa di antaranya!</string>
<string name="info_dialog_ok">Terima kasih atas infonya!</string>
<string name="local_update_import">Pembaruan lokal</string>
<string name="local_update_import_progress">Mengimpor pembaruan lokal\u2026</string>
<string name="local_update_import_success">%1$s telah diimpor. Apakah Anda ingin menginstalnya?</string>
<string name="local_update_import_failure">Gagal mengimpor pembaruan lokal</string>
<string name="local_update_import_install">Instal</string>
<string name="local_update_name">Pembaruan lokal</string>
</resources>

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Uppfærslustýring</string>
<string name="display_name">Uppfærslustýring</string>
<string name="verification_failed_notification">Sannvottun mistókst</string>
<string name="verifying_download_notification">Yfirfer uppfærslu</string>
<string name="downloading_notification">Sæki gögn</string>
<string name="download_paused_notification">Niðurhal í bið</string>
<string name="download_paused_error_notification">Villa við að sækja gögn</string>
<string name="download_completed_notification">Niðurhali lokið</string>
<string name="download_starting_notification">Byrja niðurhal</string>
<string name="update_failed_notification">Uppfærsla mistókst</string>
<string name="installation_suspended_notification">Uppsetning sett í bið</string>
<string name="new_updates_found_title">Nýjar uppfærslur</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Í bið</string>
<string name="resume_button">Halda áfram</string>
<string name="suspend_button">Setja í bið</string>
<string name="installing_update">Set inn uppfærslupakka</string>
<string name="installing_update_error">Villa í uppsetningu</string>
<string name="installing_update_finished">Uppfærsla uppsett</string>
<string name="finalizing_package">Lýk uppsetningu á pakka</string>
<string name="preparing_ota_first_boot">Undirbý fyrstu ræsingu</string>
<string name="dialog_prepare_zip_message">Undirbúningur forstillinga uppfærslu</string>
<string name="dialog_battery_low_title">Lítil hleðsla á rafhlöðu</string>
<string name="dialog_battery_low_message_pct">Hleðslan á rafhlöðunni er of lítil, þú þarft a.m.k. <xliff:g id="percent_discharging">%1$d</xliff:g>%% hleðslu til að halda áfram, <xliff:g id="percent_charging">%2$d</xliff:g>%% ef í hleðslu.</string>
<string name="reboot">Endurræsa</string>
<string name="menu_refresh">Endurlesa</string>
<string name="menu_preferences">Kjörstillingar</string>
<string name="menu_auto_updates_check">Sjálfvirk athugun með uppfærslur</string>
<string name="menu_auto_updates_check_interval_daily">Einu sinni á dag</string>
<string name="menu_auto_updates_check_interval_weekly">Einu sinni í viku</string>
<string name="menu_auto_updates_check_interval_monthly">Einu sinni í mánuði</string>
<string name="menu_auto_updates_check_interval_never">Aldrei</string>
<string name="menu_auto_delete_updates">Eyða uppfærslupökkum þegar þeir hafa verið settir inn</string>
<string name="menu_delete_update">Eyða</string>
<string name="menu_copy_url">Afrita slóð</string>
<string name="menu_export_update">Flytja út uppfærslu</string>
<string name="menu_show_changelog">Birta breytingaannál</string>
<string name="menu_ab_perf_mode">Setja uppfærsluferli í forgang</string>
<string name="menu_update_recovery">Uppfæra endurheimtingu</string>
<string name="toast_forced_update_recovery">Ekki er hægt að gera uppfærslur á endurheimtingu LineageOS óvirkar á þessu
tæki.</string>
<string name="snack_updates_found">Nýjar uppfærslur fundust</string>
<string name="snack_no_updates_found">Engar nýjar uppfærslur fundust</string>
<string name="snack_updates_check_failed">Athugun með uppfærslur mistókst. Skoðaðu internettenginguna og reyndu aftur síðar.</string>
<string name="snack_download_failed">Niðurhal mistókst. Athugaðu internettenginguna og reyndu aftur síðar.</string>
<string name="snack_download_verification_failed">Sannvottun uppfærslu mistókst.</string>
<string name="snack_download_verified">Niðurhali er lokið.</string>
<string name="snack_update_not_installable">Þessa uppfærslu er ekki gægt að setja upp á þessari byggingarútgáfu.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Síðast kannað: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> of <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Yfirfer uppfærslu</string>
<string name="list_no_updates">Engar nýjar uppfærslur fundust. Til að athuga handvirkt með nýjar uppfærslur, notaðu Endurlesa-hnappinn.</string>
<string name="action_download">Sækja</string>
<string name="action_pause">Í bið</string>
<string name="action_resume">Halda áfram</string>
<string name="action_install">Setja upp</string>
<string name="action_info">Upplýsingar</string>
<string name="action_delete">Eyða</string>
<string name="action_cancel">Hætta við</string>
<string name="confirm_delete_dialog_title">Eyða skrá</string>
<string name="confirm_delete_dialog_message">Eyða valdri uppfærsluskrá?</string>
<string name="apply_update_dialog_title">Virkja uppfærslu</string>
<string name="apply_update_dialog_message">Þú ert í þann mund að setja upp <xliff:g id="update_name">%1$s</xliff:g>.\n\nEf þú ýtir á <xliff:g id="ok">%2$s</xliff:g>, mun tækið endurræsa sig í endurheimtuham til að setja inn uppfærsluna.\n\nAthugaðu: Þessi eiginleiki krefst þess að til staðar séu samhæfð endurheimtugögn því annars þarf að setja uppfærslurnar inn handvirkt.</string>
<string name="apply_update_dialog_message_ab">Þú ert í þann mund að setja upp <xliff:g id="update_name">%1$s</xliff:g>.\n\nEf þú ýtir á <xliff:g id="ok">%2$s</xliff:g>, mun tækið hefja uppfærsluna í bakgrunnsferli.\n\nÞegar henni er lokið færðu beiðni um að endurræsa.</string>
<string name="cancel_installation_dialog_message">Hætta við uppsetningu?</string>
<string name="label_download_url">Niðurhalsslóð</string>
<string name="toast_download_url_copied">URL-slóð afrituð</string>
<string name="dialog_export_title">Flytja út uppfærslu</string>
<string name="notification_export_success">Uppfærsla flutt út</string>
<string name="notification_export_fail">Villa við útflutning</string>
<string name="toast_already_exporting">Þegar að flytja út uppfærslu</string>
<string name="toast_export_started">Útflutningur hafinn</string>
<plurals name="eta_seconds">
<item quantity="one">1 sekúnda eftir</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> sekúndur eftir</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 mínúta eftir</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> mínútur eftir</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 klukkustund eftir</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> klukkustundir eftir</item>
</plurals>
<string name="update_over_metered_network_title">Aðvörun</string>
<string name="update_over_metered_network_message">Þú ert í þann mund að fara að sækja uppfærslupakka í gegnum gjaldskylt net,
sem gæti útheimt mikla notkun gagnamagns. Viltu halda áfram?</string>
<string name="checkbox_metered_network_warning">Ekki sýna aftur</string>
<string name="menu_metered_network_warning">Aðvörun á gjaldskyldu neti</string>
<string name="blocked_update_dialog_title">Lokað á uppfærslu</string>
<string name="blocked_update_dialog_message">Þessa uppfærslu er ekki hægt að setja inn með uppfærsluforritinu. Skoðaðu <xliff:g id="info_url">%1$s</xliff:g> til að fá frekari upplýsingar.</string>
<string name="export_channel_title">Klárun útflutnings</string>
<string name="new_updates_channel_title">Nýjar uppfærslur</string>
<string name="ongoing_channel_title">Niðurhal í gangi</string>
<string name="update_failed_channel_title">Uppfærsla mistókst</string>
<string name="info_dialog_title">Vissir þú?</string>
<string name="info_dialog_message">Uppfærslur á LineageOS eru alltaf heilir uppsetningapakkar. Það þýðir að þú getur alltaf sett einungis upp nýjustu uppfærsluna, jafnvel þótt þú hafir sleppt einhverjum uppfærslum í millitíðinni!</string>
<string name="info_dialog_ok">Takk fyrir upplýsingarnar!</string>
<string name="local_update_import">Staðbundin uppfærsla</string>
<string name="local_update_import_progress">Flyt inn staðbundna uppfærslu\u2026</string>
<string name="local_update_import_success">%1$s hefur verið flutt inn. Viltu setja hana upp?</string>
<string name="local_update_import_failure">Mistókst að flytja inn staðbundna uppfærslu</string>
<string name="local_update_name">Staðbundin uppfærsla</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Aggiornamenti</string>
<string name="display_name">Aggiornamenti</string>
<string name="verification_failed_notification">Verifica fallita</string>
<string name="verifying_download_notification">Verifica aggiornamenti</string>
<string name="downloading_notification">Download in corso</string>
<string name="download_paused_notification">Download in pausa</string>
<string name="download_paused_error_notification">Errore durante il download</string>
<string name="download_completed_notification">Download completato</string>
<string name="download_starting_notification">Avvio download</string>
<string name="update_failed_notification">Aggiornamento fallito</string>
<string name="installation_suspended_notification">Installazione sospesa</string>
<string name="new_updates_found_title">Nuovi aggiornamenti</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pausa</string>
<string name="resume_button">Riprendi</string>
<string name="suspend_button">Sospendi</string>
<string name="installing_update">Installazione del pacchetto aggiornamento</string>
<string name="installing_update_error">Errore d\'installazione</string>
<string name="installing_update_finished">Aggiornamento installato</string>
<string name="finalizing_package">Finalizzazione dell\'installazione del pacchetto</string>
<string name="preparing_ota_first_boot">Preparazione per il primo avvio</string>
<string name="dialog_prepare_zip_message">Preparazione preliminare dell\'aggiornamento</string>
<string name="dialog_battery_low_title">Batteria scarica</string>
<string name="dialog_battery_low_message_pct">Il livello della batteria è troppo basso, è necessario almeno il <xliff:g id="percent_discharging">%1$d</xliff:g>%% di batteria per continuare, oppure il <xliff:g id="percent_charging">%2$d</xliff:g>%% se il dispositivo è in carica.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Esegui i seguenti comandi e ritenta l\'aggiornamento:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Impossibile installare l\'aggiornamento con OverlayFS montato</string>
<string name="reboot">Riavvia</string>
<string name="menu_refresh">Ricarica</string>
<string name="menu_preferences">Preferenze</string>
<string name="menu_auto_updates_check">Ricerca aggiornamenti automaticamente</string>
<string name="menu_auto_updates_check_interval_daily">Quotidianamente</string>
<string name="menu_auto_updates_check_interval_weekly">Settimanalmente</string>
<string name="menu_auto_updates_check_interval_monthly">Mensilmente</string>
<string name="menu_auto_updates_check_interval_never">Mai</string>
<string name="menu_auto_delete_updates">Elimina gli aggiornamenti dopo l\'installazione</string>
<string name="menu_delete_update">Elimina</string>
<string name="menu_copy_url">Copia indirizzo URL</string>
<string name="menu_export_update">Esporta aggiornamento</string>
<string name="menu_show_changelog">Mostra il changelog</string>
<string name="menu_ab_perf_mode">Agg. con priorità</string>
<string name="menu_update_recovery">Aggiornamento recovery</string>
<string name="toast_forced_update_recovery">Impossibile disabilitare l\'aggiornamento di Lineage Recovery su questo dispositivo</string>
<string name="snack_updates_found">Nessun aggiornamento trovato</string>
<string name="snack_no_updates_found">Nessun nuovo aggiornamento trovato</string>
<string name="snack_updates_check_failed">La verifica di aggiornamenti è fallita. Controlla la connessione ad internet e riprova più tardi.</string>
<string name="snack_download_failed">Il download dell\'aggiornamento è fallito. Controlla la connessione ad internet e riprova più tardi.</string>
<string name="snack_download_verification_failed">Verifica dell\'aggiornamento fallita.</string>
<string name="snack_download_verified">Download aggiornamento completato.</string>
<string name="snack_update_not_installable">Questo aggiornamento non può essere installato sopra la versione corrente.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Ultima verifica: <xliff:g id="date" example="1 Gennaio 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="Luglio 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> di <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> di <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verifica aggiornamento</string>
<string name="list_no_updates">Nessun nuovo aggiornamento trovato. Per controllare manualmente nuovi aggiornamenti, tocca il pulsante Aggiorna.</string>
<string name="action_download">Scarica</string>
<string name="action_pause">Pausa</string>
<string name="action_resume">Riprendi</string>
<string name="action_install">Installa</string>
<string name="action_info">Info</string>
<string name="action_delete">Elimina</string>
<string name="action_cancel">Annulla</string>
<string name="confirm_delete_dialog_title">Elimina file</string>
<string name="confirm_delete_dialog_message">Eliminare il file di aggiornamento selezionato?</string>
<string name="apply_update_dialog_title">Applica aggiornamento</string>
<string name="apply_update_dialog_message">Stai per installare <xliff:g id="update_name">%1$s</xliff:g>.\n\nSe premi <xliff:g id="ok">%2$s</xliff:g>, il dispositivo verrà riavviato in modalità recovery per installare l\'aggiornamento automaticamente.\n\nNota: questa funzione richiede una recovery compatibile, in caso contrario si dovrà procedere all\'installazione manualmente.</string>
<string name="apply_update_dialog_message_ab">Stai per installare <xliff:g id="update_name">%1$s</xliff:g>.\n\nSe premi <xliff:g id="ok">%2$s</xliff:g>, il dispositivo inizierà l\'installazione in background.\n\nUna volta completato, ti verrà richiesto di riavviare il dispositivo.</string>
<string name="cancel_installation_dialog_message">Annullare l\'installazione?</string>
<string name="label_download_url">Download URL</string>
<string name="toast_download_url_copied">URL copiato</string>
<string name="dialog_export_title">Esportazione aggiornamento</string>
<string name="notification_export_success">Aggiornamento esportato</string>
<string name="notification_export_fail">Errore esportazione</string>
<string name="toast_already_exporting">Esportazione aggiornamento già in corso</string>
<string name="toast_export_started">Esportazione avviata</string>
<plurals name="eta_seconds">
<item quantity="one">1 secondo rimanente</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> secondi rimanenti</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minuto rimanente</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minuti rimanenti</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 ora rimanente</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> ore rimanenti</item>
</plurals>
<string name="update_over_metered_network_title">Attenzione</string>
<string name="update_over_metered_network_message">Stai per scaricare un aggiornamento tramite una rete a consumo, ciò probabilmente comporterà un elevato traffico di dati. Vuoi procedere?</string>
<string name="checkbox_metered_network_warning">Non mostrare di nuovo</string>
<string name="menu_metered_network_warning">Avviso di rete a consumo</string>
<string name="blocked_update_dialog_title">Aggiornamento bloccato</string>
<string name="blocked_update_dialog_message">Questo aggiornamento non può essere installato usando l\'app Aggiornamenti. Si prega di leggere <xliff:g id="info_url">%1$s</xliff:g> per ulteriori informazioni.</string>
<string name="export_channel_title">Completamento esportazione</string>
<string name="new_updates_channel_title">Nuovi aggiornamenti</string>
<string name="ongoing_channel_title">Download in corso</string>
<string name="update_failed_channel_title">Aggiornamento fallito</string>
<string name="info_dialog_title">Lo sapevi?</string>
<string name="info_dialog_message">Gli aggiornamenti di LineageOS sono pacchetti d\'installazione completi. Questo significa che puoi sempre installare solo l\'ultimo aggiornamento, anche se ne hai saltati alcuni in precedenza!</string>
<string name="info_dialog_ok">Grazie per l\'informazione!</string>
<string name="local_update_import">Aggiornamento locale</string>
<string name="local_update_import_progress">Importazione aggiornamento locale\u2026</string>
<string name="local_update_import_success">%1$s è stato importato. Vuoi installarlo?</string>
<string name="local_update_import_failure">Importazione aggiornamento locale fallita</string>
<string name="local_update_import_install">Installa</string>
<string name="local_update_name">Aggiornamento locale</string>
</resources>

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">המעדכן</string>
<string name="display_name">המעדכן</string>
<string name="verification_failed_notification">האימות נכשל</string>
<string name="verifying_download_notification">מאמת עדכון</string>
<string name="downloading_notification">מוריד</string>
<string name="download_paused_notification">ההורדה מושהית</string>
<string name="download_paused_error_notification">ההורדה נכשלה</string>
<string name="download_completed_notification">ההורדה הושלמה</string>
<string name="download_starting_notification">מתחיל להוריד</string>
<string name="update_failed_notification">העדכון נכשל</string>
<string name="new_updates_found_title">עדכונים חדשים</string>
<string name="text_download_speed">%2$s,%1$s לשניה</string>
<string name="pause_button">השהה</string>
<string name="resume_button">המשך</string>
<string name="installing_update">מתקין חבילת עדכון</string>
<string name="installing_update_error">ההתקנה נכשלה</string>
<string name="installing_update_finished">העדכון הותקן</string>
<string name="finalizing_package">משלים את התקנת החבילה</string>
<string name="preparing_ota_first_boot">מתכונן להפעלה ראשונה</string>
<string name="dialog_prepare_zip_message">מתכונן להתקנת העדכון</string>
<string name="dialog_battery_low_title">סוללה חלשה</string>
<string name="dialog_battery_low_message_pct">הסוללה חלשה מדי, אתה צריך לפחות <xliff:g id="percent_discharging">%1$d</xliff:g>%% אחוזים בשביל להמשיך ו־<xliff:g id="percent_charging">%2$d</xliff:g>%% אחוזים אם המכשיר בטעינה.</string>
<string name="reboot">הפעלה מחדש</string>
<string name="menu_refresh">ריענון</string>
<string name="menu_preferences">העדפות</string>
<string name="menu_auto_updates_check">בדיקת עדכונים אוטומטית</string>
<string name="menu_auto_delete_updates">מחק קובצי עדכון לאחר התקנתם</string>
<string name="menu_delete_update">מחק</string>
<string name="menu_copy_url">העתק כתובת אינטרנט</string>
<string name="menu_export_update">יצא עדכון</string>
<string name="menu_show_changelog">הצג רשימת שינויים</string>
<string name="menu_ab_perf_mode">תעדף תהליכי עדכון</string>
<string name="snack_updates_found">נמצאו עדכונים חדשים</string>
<string name="snack_no_updates_found">לא נמצאו עדכונים חדשים</string>
<string name="snack_updates_check_failed">בדיקת העדכונים נכשלה. בדוק את החיבור שלך לאינטרנט ונסה שוב מאוחר יותר.</string>
<string name="snack_download_failed">ההורדה נכשלה. בדוק את החיבור שלך לאינטרנט ונסה שוב מאוחר יותר.</string>
<string name="snack_download_verification_failed">אימות העדכון נכשל.</string>
<string name="snack_download_verified">ההורדה הושלמה.</string>
<string name="snack_update_not_installable">אין אפשרות להתקין עדכון זה מהגרסה הקיימת.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">אנדרואיד <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">בדיקה אחרונה: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">מאמת עדכון</string>
<string name="list_no_updates">לא נמצאו עדכונים חדשים. בכדי לבדוק אם יש עדכונים חדשים, לחץ על רענון.</string>
<string name="action_download">הורד</string>
<string name="action_pause">השהה</string>
<string name="action_resume">המשך</string>
<string name="action_install">התקן</string>
<string name="action_info">מידע</string>
<string name="action_delete">מחיקה</string>
<string name="action_cancel">ביטול</string>
<string name="confirm_delete_dialog_title">מחק קובץ</string>
<string name="confirm_delete_dialog_message">למחוק את קבצי העדכון שנבחרו?</string>
<string name="apply_update_dialog_title">החל עדכון</string>
<string name="cancel_installation_dialog_message">לבטל את ההתקנה?</string>
<string name="label_download_url">כתובת ההורדה</string>
<string name="toast_download_url_copied">הכתובת הועתקה</string>
<string name="dialog_export_title">מיצא עדכון</string>
<string name="notification_export_success">העדכון ייוצא בהצלחה</string>
<string name="notification_export_fail">שגיאה בייצוא</string>
<string name="toast_already_exporting">כבר באמצע ייצוא עדכון</string>
<plurals name="eta_seconds">
<item quantity="one">שניה אחת נותרה</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> שניות נותרו</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> שניות נותרו</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> שניות נותרו</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">דקה אחת נותרה</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> דקות נותרו</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> דקות נותרו</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> דקות נותרו</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">שעה אחת נותרה</item>
<item quantity="two"><xliff:g id="count">%d</xliff:g> שעות נותרו</item>
<item quantity="many"><xliff:g id="count">%d</xliff:g> שעות נותרו</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> שעות נותרו</item>
</plurals>
<string name="update_over_metered_network_title">אזהרה</string>
<string name="checkbox_metered_network_warning">אל תציג שוב</string>
<string name="blocked_update_dialog_title">העדכון חסום</string>
<string name="blocked_update_dialog_message">אין אפשרות להתקין עדכון זה באמצעות יישום המעדכן. תוכל לקרוא בקישור <xliff:g id="info_url">%1$s</xliff:g> לקבלת מידע נוסף.</string>
<string name="export_channel_title">השלמת הייצוא</string>
<string name="new_updates_channel_title">עדכונים חדשים</string>
<string name="ongoing_channel_title">הורדות בפעולה</string>
<string name="update_failed_channel_title">העדכון נכשל</string>
</resources>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">アップデータ</string>
<string name="display_name">アップデータ</string>
<string name="verification_failed_notification">検証に失敗しました</string>
<string name="verifying_download_notification">アップデートを検証中</string>
<string name="downloading_notification">ダウンロード中</string>
<string name="download_paused_notification">ダウンロードを一時停止しました</string>
<string name="download_paused_error_notification">ダウンロードエラー</string>
<string name="download_completed_notification">ダウンロードが完了しました</string>
<string name="download_starting_notification">ダウンロードを開始中</string>
<string name="update_failed_notification">更新に失敗しました</string>
<string name="installation_suspended_notification">インストールは保留されました</string>
<string name="new_updates_found_title">新しいアップデート</string>
<string name="text_download_speed">%1$s、%2$s/s</string>
<string name="pause_button">一時停止</string>
<string name="resume_button">再開</string>
<string name="suspend_button">保留</string>
<string name="installing_update">アップデートパッケージをインストール中</string>
<string name="installing_update_error">インストールエラー</string>
<string name="installing_update_finished">アップデートのインストール完了</string>
<string name="finalizing_package">パッケージのインストールを完了中</string>
<string name="preparing_ota_first_boot">初回起動を準備中</string>
<string name="dialog_prepare_zip_message">予備のアップデート準備</string>
<string name="dialog_battery_low_title">バッテリー残量少</string>
<string name="dialog_battery_low_message_pct">バッテリー残量が不足しています。続行するには<xliff:g id="percent_discharging">%1$d</xliff:g>%%、充電時は<xliff:g id="percent_charging">%2$d</xliff:g>%%のバッテリー残量が必要です。</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ 以下のコマンドを実行し、アップデートを再試行してください:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">OverlayFS マウント済みの場合アップデートはインストールできません</string>
<string name="reboot">再起動</string>
<string name="menu_refresh">再読み込み</string>
<string name="menu_preferences">設定</string>
<string name="menu_auto_updates_check">アップデートの自動確認</string>
<string name="menu_auto_updates_check_interval_daily">1日に1回</string>
<string name="menu_auto_updates_check_interval_weekly">1週間に1回</string>
<string name="menu_auto_updates_check_interval_monthly">1か月に1回</string>
<string name="menu_auto_updates_check_interval_never">なし</string>
<string name="menu_auto_delete_updates">インストール後にアップデートを削除する</string>
<string name="menu_delete_update">削除</string>
<string name="menu_copy_url">URL のコピー</string>
<string name="menu_export_update">アップデートのエクスポート</string>
<string name="menu_show_changelog">更新履歴の表示</string>
<string name="menu_ab_perf_mode">更新プロセスを優先する</string>
<string name="menu_update_recovery">リカバリーを更新</string>
<string name="toast_forced_update_recovery">このデバイスでは Lineage Recovery のアップデートを無効にすることはできません。</string>
<string name="snack_updates_found">アップデートが見つかりました</string>
<string name="snack_no_updates_found">新しいアップデートはありません</string>
<string name="snack_updates_check_failed">アップデートを確認できませんでした。インターネット接続を確認して、しばらくしてからもう一度お試しください。</string>
<string name="snack_download_failed">ダウンロードに失敗しました。インターネット接続を確認して、もう一度やり直してください。</string>
<string name="snack_download_verification_failed">アップデートの検証に失敗しました</string>
<string name="snack_download_verified">ダウンロード完了</string>
<string name="snack_update_not_installable">このアップデートは現在のビルドに上書きインストールできません</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">最終確認: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> / <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> / <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">アップデートを確認</string>
<string name="list_no_updates">新しい更新はありません。新しい更新を手動で確認するには、更新ボタンを押してください。</string>
<string name="action_download">ダウンロード</string>
<string name="action_pause">一時停止</string>
<string name="action_resume">再開</string>
<string name="action_install">インストール</string>
<string name="action_info">情報</string>
<string name="action_delete">削除</string>
<string name="action_cancel">キャンセル</string>
<string name="confirm_delete_dialog_title">ファイルを削除</string>
<string name="confirm_delete_dialog_message">選択したアップデートファイルを削除しますか?</string>
<string name="apply_update_dialog_title">アップデートを適用</string>
<string name="apply_update_dialog_message"><xliff:g id="update_name">%1$s</xliff:g> をインストールしようとしています。\n\n<xliff:g id="ok">%2$s</xliff:g>を押すと、アップデートをインストールするために端末をリカバリーモードでに再起動します。\n\n注意: この機能には対応したリカバリーが必要です。なければ手動でインストールする必要があります。</string>
<string name="apply_update_dialog_message_ab"><xliff:g id="update_name">%1$s</xliff:g> をインストールしようとしています。\n\n<xliff:g id="ok">%2$s</xliff:g>を押すと、バックグラウンドでインストールを開始します。\n\nインストールが完了したら、再起動を促すプロンプトが表示されます。</string>
<string name="cancel_installation_dialog_message">インストールをキャンセルしますか?</string>
<string name="label_download_url">ダウンロード URL</string>
<string name="toast_download_url_copied">URL をコピーしました</string>
<string name="dialog_export_title">アップデートのエクスポート中</string>
<string name="notification_export_success">アップデートのエクスポート</string>
<string name="notification_export_fail">エラー出力</string>
<string name="toast_already_exporting">すでにアップデートをエクスポートしています。</string>
<string name="toast_export_started">エクスポートを開始しました</string>
<plurals name="eta_seconds">
<item quantity="other">残り<xliff:g id="count">%d</xliff:g></item>
</plurals>
<plurals name="eta_minutes">
<item quantity="other">残り<xliff:g id="count">%d</xliff:g></item>
</plurals>
<plurals name="eta_hours">
<item quantity="other">残り<xliff:g id="count">%d</xliff:g>時間</item>
</plurals>
<string name="update_over_metered_network_title">警告</string>
<string name="update_over_metered_network_message">従量課金制のネットワークでアップデートパッケージをダウンロードしようとしており、データ使用量が増加する可能性があります。続行しますか?</string>
<string name="checkbox_metered_network_warning">次回から表示しない</string>
<string name="menu_metered_network_warning">従量制課金接続の警告</string>
<string name="blocked_update_dialog_title">更新をブロックしました</string>
<string name="blocked_update_dialog_message">このアップデートはアプリからインストールできません。詳しくは <xliff:g id="info_url">%1$s</xliff:g> をご覧ください。</string>
<string name="export_channel_title">エクスポート完了</string>
<string name="new_updates_channel_title">新しいアップデート</string>
<string name="ongoing_channel_title">ダウンロード中</string>
<string name="update_failed_channel_title">更新に失敗しました</string>
<string name="info_dialog_title">ご存知ですか?</string>
<string name="info_dialog_message">LineageOS のアップデートは完全なインストールパッケージです。つまり、いくつかのアップデートをスキップしても、最新のアップデートのみをインストールするだけで良いのです!</string>
<string name="info_dialog_ok">ありがとうございます!</string>
<string name="local_update_import">ローカルアップデート</string>
<string name="local_update_import_progress">ローカルアップデートをインポート中\u2026</string>
<string name="local_update_import_success">%1$s をインポートしました。インストールしますか?</string>
<string name="local_update_import_failure">ローカルアップデートのインポートに失敗しました</string>
<string name="local_update_import_install">インストール</string>
<string name="local_update_name">ローカルアップデート</string>
</resources>

View File

@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">განმაახლებელი</string>
<string name="display_name">განმაახლებელი</string>
<string name="verification_failed_notification">დამოწმება ვერ მოხერხდა</string>
<string name="verifying_download_notification">მიმდინარეობს განახლების დამოწმება</string>
<string name="downloading_notification">ჩამოიტვირთება</string>
<string name="download_paused_notification">ჩამოტვირთვა შეჩერებულია</string>
<string name="download_paused_error_notification">ჩამოტვირთვის შეცდომა</string>
<string name="download_completed_notification">ჩამოტვირთვა დასრულებულია</string>
<string name="download_starting_notification">ჩამოტვირთვა იწყება</string>
<string name="update_failed_notification">განახლება ვერ მოხერხდა</string>
<string name="installation_suspended_notification">დაყენება გადაიდო</string>
<string name="new_updates_found_title">ბოლო განახლებები</string>
<string name="text_download_speed">%1$s, %2$s/წმ</string>
<string name="pause_button">შეჩერება</string>
<string name="resume_button">გაგრძელება</string>
<string name="suspend_button">გადადება</string>
<string name="installing_update">ყენდება განახლების კრებული</string>
<string name="installing_update_error">შეცდომა დაყენებისას</string>
<string name="installing_update_finished">განახლება დაყენებულია</string>
<string name="finalizing_package">სრულდება კრებულის ჩადგმა</string>
<string name="preparing_ota_first_boot">მზადდება პირველი ჩატვირთვისთვის</string>
<string name="dialog_prepare_zip_message">წინასწარი მომზადება განახლებისთვის</string>
<string name="dialog_battery_low_title">ბატარეა ჯდება</string>
<string name="dialog_battery_low_message_pct">მუხტის დონე მეტად მცირეა, საჭიროა დამუხტული იყოს არანაკლებ <xliff:g id="percent_discharging">%1$d</xliff:g>%% ან <xliff:g id="percent_charging">%2$d</xliff:g>%% შეერთდეს სატენზე.</string>
<string name="reboot">გადატვირთვა</string>
<string name="menu_refresh">განახლება</string>
<string name="menu_preferences">პარამეტრები</string>
<string name="menu_auto_updates_check">თვითგანახლების შემოწმება</string>
<string name="menu_auto_updates_check_interval_daily">დღეში ერთხელ</string>
<string name="menu_auto_updates_check_interval_weekly">კვირაში ერთხელ</string>
<string name="menu_auto_updates_check_interval_monthly">თვეში ერთხელ</string>
<string name="menu_auto_updates_check_interval_never">არასდროს</string>
<string name="menu_auto_delete_updates">განახლებების წაშლა დაყენების შემდეგ</string>
<string name="menu_delete_update">წაშლა</string>
<string name="menu_copy_url">ბმულის ასლი</string>
<string name="menu_export_update">განახლების გატანა</string>
<string name="menu_show_changelog">ცვლილებების ჩვენება</string>
<string name="menu_ab_perf_mode">განახლებისთვის უპირატესობის მინიჭება</string>
<string name="menu_update_recovery">აღმდგენის განახლება</string>
<string name="toast_forced_update_recovery">ვერ გაითიშება Lineage-აღმდგენის განახლებები ამ მოწყობილობაზე.</string>
<string name="snack_updates_found">ნაპოვნია განახლებები</string>
<string name="snack_no_updates_found">განახლებები ვერ მოიძებნა</string>
<string name="snack_updates_check_failed">განახლებებზე შემოწმება ვერ მოხერხდა. გთხოვთ, გადაამოწმოთ თქვენი ინტერნეტკავშირი და მოგვიანებით სცადოთ ხელახლა.</string>
<string name="snack_download_failed">ჩამოტვირთვა ვერ მოხერხდა. გთხოვთ გადაამოწმოთ თქვენი ინტერნეტკავშირი და სცადოთ ხელახლა.</string>
<string name="snack_download_verification_failed">განახლების დამოწმება ვერ მოხერხდა.</string>
<string name="snack_download_verified">ჩამოტვირთვა დასრულებულია.</string>
<string name="snack_update_not_installable">განახლების ვერ დაყენდება მიმდინარე ანაწყობზე.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">ბოლო შემოწმება: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g>, სულ <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g>, სულ <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">განახლება მოწმდება</string>
<string name="list_no_updates">განახლებები ვერ მოიძებნა. განახლებებზე ხელით შესამოწმებლად, გამოიყენეთ განახლების ღილაკი.</string>
<string name="action_download">ჩამოტვირთვა</string>
<string name="action_pause">შეჩერება</string>
<string name="action_resume">გაგრძელება</string>
<string name="action_install">დაყენება</string>
<string name="action_info">მონაცემები</string>
<string name="action_delete">წაშლა</string>
<string name="action_cancel">გაუქმება</string>
<string name="confirm_delete_dialog_title">ფაილის წაშლა</string>
<string name="confirm_delete_dialog_message">წაიშალოს განახლების შერჩეული ფაილი?</string>
<string name="apply_update_dialog_title">განახლების ასახვა</string>
<string name="apply_update_dialog_message">აპირებთ, ჩააყენოთ <xliff:g id="update_name">%1$s</xliff:g>.\n\nთუ დააჭერთ ღილაკზე <xliff:g id="ok">%2$s</xliff:g>, მოწყობილობა ხელახლა ჩაირთვება აღმდგენ რეჟიმში, განახლების დასაყენებლად.\n\nშენიშვნა: საჭიროებს თავსებად აღმდგენ გარსს, თუ არადა განახლებები ხელით იქნება დასაყენებელი.</string>
<string name="apply_update_dialog_message_ab">აპირებთ, ჩააყენოთ <xliff:g id="update_name">%1$s</xliff:g>.\n\nთუ დააჭერთ ღილაკზე <xliff:g id="ok">%2$s</xliff:g>, მოწყობილობა დაიწყებს დაყენებას ფონურად.\n\nდასრულებისას კი მოგთხოვთ გადატვირთვას.</string>
<string name="cancel_installation_dialog_message">გაუქმდეს დაყენება?</string>
<string name="label_download_url">ჩამოტვირთვის ბმული</string>
<string name="toast_download_url_copied">ბმულის ასლი აღებულია</string>
<string name="dialog_export_title">განახლება ცალკე შეინახება</string>
<string name="notification_export_success">განახლება გატანილია ფაილში</string>
<string name="notification_export_fail">შეცდომა გატანისას</string>
<string name="toast_already_exporting">გატანა უკვე მიმდინარეობს</string>
<string name="toast_export_started">გატანა დაწყებულია</string>
<plurals name="eta_seconds">
<item quantity="one">დარჩენილია 1 წამი</item>
<item quantity="other">დარჩენილია <xliff:g id="count">%d</xliff:g> წამი</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">დარჩენილია 1 წუთი</item>
<item quantity="other">დარჩენილია <xliff:g id="count">%d</xliff:g> წუთი</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">დარჩენილია 1 საათი</item>
<item quantity="other">დარჩენილია <xliff:g id="count">%d</xliff:g> საათი</item>
</plurals>
<string name="update_over_metered_network_title">გაფრთხილება</string>
<string name="update_over_metered_network_message">აპირებთ ჩამოტვირთოთ განახლების კრებული შეზღუდული ინტერნეტით, რასაც შეიძლება მოჰყვეს დიდი ხარჯი. ნამდვილად გსურთ, განაგრძოთ?</string>
<string name="checkbox_metered_network_warning">მომავალში ჩვენების გარეშე</string>
<string name="menu_metered_network_warning">შეზღუდული ქსელის გაფრთხილება</string>
<string name="blocked_update_dialog_title">განახლება შეიზღუდა</string>
<string name="blocked_update_dialog_message">განახლების დაყენება ვერ ხერხდება გამნახლებელი აპით. ვრცლად, გთხოვთ, იხილოთ <xliff:g id="info_url">%1$s</xliff:g>.</string>
<string name="export_channel_title">გადატანა დასრულებულია</string>
<string name="new_updates_channel_title">ბოლო განახლებები</string>
<string name="ongoing_channel_title">მიმდინარე ჩამოტვირთვები</string>
<string name="update_failed_channel_title">განახლება ვერ მოხერხდა</string>
<string name="info_dialog_title">იცოდით?</string>
<string name="info_dialog_message">LineageOS-ის განახლებები სრულ კრებულებს წარმოადგენს. ეს კი ნიშნავს, რომ ყოველთვის შეგიძლიათ ჩააყენოთ ბოლო განახლება, ზოგიერთის გამოტოვების შემთხვევაშიც. </string>
<string name="info_dialog_ok">გმადლობთ, რომ მაცნობეთ!</string>
<string name="local_update_import">ადგილობრივად განახლება</string>
<string name="local_update_import_progress">ადგილობრივი განახლების შემოტანა\u2026</string>
<string name="local_update_import_success">%1$s შემოტანილია. გსურთ, დააყენოთ?</string>
<string name="local_update_import_failure">ადგილობრივი განახლების შემოტანა ვერ მოხერხდა</string>
<string name="local_update_import_install">დაყენება</string>
<string name="local_update_name">ადგილობრივი განახლება</string>
</resources>

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Asefrak n ulqem</string>
<string name="display_name">Asefrak n ulqem</string>
<string name="verification_failed_notification">Icceḍ usenqed</string>
<string name="verifying_download_notification">Asenqed n welqem</string>
<string name="downloading_notification">Asider</string>
<string name="download_paused_error_notification">Tuccḍa n usider</string>
<string name="download_completed_notification">Asider yemmed</string>
<string name="download_starting_notification">Asenker n usider</string>
<string name="installation_suspended_notification">Ittwafsex usebdded</string>
<string name="new_updates_found_title">Ileqman imaynuten</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Steɛfu</string>
<string name="resume_button">Kemmel</string>
<string name="suspend_button">Ittwafsex</string>
<string name="installing_update">Asebded n ukemmus n lqem</string>
<string name="installing_update_error">Tuccḍa g usebded</string>
<string name="installing_update_finished">Lqem ibded</string>
<string name="preparing_ota_first_boot">Aheggi i tnekra tamezwarut</string>
<string name="dialog_prepare_zip_message">Aheggi n lqem n unezwer</string>
<string name="dialog_battery_low_title">Aẓru qrib ad-yefak</string>
<string name="reboot">Ales asenker</string>
<string name="menu_refresh">Sismeḍ</string>
<string name="menu_preferences">Tiwelhiwin</string>
<string name="menu_auto_updates_check">A senqed n uleqqem awurman</string>
<string name="menu_auto_updates_check_interval_daily">Tikkelt i wass</string>
<string name="menu_auto_updates_check_interval_weekly">Tikkelt i ddurt</string>
<string name="menu_auto_updates_check_interval_monthly">Tikkelt i waggur</string>
<string name="menu_auto_updates_check_interval_never">Weṛǧin</string>
<string name="menu_auto_delete_updates">Kkes Ileqman ticki isbedden</string>
<string name="menu_delete_update">Kkes</string>
<string name="menu_copy_url">Nɣel URL</string>
<string name="menu_export_update">Sifeḍ lqem</string>
<string name="menu_update_recovery">Leqqem aḥraz</string>
<string name="snack_updates_found">Llan ileqman imaynuten</string>
<string name="snack_no_updates_found">Ulac ileqman imaynuten</string>
<string name="snack_updates_check_failed">Icceḍ usenqed n uleqqem. Txilek senqed tuqqna-k γer internet sakin ɛreḍ tikelt nniḍen ticki.</string>
<string name="snack_download_failed">Icceḍ usider. Txilek senqed tuqqna-k γer internet sakin ɛreḍ tikelt nniḍen ticki.</string>
<string name="snack_download_verification_failed">Icceḍ usenqed n ulqem.</string>
<string name="snack_download_verified">Asider yemmed.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Asenqed aneggaru: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g>(<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">Asenqed n welqem</string>
<string name="list_no_updates">Ulac ileqman imaynuten. Iwakken ad-tsenqdeḍ ileqman imaynuten s ufus, seqdec taqffalt Sismeḍ.</string>
<string name="action_download">Sider</string>
<string name="action_pause">Steɛfu</string>
<string name="action_resume">Kemmel</string>
<string name="action_install">Sebded</string>
<string name="action_info">Talɣut</string>
<string name="action_delete">Kkes</string>
<string name="action_cancel">Sefsex</string>
<string name="confirm_delete_dialog_title">Kkes afaylu</string>
<string name="confirm_delete_dialog_message">Kkes afaylu n lqem ittwafernen?</string>
<string name="apply_update_dialog_title">Seddu lqem</string>
<string name="label_download_url">Sider URL</string>
<string name="toast_download_url_copied">URL ittwanγel</string>
<string name="dialog_export_title">Asifeḍ n lqem</string>
<string name="notification_export_success">Lqem ittwasifeḍ</string>
<string name="notification_export_fail">Tuccḍa g usifeḍ</string>
<string name="update_over_metered_network_title">Ɣur-k</string>
<string name="checkbox_metered_network_warning">Ur tuɣaleḍ ara ad itsekneḍ</string>
<string name="blocked_update_dialog_title">Lqem iwḥel</string>
<string name="blocked_update_dialog_message">A leqqem agi ur izmir ara ad-ibded s usnas n usefrak n-lqem. Ttxil-ek ɣer <xliff:g id="info_url">%1$s</xliff:g> i ugar talɣut.</string>
<string name="new_updates_channel_title">Ileqman imaynuten</string>
</resources>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="verification_failed_notification">ಪರಿಶೀಲನೆ ವಿಫಲ</string>
<string name="verifying_download_notification">ನವೀಕರಣ ಪರಿಶೀಲಿಸುತ್ತಿದೆ</string>
<string name="downloading_notification">ಇಳಿಸುತ್ತಿದೆ</string>
<string name="download_paused_notification">ಇಳಿಸುವಿಕೆ ವಿರಾಮ</string>
<string name="download_paused_error_notification">ಇಳಿಸುವಾಗ ದೋಷ</string>
<string name="download_completed_notification">ಇಳಿಸುವಿಕೆ ಪೂರ್ಣಗೊಂಡಿದೆ</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="installing_update">ನವೀಕರಣ ಘಂಟನ್ನು ಸ್ಥಾಪಿಸುತ್ತಿದೆ</string>
<string name="installing_update_error">ಸ್ಥಾಪನೆ ದೋಷ</string>
<string name="finalizing_package">ಘಂಟು ಸ್ಥಾಪನೆಯನ್ನು ಕೊನೆಗೊಳಿಸುತ್ತಿದೆ</string>
<string name="dialog_battery_low_title">ಅಲ್ಪ ಮಿಂತಿಣಿ</string>
<string name="dialog_battery_low_message_pct">ಮಿಂತಿಣಿ ಮಟ್ಟ ತೀರಾ ಕಡಿಮೆಯಿದೆ. ಮುಂದುವರಿಸಲು ನಿಮಗೆ ಕನಿಷ್ಟ <xliff:g id="percent_discharging">%1$d</xliff:g>%% ಚಾರ್ಜ್ ಅಥವಾ ಚಾರ್ಜಿಂಗ್ನಲ್ಲಿ <xliff:g id="percent_charging">%2$d</xliff:g>%% ಬೇಕು.</string>
<string name="menu_auto_updates_check">ಸ್ವಯಂ ನವೀಕರಣ ಪರಿಶೀಲನೆ</string>
<string name="menu_auto_updates_check_interval_daily">ದಿನಕ್ಕೊಮ್ಮೆ</string>
<string name="menu_auto_updates_check_interval_weekly">ವಾರಕ್ಕೊಮ್ಮೆ</string>
<string name="menu_auto_updates_check_interval_monthly">ತಿಂಗಳಿಗೊಮ್ಮೆ</string>
<string name="menu_auto_updates_check_interval_never">ಎಂದಿಗೂ ಬೇಡ</string>
<string name="menu_auto_delete_updates">ಸ್ಥಾಪಿಸಿದ ನಂತರ ನವೀಕರಣಗಳನ್ನು ಅಳಿಸು</string>
<string name="menu_delete_update">ಅಳಿಸು</string>
<string name="menu_copy_url">URL ನಕಲಿಸು</string>
<string name="menu_export_update">ನವೀಕರಿಣ ನಿರ್ಯಾತ</string>
<string name="menu_show_changelog">ಬದಲಾವಣೆಗಳನ್ನು ತೋರಿಸು</string>
<string name="menu_ab_perf_mode">ನವೀಕರಣಕ್ಕೆ ಆದ್ಯತೆ ಕೊಡು</string>
<string name="snack_download_verified">ಇಳಿಸುವಿಕೆ ಪೂರ್ಣಗೊಂಡಿದೆ.</string>
<string name="header_last_updates_check">ಕೊನೆಯ ಪರಿಶೀಲನೆ: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">ನವೀಕರಣ ಪರಿಶೀಲಿಸುತ್ತಿದೆ</string>
<string name="action_download">ಇಳಿಸು</string>
<string name="action_install">ಸ್ಥಾಪಿಸು</string>
<string name="action_info">ಮಾಹಿತಿ</string>
<string name="action_delete">ಅಳಿಸು</string>
<string name="action_cancel">ರದ್ದು</string>
<string name="confirm_delete_dialog_title">ಕಡತವನ್ನು ಅಳಿಸು</string>
<string name="confirm_delete_dialog_message">ಆಯ್ಕೆಯಾದ ನವೀಕರಣ ಕಡತ ಅಳಿಸುವುದೇ?</string>
<string name="apply_update_dialog_title">ನವೀಕರಣ ಅನ್ವಯಿಸು</string>
<string name="cancel_installation_dialog_message">ಸ್ಥಾಪನೆ ರದ್ದಿಸಲೇ?</string>
<string name="label_download_url">ಇಳಿಸುವ URL</string>
<string name="dialog_export_title">ನವೀಕರಿಣ ನಿರ್ಯಾತವಾಗುತ್ತಿದೆ</string>
<string name="notification_export_fail">ದೋಷ ನಿರ್ಯಾತ</string>
<string name="toast_already_exporting">ಈಗಾಗಲೇ ನವೀಕರಣವನ್ನು ರಫ್ತು ಮಾಡಲಾಗುತ್ತಿದೆ</string>
<plurals name="eta_seconds">
<item quantity="one">೧ ಕ್ಷಣ ಬಾಕಿ</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> ಕ್ಷಣ ಬಾಕಿ</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">೧ ನಿಮಿಷ ಬಾಕಿ</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> ನಿಮಿಷಗಳು ಬಾಕಿ</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">೧ ಗಂಟೆ ಬಾಕಿ</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> ಗಂಟೆ ಬಾಕಿ</item>
</plurals>
<string name="update_over_metered_network_title">ಎಚ್ಚರಿಕೆ</string>
<string name="checkbox_metered_network_warning">ಪುನಃ ತೋರಿಸದಿರು</string>
<string name="export_channel_title">ನಿರ್ಯಾತ ಪೂರ್ಣತೆ</string>
<string name="ongoing_channel_title">ಪ್ರಗತಿಯಲ್ಲಿರುವ ಕೆಳಭರಿತಗಳು</string>
</resources>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">업데이터</string>
<string name="display_name">업데이터</string>
<string name="verification_failed_notification">검증 실패</string>
<string name="verifying_download_notification">업데이트 검증 중</string>
<string name="downloading_notification">다운로드 중</string>
<string name="download_paused_notification">다운로드 일시 중지됨</string>
<string name="download_paused_error_notification">다운로드 오류</string>
<string name="download_completed_notification">다운로드 완료</string>
<string name="download_starting_notification">다운로드 시작</string>
<string name="update_failed_notification">업데이트 실패</string>
<string name="installation_suspended_notification">설치가 지연됨</string>
<string name="new_updates_found_title">새 업데이트</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">일시 중지</string>
<string name="resume_button">이어 받기</string>
<string name="suspend_button">지연</string>
<string name="installing_update">업데이트 패키지 설치 중</string>
<string name="installing_update_error">설치 오류</string>
<string name="installing_update_finished">업데이트 설치됨</string>
<string name="finalizing_package">패키지 설치 마무리 중</string>
<string name="preparing_ota_first_boot">첫 번째 부팅 준비 중</string>
<string name="dialog_prepare_zip_message">예비 업데이트 준비</string>
<string name="dialog_battery_low_title">배터리 부족</string>
<string name="dialog_battery_low_message_pct">배터리 수준이 너무 낮습니다. 계속하려면 방전 중일 경우 <xliff:g id="percent_discharging">%1$d</xliff:g>%% 이상, 충전 중일 경우 <xliff:g id="percent_charging">%2$d</xliff:g>%% 이상의 배터리 수준이 필요합니다.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ 다음 명령어를 실행한 뒤 업데이트를 다시 시도해 주세요:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">OverlayFS 마운트 상태에서는 업데이트를 설치할 수 없음</string>
<string name="reboot">다시 시작</string>
<string name="menu_refresh">새로고침</string>
<string name="menu_preferences">설정</string>
<string name="menu_auto_updates_check">업데이트 자동 확인</string>
<string name="menu_auto_updates_check_interval_daily">하루에 한 번</string>
<string name="menu_auto_updates_check_interval_weekly">일주일에 한 번</string>
<string name="menu_auto_updates_check_interval_monthly">한달에 한 번</string>
<string name="menu_auto_updates_check_interval_never">사용 안 함</string>
<string name="menu_auto_delete_updates">설치한 뒤 업데이트 파일 삭제</string>
<string name="menu_delete_update">삭제</string>
<string name="menu_copy_url">URL 복사</string>
<string name="menu_export_update">업데이트 내보내기</string>
<string name="menu_show_changelog">변경 사항 보기</string>
<string name="menu_ab_perf_mode">우선 업데이트</string>
<string name="menu_update_recovery">복구 모드 업데이트</string>
<string name="toast_forced_update_recovery">이 기기에서는 Lineage 복구 모드 업데이트를 비활성화할 수 없습니다.</string>
<string name="snack_updates_found">새 업데이트 발견</string>
<string name="snack_no_updates_found">새로운 업데이트 없음</string>
<string name="snack_updates_check_failed">업데이트 확인에 실패했습니다. 인터넷 연결을 확인한 뒤 다시 시도해 주세요.</string>
<string name="snack_download_failed">다운로드에 실패했습니다. 인터넷 연결을 확인한 뒤 다시 시도해 주세요.</string>
<string name="snack_download_verification_failed">업데이트 검증에 실패했습니다.</string>
<string name="snack_download_verified">다운로드가 완료되었습니다.</string>
<string name="snack_update_not_installable">현재 빌드에서는 이 업데이트를 설치할 수 없습니다.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">마지막 확인: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> / <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> / <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">업데이트 검증 중</string>
<string name="list_no_updates">새로운 업데이트가 없습니다. 수동으로 새 업데이트를 확인하려면 새로고침 버튼을 누르세요.</string>
<string name="action_download">다운로드</string>
<string name="action_pause">일시 중지</string>
<string name="action_resume">이어 받기</string>
<string name="action_install">설치</string>
<string name="action_info">정보</string>
<string name="action_delete">삭제</string>
<string name="action_cancel">취소</string>
<string name="confirm_delete_dialog_title">파일 삭제</string>
<string name="confirm_delete_dialog_message">선택한 업데이트 파일을 삭제하시겠습니까?</string>
<string name="apply_update_dialog_title">업데이트 적용</string>
<string name="apply_update_dialog_message"><xliff:g id="update_name">%1$s</xliff:g> 버전을 설치하려 합니다.\n\n<xliff:g id="ok">%2$s</xliff:g>을 누르면 업데이트를 설치하기 위해 기기가 리커버리 모드로 다시 시작됩니다.\n\n주의: 이 기능은 호환되는 리커버리가 필요하며, 없을 경우 업데이트를 수동으로 설치해야 합니다.</string>
<string name="apply_update_dialog_message_ab"><xliff:g id="update_name">%1$s</xliff:g> 버전을 설치하려 합니다.\n\n<xliff:g id="ok">%2$s</xliff:g>을 누르면 백그라운드에서 이 업데이트를 설치합니다.\n\n설치가 완료되면 기기를 다시 시작할 것인지 묻는 대화 상자가 나타납니다.</string>
<string name="cancel_installation_dialog_message">설치를 취소하시겠습니까?</string>
<string name="label_download_url">다운로드 URL</string>
<string name="toast_download_url_copied">URL 복사됨</string>
<string name="dialog_export_title">업데이트 내보내는 중</string>
<string name="notification_export_success">업데이트를 내보냈습니다.</string>
<string name="notification_export_fail">내보내기 오류</string>
<string name="toast_already_exporting">이미 업데이트를 내보내는 중입니다.</string>
<string name="toast_export_started">내보내기를 시작했습니다.</string>
<plurals name="eta_seconds">
<item quantity="other"><xliff:g id="count">%d</xliff:g>초 남음</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="other"><xliff:g id="count">%d</xliff:g>분 남음</item>
</plurals>
<plurals name="eta_hours">
<item quantity="other"><xliff:g id="count">%d</xliff:g>시간 남음</item>
</plurals>
<string name="update_over_metered_network_title">경고</string>
<string name="update_over_metered_network_message">모바일 데이터를 사용하여 업데이트 패키지를 다운로드하려 합니다. 데이터를 매우 많이 사용하게 될 수 있습니다. 정말 계속하시겠습니까?</string>
<string name="checkbox_metered_network_warning">다시 보지 않기</string>
<string name="menu_metered_network_warning">모바일 데이터 사용 경고</string>
<string name="blocked_update_dialog_title">업데이트 차단됨</string>
<string name="blocked_update_dialog_message">이 업데이트는 업데이터 앱으로 설치할 수 없습니다. 자세한 정보는 <xliff:g id="info_url">%1$s</xliff:g> 페이지를 참고하세요.</string>
<string name="export_channel_title">내보내기 완료</string>
<string name="new_updates_channel_title">새 업데이트</string>
<string name="ongoing_channel_title">진행 중인 다운로드</string>
<string name="update_failed_channel_title">업데이트 실패</string>
<string name="info_dialog_title">알고 계신가요?</string>
<string name="info_dialog_message">LineageOS 업데이트는 전체 설치 패키지입니다. 중간에 몇 개 버전을 건너뛰었더라도 가장 최신 버전만 설치하면 됩니다!</string>
<string name="info_dialog_ok">정보 감사합니다!</string>
<string name="local_update_import">로컬 업데이트</string>
<string name="local_update_import_progress">로컬 업데이트 가져오는 중\u2026</string>
<string name="local_update_import_success">%1$s 업데이트를 가져왔습니다. 설치하시겠습니까?</string>
<string name="local_update_import_failure">로컬 업데이트를 가져오지 못했습니다.</string>
<string name="local_update_import_install">설치</string>
<string name="local_update_name">로컬 업데이트</string>
</resources>

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Oppdaterer</string>
<string name="display_name">Oppdaterer</string>
<string name="verification_failed_notification">Bekreftelse mislyktes</string>
<string name="verifying_download_notification">Bekrefter oppdatering</string>
<string name="downloading_notification">Laster ned</string>
<string name="download_paused_notification">Nedlasting pauset</string>
<string name="download_paused_error_notification">Nedlastingsfeil</string>
<string name="download_completed_notification">Nedlasting fullført</string>
<string name="download_starting_notification">Starter nedlasting</string>
<string name="update_failed_notification">Oppdatering feilet</string>
<string name="new_updates_found_title">Nye oppdateringer</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pause</string>
<string name="resume_button">Gjenoppta</string>
<string name="installing_update">Installerer oppdateringspakke</string>
<string name="installing_update_error">Installasjonsfeil</string>
<string name="installing_update_finished">Oppdatering installert</string>
<string name="finalizing_package">Fullfører pakkeinstallsjon</string>
<string name="preparing_ota_first_boot">Forbereder første oppstart</string>
<string name="dialog_prepare_zip_message">Forhåndsregler tas før oppdatering</string>
<string name="reboot">Start på nytt</string>
<string name="menu_refresh">Oppdater</string>
<string name="menu_preferences">Innstillinger</string>
<string name="menu_auto_updates_check">Auto-oppdateringssjekk</string>
<string name="menu_auto_delete_updates">Slett oppdateringer når installert</string>
<string name="menu_delete_update">Slett</string>
<string name="menu_copy_url">Kopier nettadresse</string>
<string name="menu_export_update">Eksporter oppdatering</string>
<string name="snack_updates_found">Nye oppdateringer funnet</string>
<string name="snack_no_updates_found">Ingen nye oppdateringer funnet</string>
<string name="snack_updates_check_failed">Oppdateringssjekken mislyktes. Sjekk din internettilkobling og prøv igjen senere.</string>
<string name="snack_download_failed">Nedlastingen mislyktes. Sjekk din internettilkobling og prøv igjen senere.</string>
<string name="snack_download_verification_failed">Oppdateringsbekreftelsen mislyktes.</string>
<string name="snack_download_verified">Nedlasting fullført.</string>
<string name="snack_update_not_installable">Denne oppdateringen kan ikke installeres over gjeldende installasjon.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Sist sjekket: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_verifying_update">Bekrefter oppdatering</string>
<string name="list_no_updates">Ingen nye programvareoppdateringer funnet. For å se etter oppdateringer manuelt, bruk Oppdater-knappen.</string>
<string name="action_download">Last ned</string>
<string name="action_pause">Sett på pause</string>
<string name="action_resume">Fortsett</string>
<string name="action_install">Installer</string>
<string name="action_info">Info</string>
<string name="action_delete">Slett</string>
<string name="action_cancel">Avbryt</string>
<string name="confirm_delete_dialog_title">Slett fil</string>
<string name="confirm_delete_dialog_message">Slett valgt oppdateringsfil?</string>
<string name="apply_update_dialog_title">Installer oppdatering</string>
<string name="cancel_installation_dialog_message">Vil du avbryte installasjonen?</string>
<string name="label_download_url">Last ned nettadresse</string>
<string name="toast_download_url_copied">Nettadresse kopiert</string>
<string name="dialog_export_title">Eksporterer oppdatering</string>
<string name="notification_export_success">Oppdatering eksportert</string>
<string name="notification_export_fail">Eksporteringsfeil</string>
<string name="toast_already_exporting">Eksporterer allerede en oppdatering</string>
<string name="update_over_metered_network_title">Advarsel</string>
<string name="checkbox_metered_network_warning">Ikke vis igjen</string>
<string name="blocked_update_dialog_title">Oppdatering blokkert</string>
<string name="blocked_update_dialog_message">Denne oppdateringen kan ikke installeres med oppdateringsappen. Les <xliff:g id="info_url">%1$s</xliff:g> for mer informasjon.</string>
<string name="new_updates_channel_title">Nye oppdateringer</string>
<string name="update_failed_channel_title">Oppdatering feilet</string>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="theme_is_light">false</bool>
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="theme_primary">#212121</color>
<color name="theme_primary_dark">#1c1c1c</color>
<color name="theme_accent">@*android:color/accent_device_default_dark</color>
<color name="background">@android:color/system_neutral1_900</color>
<color name="toolbar_collapsed">@android:color/system_neutral1_700</color>
<color name="inverted">#f5f5f5</color>
</resources>

View File

@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Updater</string>
<string name="display_name">Updater</string>
<string name="verification_failed_notification">Verificatie mislukt</string>
<string name="verifying_download_notification">Update verifiëren</string>
<string name="downloading_notification">Downloaden</string>
<string name="download_paused_notification">Download gepauzeerd</string>
<string name="download_paused_error_notification">Fout bij downloaden</string>
<string name="download_completed_notification">Downloaden voltooid</string>
<string name="download_starting_notification">Download starten</string>
<string name="update_failed_notification">Update mislukt</string>
<string name="installation_suspended_notification">Installatie onderbroken</string>
<string name="new_updates_found_title">Nieuwe updates</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pauzeren</string>
<string name="resume_button">Hervatten</string>
<string name="suspend_button">Onderbreken</string>
<string name="installing_update">Update installeren</string>
<string name="installing_update_error">Installatiefout</string>
<string name="installing_update_finished">Update geïnstalleerd</string>
<string name="finalizing_package">Installatie van het pakket afronden</string>
<string name="preparing_ota_first_boot">Eerste start voorbereiden</string>
<string name="dialog_prepare_zip_message">Update voorbereiden</string>
<string name="dialog_battery_low_title">Batterij bijna leeg</string>
<string name="dialog_battery_low_message_pct">Uw batterijniveau is te laag, u moet op zijn minst <xliff:g id="percent_discharging">%1$d</xliff:g>%% batterijcapaciteit hebben om door te gaan of <xliff:g id="percent_charging">%2$d</xliff:g>%% tijdens het opladen.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[Voer deze opdrachten uit en probeer opnieuw te updaten:\n
• adb root\n
• adb enable-verity\n
• adb reboot]]></string>
<string name="dialog_scratch_mounted_title">Kan update niet installeren met OverlayFS gekoppeld</string>
<string name="reboot">Herstarten</string>
<string name="menu_refresh">Vernieuwen</string>
<string name="menu_preferences">Instellingen</string>
<string name="menu_auto_updates_check">Automatisch controleren op updates</string>
<string name="menu_auto_updates_check_interval_daily">Een keer per dag</string>
<string name="menu_auto_updates_check_interval_weekly">Een keer per week</string>
<string name="menu_auto_updates_check_interval_monthly">Een keer per maand</string>
<string name="menu_auto_updates_check_interval_never">Nooit</string>
<string name="menu_auto_delete_updates">Updates verwijderen nadat ze geïnstalleerd zijn</string>
<string name="menu_delete_update">Verwijderen</string>
<string name="menu_copy_url">URL kopiëren</string>
<string name="menu_export_update">Update exporteren</string>
<string name="menu_show_changelog">Changelog weergeven</string>
<string name="menu_ab_perf_mode">Geef prioriteit aan het updateproces</string>
<string name="menu_update_recovery">Recovery bijwerken</string>
<string name="toast_forced_update_recovery">Het is onmogelijk om Lineage Recovery updates op dit apparaat uit te schakelen.</string>
<string name="snack_updates_found">Nieuwe updates gevonden</string>
<string name="snack_no_updates_found">Geen nieuwe updates gevonden</string>
<string name="snack_updates_check_failed">Kan niet controleren op updates. Controleer uw internetverbinding en probeer het later opnieuw.</string>
<string name="snack_download_failed">Downloaden mislukt. Controleer uw internetverbinding en probeer het later opnieuw.</string>
<string name="snack_download_verification_failed">Verificatie van de update mislukt.</string>
<string name="snack_download_verified">Downloaden voltooid.</string>
<string name="snack_update_not_installable">Deze update kan niet worden geïnstalleerd bovenop de huidige versie.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Laatst gecontroleerd: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> van <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> van <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Update verifiëren</string>
<string name="list_no_updates">Geen nieuwe updates gevonden. Gebruik de knop Vernieuwen om handmatig te controleren op nieuwe updates.</string>
<string name="action_download">Downloaden</string>
<string name="action_pause">Pauzeren</string>
<string name="action_resume">Hervatten</string>
<string name="action_install">Installeren</string>
<string name="action_info">Informatie</string>
<string name="action_delete">Verwijderen</string>
<string name="action_cancel">Annuleren</string>
<string name="confirm_delete_dialog_title">Bestand verwijderen</string>
<string name="confirm_delete_dialog_message">Geselecteerde update-bestand verwijderen?</string>
<string name="apply_update_dialog_title">Update toepassen</string>
<string name="apply_update_dialog_message">U staat op het punt uw systeem bij te werken naar <xliff:g id="update_name">%1$s</xliff:g>.\n\nAls u op <xliff:g id="ok">%2$s</xliff:g> tikt, zal het apparaat herstarten naar recovery om de update te installeren.\n\nLet op: een compatibele recovery is vereist, anders moet de update handmatig worden geïnstalleerd.</string>
<string name="apply_update_dialog_message_ab">U staat op het punt om uw toestel bij te werken naar <xliff:g id="update_name">%1$s</xliff:g>.\n\nAls u op <xliff:g id="ok">%2$s</xliff:g> tikt, zal het apparaat de update op de achtergrond uitvoeren.\n\nZodra de installatie voltooid is, zal gevraagd worden om het apparaat te herstarten.</string>
<string name="cancel_installation_dialog_message">Installatie annuleren?</string>
<string name="label_download_url">Download-URL</string>
<string name="toast_download_url_copied">URL gekopieerd</string>
<string name="dialog_export_title">Update exporteren</string>
<string name="notification_export_success">Update geëxporteerd</string>
<string name="notification_export_fail">Fout bij exporteren</string>
<string name="toast_already_exporting">Er wordt al een update geëxporteerd</string>
<string name="toast_export_started">Exporteren is begonnen</string>
<plurals name="eta_seconds">
<item quantity="one">1 seconde resterend</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> seconden resterend</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minuut resterend</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minuten resterend</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 uur resterend</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> uur resterend</item>
</plurals>
<string name="update_over_metered_network_title">Let op</string>
<string name="update_over_metered_network_message">U staat op het punt om een updatepakket te downloaden via een netwerk met datalimiet, wat waarschijnlijk een hoog gegevensgebruik zal veroorzaken. Wilt u doorgaan?</string>
<string name="checkbox_metered_network_warning">Niet opnieuw tonen</string>
<string name="menu_metered_network_warning">Waarschuwing gemeten netwerk</string>
<string name="blocked_update_dialog_title">Update geblokkeerd</string>
<string name="blocked_update_dialog_message">Deze update kan niet worden geïnstalleerd met behulp van de updater-app. Lees <xliff:g id="info_url">%1$s</xliff:g> voor meer informatie.</string>
<string name="export_channel_title">Exporteren voltooid</string>
<string name="new_updates_channel_title">Nieuwe updates</string>
<string name="ongoing_channel_title">Huidige downloads</string>
<string name="update_failed_channel_title">Update mislukt</string>
<string name="info_dialog_title">Wist u dat?</string>
<string name="info_dialog_message">LineageOS updates zijn volledige installatiepakketten. Dat betekent dat u altijd alleen de nieuwste update hoeft te installeren, zelfs als u een paar updates overslaat!</string>
<string name="info_dialog_ok">Bedankt voor de informatie!</string>
<string name="local_update_import">Lokale update</string>
<string name="local_update_import_progress">Importeer lokale update\u2026</string>
<string name="local_update_import_success">%1$s is geïmporteerd. Wilt u het installeren?</string>
<string name="local_update_import_failure">Importeren van lokale update is mislukt</string>
<string name="local_update_import_install">Installeer</string>
<string name="local_update_name">Lokale update</string>
</resources>

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Aktualizator</string>
<string name="display_name">Aktualizator</string>
<string name="verification_failed_notification">Weryfikacja nie powiodła się</string>
<string name="verifying_download_notification">Weryfikacja aktualizacji</string>
<string name="downloading_notification">Pobieranie</string>
<string name="download_paused_notification">Pobieranie wstrzymane</string>
<string name="download_paused_error_notification">Błąd pobierania</string>
<string name="download_completed_notification">Pobieranie zakończone</string>
<string name="download_starting_notification">Rozpoczęcie pobierania</string>
<string name="update_failed_notification">Aktualizacja nie powiodła się</string>
<string name="installation_suspended_notification">Instalacja zawieszona</string>
<string name="new_updates_found_title">Nowe aktualizacje</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Wstrzymaj</string>
<string name="resume_button">Wznów</string>
<string name="suspend_button">Zawieś</string>
<string name="installing_update">Instalowanie pakietu aktualizacji</string>
<string name="installing_update_error">Błąd instalacji</string>
<string name="installing_update_finished">Zainstalowano aktualizację</string>
<string name="finalizing_package">Kończenie instalacji pakietu</string>
<string name="preparing_ota_first_boot">Przygotowanie do pierwszego uruchomienia</string>
<string name="dialog_prepare_zip_message">Przygotowanie wstępne aktualizacji</string>
<string name="dialog_battery_low_title">Niskim poziom baterii</string>
<string name="dialog_battery_low_message_pct">Poziom naładowania baterii jest zbyt niski, musisz mieć co najmniej <xliff:g id="percent_discharging">%1$d</xliff:g>%% baterii lub <xliff:g id="percent_charging">%2$d</xliff:g>%% w trakcie ładowania.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Uruchom następujące polecenia i dokonaj ponownej aktualizacji:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Nie można zainstalować aktualizacji z zamontowanym \"OverlayFS\"</string>
<string name="reboot">Uruchom ponownie</string>
<string name="menu_refresh">Odśwież</string>
<string name="menu_preferences">Ustawienia</string>
<string name="menu_auto_updates_check">Automatyczne sprawdzanie aktualizacji</string>
<string name="menu_auto_updates_check_interval_daily">Raz dziennie</string>
<string name="menu_auto_updates_check_interval_weekly">Raz w tygodniu</string>
<string name="menu_auto_updates_check_interval_monthly">Raz w miesiącu</string>
<string name="menu_auto_updates_check_interval_never">Nigdy</string>
<string name="menu_auto_delete_updates">Usuń pliki aktualizacji po zainstalowaniu</string>
<string name="menu_delete_update">Usuń</string>
<string name="menu_copy_url">Kopiuj adres URL</string>
<string name="menu_export_update">Wyślij aktualizację</string>
<string name="menu_show_changelog">Pokaż listę zmian</string>
<string name="menu_ab_perf_mode">Nadaj wyższy priorytet procesowi aktualizacji</string>
<string name="menu_update_recovery">Aktualizuj Recovery</string>
<string name="toast_forced_update_recovery">Nie można wyłączyć aktualizacji Lineage Recovery na tym urządzeniu.</string>
<string name="snack_updates_found">Znaleziono nowe aktualizacje</string>
<string name="snack_no_updates_found">Nie znaleziono nowych aktualizacji</string>
<string name="snack_updates_check_failed">Sprawdzanie aktualizacji nie powiodło się. Sprawdź połączenie z Internetem i spróbuj ponownie.</string>
<string name="snack_download_failed">Pobieranie nie powiodło się. Sprawdź połączenie z Internetem i spróbuj ponownie później.</string>
<string name="snack_download_verification_failed">Weryfikacja aktualizacji się nie powiodła.</string>
<string name="snack_download_verified">Pobieranie zakończone.</string>
<string name="snack_update_not_installable">Ta aktualizacja nie może zostać zainstalowana na bieżącej wersji systemu.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Ostatnio sprawdzane: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> z <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> z <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Sprawdzanie aktualizacji</string>
<string name="list_no_updates">Nie znaleziono nowych aktualizacji. Aby ręcznie sprawdzić dostępność nowych aktualizacji, użyj przycisku Odśwież.</string>
<string name="action_download">Pobierz</string>
<string name="action_pause">Wstrzymaj</string>
<string name="action_resume">Wznów</string>
<string name="action_install">Zainstaluj</string>
<string name="action_info">Informacje</string>
<string name="action_delete">Usuń</string>
<string name="action_cancel">Anuluj</string>
<string name="confirm_delete_dialog_title">Usuń plik</string>
<string name="confirm_delete_dialog_message">Usunąć wybrany plik aktualizacji?</string>
<string name="apply_update_dialog_title">Zastosuj aktualizację</string>
<string name="apply_update_dialog_message">Zamierzasz zainstalować <xliff:g id="update_name">%1$s</xliff:g>.\n\nJeśli naciśniesz <xliff:g id="ok">%2$s</xliff:g>, urządzenie uruchomi się ponownie w trybie Recovery, aby zainstalować aktualizację.\n\nUwaga: Ta funkcja wymaga kompatybilnego Recovery lub aktualizacje będą musiały być zainstalowane ręcznie.</string>
<string name="apply_update_dialog_message_ab">Zamierzasz zainstalować <xliff:g id="update_name">%1$s</xliff:g>.\n\nJeśli naciśniesz <xliff:g id="ok">%2$s</xliff:g>, urządzenie rozpocznie instalację w tle.\n\nPo zakończeniu, zostanie wyświetlony komunikat, aby uruchomić urządzenie ponownie.</string>
<string name="cancel_installation_dialog_message">Anulować instalację?</string>
<string name="label_download_url">Pobierz adres URL</string>
<string name="toast_download_url_copied">Skopiowano adres URL</string>
<string name="dialog_export_title">Wysyłanie aktualizacji</string>
<string name="notification_export_success">Aktualizacja wysłana</string>
<string name="notification_export_fail">Błąd wysyłania</string>
<string name="toast_already_exporting">Aktualizacja jest już wysyłana</string>
<string name="toast_export_started">Rozpoczęto eksportowanie</string>
<plurals name="eta_seconds">
<item quantity="one">Pozostała 1 sekunda</item>
<item quantity="few">Pozostały <xliff:g id="count">%d</xliff:g> sekundy</item>
<item quantity="many">Pozostało <xliff:g id="count">%d</xliff:g> sekund</item>
<item quantity="other">Pozostało <xliff:g id="count">%d</xliff:g> sekund</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">Pozostała 1 minuta</item>
<item quantity="few">Pozostały <xliff:g id="count">%d</xliff:g> minuty</item>
<item quantity="many">Pozostało <xliff:g id="count">%d</xliff:g> minut</item>
<item quantity="other">Pozostało <xliff:g id="count">%d</xliff:g> minut</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">Pozostała 1 godzina</item>
<item quantity="few">Pozostały <xliff:g id="count">%d</xliff:g> godziny</item>
<item quantity="many">Pozostało <xliff:g id="count">%d</xliff:g> godzin</item>
<item quantity="other">Pozostało <xliff:g id="count">%d</xliff:g> godzin</item>
</plurals>
<string name="update_over_metered_network_title">Ostrzeżenie</string>
<string name="update_over_metered_network_message">Zamierzasz pobrać pakiet aktualizacji za pomocą sieci komórkowej, co prawdopodobnie spowoduje wysokie zużycie danych. Czy chcesz kontynuować?</string>
<string name="checkbox_metered_network_warning">Nie pokazuj ponownie</string>
<string name="menu_metered_network_warning">Ostrzeżenie o sieci z pomiarem</string>
<string name="blocked_update_dialog_title">Aktualizacja zablokowana</string>
<string name="blocked_update_dialog_message">Tej aktualizacji nie można zainstalować przy użyciu aplikacji \"Aktualizator\". Zapoznaj się z <xliff:g id="info_url">%1$s </xliff:g>, aby uzyskać więcej informacji.</string>
<string name="export_channel_title">Eksport zakończony</string>
<string name="new_updates_channel_title">Nowe aktualizacje</string>
<string name="ongoing_channel_title">Trwające pobieranie</string>
<string name="update_failed_channel_title">Aktualizacja nie powiodła się</string>
<string name="info_dialog_title">Czy wiesz, że?</string>
<string name="info_dialog_message">Aktualizacje LineageOS to pełne pakiety instalacyjne. Oznacza to, że zawsze możesz zainstalować tylko najnowszą aktualizację, nawet jeśli poprzednie zostały pominięte!</string>
<string name="info_dialog_ok">Dziękujemy za informację!</string>
<string name="local_update_import">Aktualizacja lokalna</string>
<string name="local_update_import_progress">Importowanie aktualizacji lokalnej\u2026</string>
<string name="local_update_import_success">Zaimportowano %1$s. Czy chcesz to zainstalować?</string>
<string name="local_update_import_failure">Nie udało się zaimportować aktualizacji lokalnej</string>
<string name="local_update_import_install">Zainstaluj</string>
<string name="local_update_name">Aktualizacja lokalna</string>
</resources>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Atualizador</string>
<string name="display_name">Atualizador</string>
<string name="verification_failed_notification">Falha na verificação</string>
<string name="verifying_download_notification">Verificando atualização</string>
<string name="downloading_notification">Baixando</string>
<string name="download_paused_notification">Download pausado</string>
<string name="download_paused_error_notification">Erro ao baixar</string>
<string name="download_completed_notification">Download concluído</string>
<string name="download_starting_notification">Iniciando download</string>
<string name="update_failed_notification">Falha ao atualizar</string>
<string name="installation_suspended_notification">Instalação suspensa</string>
<string name="new_updates_found_title">Novas atualizações</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pausar</string>
<string name="resume_button">Continuar</string>
<string name="suspend_button">Suspender</string>
<string name="installing_update">Instalando o pacote de atualização</string>
<string name="installing_update_error">Erro de instalação</string>
<string name="installing_update_finished">Atualização instalada</string>
<string name="finalizing_package">Finalizando a instalação do pacote</string>
<string name="preparing_ota_first_boot">Preparando-se para a primeira inicialização</string>
<string name="dialog_prepare_zip_message">Preparação preliminar de atualização</string>
<string name="dialog_battery_low_title">Bateria fraca</string>
<string name="dialog_battery_low_message_pct">O nível da bateria está muito baixo, precisando de, pelo menos, <xliff:g id="percent_discharging">%1$d</xliff:g>%% de bateria para continuar, ou <xliff:g id="percent_charging">%2$d</xliff:g>%% se estiver carregando.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Execute os seguintes comandos e tente atualizar novamente:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Não é possível instalar a atualização com o OverlayFS montado</string>
<string name="reboot">Reiniciar</string>
<string name="menu_refresh">Atualizar</string>
<string name="menu_preferences">Preferências</string>
<string name="menu_auto_updates_check">Autoverificar por atualizações</string>
<string name="menu_auto_updates_check_interval_daily">Diariamente</string>
<string name="menu_auto_updates_check_interval_weekly">Semanalmente</string>
<string name="menu_auto_updates_check_interval_monthly">Mensalmente</string>
<string name="menu_auto_updates_check_interval_never">Nunca</string>
<string name="menu_auto_delete_updates">Excluir pacotes instalados</string>
<string name="menu_delete_update">Excluir</string>
<string name="menu_copy_url">Copiar URL</string>
<string name="menu_export_update">Exportar atualização</string>
<string name="menu_show_changelog">Mostrar alterações</string>
<string name="menu_ab_perf_mode">Priorizar o processo de atualização</string>
<string name="menu_update_recovery">Atualizar a recuperação</string>
<string name="toast_forced_update_recovery">Não é possível desativar as atualizações do Lineage Recovery neste dispositivo.</string>
<string name="snack_updates_found">Nova atualização disponível</string>
<string name="snack_no_updates_found">Não foram encontradas novas atualizações</string>
<string name="snack_updates_check_failed">Falha ao procurar por atualizações. Verifique sua conexão com a internet e tente novamente.</string>
<string name="snack_download_failed">Falha ao baixar a atualização. Verifique sua conexão com a internet e tente novamente.</string>
<string name="snack_download_verification_failed">Falha na verificação da atualização.</string>
<string name="snack_download_verified">Download concluído.</string>
<string name="snack_update_not_installable">Esta atualização não pode ser instalada por cima da versão atual.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Última verificação: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> às <xliff:g id="time" example="01:23">%2$s</xliff:g></string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verificando atualização</string>
<string name="list_no_updates">Não foram encontradas novas atualizações. Use o botão Atualizar para buscar por novas atualizações manualmente.</string>
<string name="action_download">Baixar</string>
<string name="action_pause">Pausar</string>
<string name="action_resume">Continuar</string>
<string name="action_install">Instalar</string>
<string name="action_info">Informações</string>
<string name="action_delete">Excluir</string>
<string name="action_cancel">Cancelar</string>
<string name="confirm_delete_dialog_title">Excluir arquivo</string>
<string name="confirm_delete_dialog_message">Excluir o arquivo de atualização selecionado?</string>
<string name="apply_update_dialog_title">Instalar atualização</string>
<string name="apply_update_dialog_message">Você está prestes a instalar <xliff:g id="update_name">%1$s</xliff:g>.\n\nSe você pressionar <xliff:g id="ok">%2$s</xliff:g>, o dispositivo será reiniciado no modo de recuperação para instalar a atualização.\n\nObservação: Esse recurso requer uma recuperação compatível ou as atualizações precisarão ser instaladas manualmente.</string>
<string name="apply_update_dialog_message_ab">Você está prestes a instalar <xliff:g id="update_name">%1$s</xliff:g>.\n\nSe você pressionar <xliff:g id="ok">%2$s</xliff:g>, a instalação do dispositivo começará em segundo plano.\n\nDepois de concluído, você será solicitado a reiniciar o dispositivo.</string>
<string name="cancel_installation_dialog_message">Deseja cancelar a instalação?</string>
<string name="label_download_url">URL de Download</string>
<string name="toast_download_url_copied">URL copiado</string>
<string name="dialog_export_title">Exportando atualização</string>
<string name="notification_export_success">Atualização exportada</string>
<string name="notification_export_fail">Falha ao exportar</string>
<string name="toast_already_exporting">Uma atualização já está sendo exportada</string>
<string name="toast_export_started">Exportação iniciada</string>
<plurals name="eta_seconds">
<item quantity="one">1 segundo restante</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> segundos restantes</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minuto restante</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutos restantes</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 hora restante</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> horas restantes</item>
</plurals>
<string name="update_over_metered_network_title">Aviso</string>
<string name="update_over_metered_network_message">Você está prestes a baixar um pacote de atualização usando os dados móveis, o que provavelmente causará um alto consumo de dados. Deseja continuar?</string>
<string name="checkbox_metered_network_warning">Não mostrar novamente</string>
<string name="menu_metered_network_warning">Aviso de rede limitada</string>
<string name="blocked_update_dialog_title">Atualização bloqueada</string>
<string name="blocked_update_dialog_message">Esta atualização não pode ser instalada pelo Atualizador. Leia <xliff:g id="info_url">%1$s</xliff:g> para obter mais informações.</string>
<string name="export_channel_title">Exportação concluída</string>
<string name="new_updates_channel_title">Novas atualizações</string>
<string name="ongoing_channel_title">Downloads em andamento</string>
<string name="update_failed_channel_title">Falha ao atualizar</string>
<string name="info_dialog_title">Você sabia?</string>
<string name="info_dialog_message">As atualizações do LineageOS são pacotes de instalação completos. Isso significa que você sempre pode instalar apenas a atualização mais recente, mesmo que você tenha ignorado versões anteriores!</string>
<string name="info_dialog_ok">Agradecemos o seu comentário!</string>
<string name="local_update_import">Atualização local</string>
<string name="local_update_import_progress">Importando atualização local\u2026</string>
<string name="local_update_import_success">%1$s foi importado. Você quer instalá-lo?</string>
<string name="local_update_import_failure">Falha ao importar a atualização local</string>
<string name="local_update_import_install">Instalar</string>
<string name="local_update_name">Atualização local</string>
</resources>

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Atualizador</string>
<string name="display_name">Atualizador</string>
<string name="verification_failed_notification">Verificação falhou</string>
<string name="verifying_download_notification">A verificar atualização</string>
<string name="downloading_notification">A transferir</string>
<string name="download_paused_notification">Transferência em pausa</string>
<string name="download_paused_error_notification">Erro na transferência</string>
<string name="download_completed_notification">Transferência concluída</string>
<string name="download_starting_notification">A iniciar a transferência</string>
<string name="update_failed_notification">A atualização falhou</string>
<string name="installation_suspended_notification">Instalação suspensa</string>
<string name="new_updates_found_title">Novas atualizações</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pausar</string>
<string name="resume_button">Continuar</string>
<string name="suspend_button">Suspender</string>
<string name="installing_update">A instalar o pacote de atualização</string>
<string name="installing_update_error">Erro de instalação</string>
<string name="installing_update_finished">Atualização instalada</string>
<string name="finalizing_package">A finalizar a instalação do pacote</string>
<string name="preparing_ota_first_boot">A preparar para a primeira inicialização</string>
<string name="dialog_prepare_zip_message">Preparação preliminar de atualização</string>
<string name="dialog_battery_low_title">Bateria fraca</string>
<string name="dialog_battery_low_message_pct">O nível da bateria está demasiado baixo. Precisa de, pelo menos, <xliff:g id="percent_discharging">%1$d</xliff:g>%% de bateria para continuar, <xliff:g id="percent_charging">%2$d</xliff:g>%% se estiver a carregar.</string>
<string name="reboot">Reiniciar</string>
<string name="menu_refresh">Atualizar</string>
<string name="menu_preferences">Preferências</string>
<string name="menu_auto_updates_check">Verificação automática de atualizações</string>
<string name="menu_auto_updates_check_interval_daily">Uma vez por dia</string>
<string name="menu_auto_updates_check_interval_weekly">Uma vez por semana</string>
<string name="menu_auto_updates_check_interval_monthly">Uma vez por mês</string>
<string name="menu_auto_updates_check_interval_never">Nunca</string>
<string name="menu_auto_delete_updates">Apagar atualizações depois de instaladas</string>
<string name="menu_delete_update">Apagar</string>
<string name="menu_copy_url">Copiar URL</string>
<string name="menu_export_update">Exportar atualização</string>
<string name="menu_show_changelog">Mostrar registo de alterações</string>
<string name="menu_ab_perf_mode">Priorizar o processo de atualização</string>
<string name="menu_update_recovery">Atualizar recuperação</string>
<string name="toast_forced_update_recovery">Não é possível desativar as atualizações da recuperação Lineage neste dispositivo.</string>
<string name="snack_updates_found">Não foram encontradas atualizações</string>
<string name="snack_no_updates_found">Não foram encontradas novas atualizações</string>
<string name="snack_updates_check_failed">A verificação de atualizações falhou. Por favor, verifique a sua ligação à internet e tente novamente.</string>
<string name="snack_download_failed">A transferência falhou. Por favor, verifique a sua ligação à internet e tente novamente.</string>
<string name="snack_download_verification_failed">A verificação da atualização falhou.</string>
<string name="snack_download_verified">Transferência concluída.</string>
<string name="snack_update_not_installable">Esta atualização não pode ser instalada por cima da compilação atual.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Última verificação: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> de <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">A verificar atualização</string>
<string name="list_no_updates">Não foram encontradas novas atualizações. Para verificar novas atualizações manualmente, use o botão Atualizar.</string>
<string name="action_download">Transferir</string>
<string name="action_pause">Pausar</string>
<string name="action_resume">Retomar</string>
<string name="action_install">Instalar</string>
<string name="action_info">Informações</string>
<string name="action_delete">Eliminar</string>
<string name="action_cancel">Cancelar</string>
<string name="confirm_delete_dialog_title">Eliminar ficheiro</string>
<string name="confirm_delete_dialog_message">Deseja eliminar o ficheiro de atualizações selecionado?</string>
<string name="apply_update_dialog_title">Aplicar atualização</string>
<string name="apply_update_dialog_message">Está prestes a atualizar para <xliff:g id="update_name">%1$s</xliff:g>.\n\nSe carregar em<xliff:g id="ok">%2$s</xliff:g>, o dispositivo irá reiniciar no modo de recuperação para instalar a atualização.\n\nNota: É necessária uma Recuperação compatível, caso contrário as atualizações terão de ser instaladas manualmente.</string>
<string name="apply_update_dialog_message_ab">Está prestes a atualizar para <xliff:g id="update_name">%1$s</xliff:g>.\n\nSe selecionar <xliff:g id="ok">%2$s</xliff:g>, o dispositivo irá iniciar a instalação em segundo plano.\n\nUma vez concluída, ser-lhe-á pedido que reinicie o dispositivo.</string>
<string name="cancel_installation_dialog_message">Cancelar a instalação?</string>
<string name="label_download_url">URL de transferência</string>
<string name="toast_download_url_copied">URL copiado</string>
<string name="dialog_export_title">A exportar a atualização</string>
<string name="notification_export_success">Atualização exportada</string>
<string name="notification_export_fail">Erro de exportação</string>
<string name="toast_already_exporting">Já está a exportar uma atualização</string>
<string name="toast_export_started">Exportação iniciada</string>
<plurals name="eta_seconds">
<item quantity="one">1 segundo restante</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> segundos restantes</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minuto restante</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> minutos restantes</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 hora restante</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> horas restantes</item>
</plurals>
<string name="update_over_metered_network_title">Aviso</string>
<string name="checkbox_metered_network_warning">Não mostrar novamente</string>
<string name="blocked_update_dialog_title">Atualização bloqueada</string>
<string name="blocked_update_dialog_message">Esta atualização não pode ser instalada usando a aplicação do atualizador. Por favor, leia <xliff:g id="info_url">%1$s </xliff:g> para mais informações.</string>
<string name="export_channel_title">Conclusão da exportação</string>
<string name="new_updates_channel_title">Novas atualizações</string>
<string name="ongoing_channel_title">Transferências em curso</string>
<string name="update_failed_channel_title">A atualização falhou</string>
<string name="info_dialog_title">Sabias que?</string>
<string name="info_dialog_message">As atualizações do LineageOS são pacotes de instalação completa. Isso significa que podes instalar apenas a última atualização, mesmo que tenhas ignorado alguns deles!</string>
<string name="info_dialog_ok">Obrigado pela informação!</string>
</resources>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Actualizator</string>
<string name="display_name">Actualizator</string>
<string name="verification_failed_notification">Verificarea a eșuat</string>
<string name="verifying_download_notification">Verificare actualizare</string>
<string name="downloading_notification">Descărcare</string>
<string name="download_paused_notification">Descărcare întreruptă</string>
<string name="download_paused_error_notification">Eroare la descărcare</string>
<string name="download_completed_notification">Descărcare terminată</string>
<string name="download_starting_notification">Pornire descărcare</string>
<string name="update_failed_notification">Actualizare eșuată</string>
<string name="installation_suspended_notification">Instalarea a fost suspendată</string>
<string name="new_updates_found_title">Actualizări noi</string>
<string name="text_download_speed">%1$s, %2$s/s</string>
<string name="pause_button">Pauză</string>
<string name="resume_button">Reluaţi</string>
<string name="suspend_button">Suspendă</string>
<string name="installing_update">Se instalează pachetul de actualizare</string>
<string name="installing_update_error">Eroare la instalare</string>
<string name="installing_update_finished">Actualizare instalată</string>
<string name="finalizing_package">Se finalizează instalarea pachetului</string>
<string name="preparing_ota_first_boot">Se pregătește pentru prima pornire</string>
<string name="dialog_prepare_zip_message">Pregătire preliminară pentru actualizare</string>
<string name="dialog_battery_low_title">Baterie slabă</string>
<string name="dialog_battery_low_message_pct">Nivelul bateriei este prea scăzut. Aveți nevoie de cel puțin<xliff:g id="percent_discharging">%1$d</xliff:g>%% pentru a continua, <xliff:g id="percent_charging">%2$d</xliff:g>%% dacă telefonul este la încărcat.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Vă rugăm să rulați următoarele și să reîncărcați actualizarea:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Nu se poate instala actualizarea cu OverlayFS montat</string>
<string name="reboot">Repornire</string>
<string name="menu_refresh">Reîmprospătare</string>
<string name="menu_preferences">Preferințe</string>
<string name="menu_auto_updates_check">Verificare automată a actualizărilor</string>
<string name="menu_auto_updates_check_interval_daily">Odată pe zi</string>
<string name="menu_auto_updates_check_interval_weekly">Odată pe săptămână</string>
<string name="menu_auto_updates_check_interval_monthly">Odată pe lună</string>
<string name="menu_auto_updates_check_interval_never">Niciodată</string>
<string name="menu_auto_delete_updates">Şterge actualizările atunci când sunt instalate</string>
<string name="menu_delete_update">Șterge</string>
<string name="menu_copy_url">Copiază URL</string>
<string name="menu_export_update">Exportează actualizarea</string>
<string name="menu_show_changelog">Arată changelog</string>
<string name="menu_ab_perf_mode">Proces update prioritar</string>
<string name="menu_update_recovery">Actualizare recovery</string>
<string name="toast_forced_update_recovery">Este imposibil să dezactivați actualizarea Lineage Recovery pe acest dispozitiv.</string>
<string name="snack_updates_found">Noi actualizări găsite</string>
<string name="snack_no_updates_found">Nu s-au găsit actualizări noi</string>
<string name="snack_updates_check_failed">Verificarea actualizării a eșuat. Vă rugăm să verificați conexiunea la internet și să încercați din nou mai târziu.</string>
<string name="snack_download_failed">Descărcarea a eșuat. Vă rugăm să verificați conexiunea la internet și să încercați din nou mai târziu.</string>
<string name="snack_download_verification_failed">Verificarea actualizării a eșuat.</string>
<string name="snack_download_verified">Descărcare terminată.</string>
<string name="snack_update_not_installable">Această actualizare nu poate fi instalată pe build-ul curent.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Ultima verificare: <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> (<xliff:g id="time" example="01:23">%2$s</xliff:g>)</string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> din <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> din <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Verificare actualizare</string>
<string name="list_no_updates">Nicio actualizare nouă găsită. Pentru a verifica manual pentru noi actualizări, utilizați butonul Reîmprospătare.</string>
<string name="action_download">Descărcați</string>
<string name="action_pause">Pauză</string>
<string name="action_resume">Reluaţi</string>
<string name="action_install">Instalați</string>
<string name="action_info">Info</string>
<string name="action_delete">Ștergeți</string>
<string name="action_cancel">Anulare</string>
<string name="confirm_delete_dialog_title">Ștergeți fișierul</string>
<string name="confirm_delete_dialog_message">Șterge fișierul de actualizare selectat?</string>
<string name="apply_update_dialog_title">Aplicaţi actualizarea</string>
<string name="apply_update_dialog_message">Sunteți pe cale să instalați <xliff:g id="update_name">%1$s</xliff:g>.\n\nDacă apăsați <xliff:g id="ok">%2$s</xliff:g>, dispozitivul va reporni în modul recuperare pentru a instala actualizarea.\n\nNotă: Această caracteristică necesită un Recovery compatibil ori actualizările vor trebui instalate manual.</string>
<string name="apply_update_dialog_message_ab">Sunteți pe cale să instalați <xliff:g id="update_name">%1$s</xliff:g>.\n\nDacă apăsați <xliff:g id="ok">%2$s</xliff:g>, dispozitivul va începe instalarea în fundal.\n\nOdată terminată, vi se va solicita să reporniți dispozitivul.</string>
<string name="cancel_installation_dialog_message">Revocaţi instalarea?</string>
<string name="label_download_url">Descărcați URL-ul</string>
<string name="toast_download_url_copied">URL copiat</string>
<string name="dialog_export_title">Exportare actualizare</string>
<string name="notification_export_success">Actualizare exportată</string>
<string name="notification_export_fail">Eroare de export</string>
<string name="toast_already_exporting">Se exportează deja o actualizare</string>
<string name="toast_export_started">Export inițiat</string>
<plurals name="eta_seconds">
<item quantity="one">1 secundă rămasă</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> (de) secunde rămase</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> (de) secunde rămase</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">1 minut rămas</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> (de) minute rămase</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> (de) minute rămase</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">1 oră rămasă</item>
<item quantity="few"><xliff:g id="count">%d</xliff:g> (de) ore rămase</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> (de) ore rămase</item>
</plurals>
<string name="update_over_metered_network_title">Avertizare</string>
<string name="update_over_metered_network_message">Sunteți pe cale să descărcați un pachet de actualizare printr-o rețea contorizată care va cauza probabil un consum ridicat de date. Doriți să continuați?</string>
<string name="checkbox_metered_network_warning">Nu mai afişa</string>
<string name="menu_metered_network_warning">Avertizare rețea contorizată</string>
<string name="blocked_update_dialog_title">Actualizare blocată</string>
<string name="blocked_update_dialog_message">Această actualizare nu poate fi instalată folosind aplicația actualizator. Vă rugăm să citiţi <xliff:g id="info_url">%1$s</xliff:g> pentru mai multe informaţii.</string>
<string name="export_channel_title">Completare export</string>
<string name="new_updates_channel_title">Actualizări noi</string>
<string name="ongoing_channel_title">Descărcări în desfășurare</string>
<string name="update_failed_channel_title">Actualizare eșuată</string>
<string name="info_dialog_title">Știai că?</string>
<string name="info_dialog_message">Actualizările LineageOS sunt pachete complete de instalare. Acest lucru înseamnă că întotdeauna puteți instala doar ultima actualizare, chiar dacă ați sărit unele dintre ele!</string>
<string name="info_dialog_ok">Mulțumesc pentru informații!</string>
<string name="local_update_import">Actualizare locală</string>
<string name="local_update_import_progress">Importare actualizare locală\u2026</string>
<string name="local_update_import_success">%1$s a fost importată. Doriți să o instalați?</string>
<string name="local_update_import_failure">Eroare la importarea actualizării locale</string>
<string name="local_update_import_install">Instalați</string>
<string name="local_update_name">Actualizare locală</string>
</resources>

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Обновления системы</string>
<string name="display_name">Обновления системы</string>
<string name="verification_failed_notification">Проверка не удалась</string>
<string name="verifying_download_notification">Проверка обновления</string>
<string name="downloading_notification">Загрузка</string>
<string name="download_paused_notification">Загрузка приостановлена</string>
<string name="download_paused_error_notification">Ошибка при загрузке</string>
<string name="download_completed_notification">Загрузка завершена</string>
<string name="download_starting_notification">Загрузка началась</string>
<string name="update_failed_notification">Сбой обновления</string>
<string name="installation_suspended_notification">Установка приостановлена</string>
<string name="new_updates_found_title">Доступны обновления</string>
<string name="text_download_speed">%1$s, %2$s/с</string>
<string name="pause_button">Пауза</string>
<string name="resume_button">Возобновить</string>
<string name="suspend_button">Приостановить</string>
<string name="installing_update">Установка обновлений</string>
<string name="installing_update_error">Ошибка установки</string>
<string name="installing_update_finished">Обновление установлено</string>
<string name="finalizing_package">Завершение установки</string>
<string name="preparing_ota_first_boot">Подготовка к первому запуску</string>
<string name="dialog_prepare_zip_message">Подготовка обновления</string>
<string name="dialog_battery_low_title">Низкий заряд батареи</string>
<string name="dialog_battery_low_message_pct">Заряд батареи слишком мал. Для продолжения требуется не менее <xliff:g id="percent_discharging">%1$d</xliff:g>%% или более <xliff:g id="percent_charging">%2$d</xliff:g>%% при подключенном зарядном устройстве.</string>
<string name="dialog_scratch_mounted_message"><![CDATA[ Выполните следующие команды и повторите попытку обновления:\n
• adb root\n
• adb enable-verity\n
• adb reboot
]]></string>
<string name="dialog_scratch_mounted_title">Невозможно установить обновление при примонтированной OverlayFS</string>
<string name="reboot">Перезапуск</string>
<string name="menu_refresh">Обновить</string>
<string name="menu_preferences">Настройки</string>
<string name="menu_auto_updates_check">Автоматическая проверка обновлений</string>
<string name="menu_auto_updates_check_interval_daily">Раз в день</string>
<string name="menu_auto_updates_check_interval_weekly">Раз в неделю</string>
<string name="menu_auto_updates_check_interval_monthly">Раз в месяц</string>
<string name="menu_auto_updates_check_interval_never">Никогда</string>
<string name="menu_auto_delete_updates">Удалить файлы обновления после установки</string>
<string name="menu_delete_update">Удалить</string>
<string name="menu_copy_url">Скопировать URL</string>
<string name="menu_export_update">Экспорт обновлений</string>
<string name="menu_show_changelog">Показать журнал изменений</string>
<string name="menu_ab_perf_mode">Приоритет процесса обновления</string>
<string name="menu_update_recovery">Обновлять Recovery</string>
<string name="toast_forced_update_recovery">Отключить обновления Lineage Recovery на этом устройстве невозможно.</string>
<string name="snack_updates_found">Доступно обновление</string>
<string name="snack_no_updates_found">Обновлений не найдено</string>
<string name="snack_updates_check_failed">Проверка обновлений не удалась. Проверьте подключение к интернету и повторите попытку.</string>
<string name="snack_download_failed">Загрузка не удалась. Проверьте подключение к интернету и повторите попытку.</string>
<string name="snack_download_verification_failed">Ошибка проверки обновления.</string>
<string name="snack_download_verified">Загрузка завершена.</string>
<string name="snack_update_not_installable">Это обновление не может быть установлено поверх текущей сборки.</string>
<string name="header_title_text">LineageOS\n%1$s</string>
<string name="header_android_version">Android <xliff:g id="version" example="7.1.2">%1$s</xliff:g></string>
<string name="header_last_updates_check">Поиск обновлений выполнялся <xliff:g id="date" example="1 January 1970">%1$s</xliff:g> в <xliff:g id="time" example="01:23">%2$s</xliff:g></string>
<string name="list_build_version">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g></string>
<string name="list_build_version_date">LineageOS <xliff:g id="version" example="14.1">%1$s</xliff:g> - <xliff:g id="date" example="July 11, 2017">%2$s</xliff:g></string>
<string name="list_download_progress_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> из <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g></string>
<string name="list_download_progress_eta_newer"><xliff:g id="filesize_without_unit" example="12.2">%1$s</xliff:g> из <xliff:g id="filesize_without_unit" example="310 MB">%2$s</xliff:g> (<xliff:g id="eta" example="3 minutes left">%3$s</xliff:g>)</string>
<string name="list_verifying_update">Проверка обновлений</string>
<string name="list_no_updates">Обновлений не найдено. Чтобы проверить наличие обновлений вручную, используйте кнопку Обновить.</string>
<string name="action_download">Скачать</string>
<string name="action_pause">Приостановить</string>
<string name="action_resume">Возобновить</string>
<string name="action_install">Установить</string>
<string name="action_info">Информация</string>
<string name="action_delete">Удалить</string>
<string name="action_cancel">Отмена</string>
<string name="confirm_delete_dialog_title">Удалить файл</string>
<string name="confirm_delete_dialog_message">Удалить выбранный файл обновления?</string>
<string name="apply_update_dialog_title">Применить обновление</string>
<string name="apply_update_dialog_message">Будет выполнена установка <xliff:g id="update_name">%1$s</xliff:g>.\n\nПри нажатии кнопки <xliff:g id="ok">%2$s</xliff:g> устройство будет перезапущено в режиме Recovery для установки новой версии.\n\nПримечание: для использования данной возможности необходим совместимый Recovery. При возникновении ошибки обновление потребуется установить вручную.</string>
<string name="apply_update_dialog_message_ab">Будет выполнена установка <xliff:g id="update_name">%1$s</xliff:g>.\n\nПри нажатии кнопки <xliff:g id="ok">%2$s</xliff:g> будет начата установка в фоновом режиме.\n\nПо завершении вам будет предложено перезапустить устройство.</string>
<string name="cancel_installation_dialog_message">Отменить установку?</string>
<string name="label_download_url">Ссылка для скачивания</string>
<string name="toast_download_url_copied">URL скопирован в буфер обмена</string>
<string name="dialog_export_title">Экспорт обновлений</string>
<string name="notification_export_success">Обновление экспортировано</string>
<string name="notification_export_fail">Ошибка экспорта</string>
<string name="toast_already_exporting">Экспорт уже выполняется</string>
<string name="toast_export_started">Экспорт начат</string>
<plurals name="eta_seconds">
<item quantity="one">осталась <xliff:g id="count">%d</xliff:g> секунда</item>
<item quantity="few">осталось <xliff:g id="count">%d</xliff:g> секунды</item>
<item quantity="many">осталось <xliff:g id="count">%d</xliff:g> секунд</item>
<item quantity="other">осталось <xliff:g id="count">%d</xliff:g> секунд</item>
</plurals>
<plurals name="eta_minutes">
<item quantity="one">осталась <xliff:g id="count">%d</xliff:g> минута</item>
<item quantity="few">осталось <xliff:g id="count">%d</xliff:g> минуты</item>
<item quantity="many">осталось <xliff:g id="count">%d</xliff:g> минут</item>
<item quantity="other">осталось <xliff:g id="count">%d</xliff:g> минут</item>
</plurals>
<plurals name="eta_hours">
<item quantity="one">остался <xliff:g id="count">%d</xliff:g> час</item>
<item quantity="few">осталось <xliff:g id="count">%d</xliff:g> часа</item>
<item quantity="many">осталось <xliff:g id="count">%d</xliff:g> часов</item>
<item quantity="other">осталось <xliff:g id="count">%d</xliff:g> часов</item>
</plurals>
<string name="update_over_metered_network_title">Предупреждение</string>
<string name="update_over_metered_network_message">Вы собираетесь загрузить пакет обновления через мобильную сеть, что, вероятно, приведет к значительному расходу данных. Продолжить?</string>
<string name="checkbox_metered_network_warning">Не показывать это сообщение</string>
<string name="menu_metered_network_warning">Предупреждение о сети с тарификацией</string>
<string name="blocked_update_dialog_title">Обновление заблокировано</string>
<string name="blocked_update_dialog_message">Эту сборку нельзя установить с помощью встроенной системы обновления. Для получения дополнительной информации ознакомьтесь с <xliff:g id="info_url">%1$s</xliff:g>.</string>
<string name="export_channel_title">Экспорт завершен</string>
<string name="new_updates_channel_title">Доступны обновления</string>
<string name="ongoing_channel_title">Текущие загрузки</string>
<string name="update_failed_channel_title">Сбой обновления</string>
<string name="info_dialog_title">Знаете ли вы?</string>
<string name="info_dialog_message">Обновления LineageOS представляют собой полные установочные пакеты. Это означает, что вы всегда можете установить только последнее обновление, даже если вы пропустили некоторые из них!</string>
<string name="info_dialog_ok">Спасибо за информацию!</string>
<string name="local_update_import">Локальное обновление</string>
<string name="local_update_import_progress">Импорт локального обновления\u2026</string>
<string name="local_update_import_success">Обновление %1$s было импортировано. Установить его?</string>
<string name="local_update_import_failure">Не удалось импортировать локальное обновление</string>
<string name="local_update_import_install">Установить</string>
<string name="local_update_name">Локальное обновление</string>
</resources>

Some files were not shown because too many files have changed in this diff Show More