Merge "DO NOT MERGE. Use resolved path when inserting and deleting." into mnc-dr1...
Jeff Sharkey [Thu, 18 Feb 2016 19:36:42 +0000 (19:36 +0000)]
am: 102cab3e7d  -s ours

* commit '102cab3e7deee3392a4d4bf818fabc527db0a222':
  DO NOT MERGE. Use resolved path when inserting and deleting.

22 files changed:
Android.mk
res/values-b+sr+Latn/strings.xml [new file with mode: 0644]
res/values-bs-rBA/strings.xml [new file with mode: 0644]
res/values-ro/strings.xml
res/values-uz-rUZ/strings.xml
src/com/android/providers/downloads/Constants.java
src/com/android/providers/downloads/DownloadNotifier.java
src/com/android/providers/downloads/DownloadProvider.java
src/com/android/providers/downloads/DownloadReceiver.java
src/com/android/providers/downloads/DownloadService.java
src/com/android/providers/downloads/DownloadStorageProvider.java
src/com/android/providers/downloads/Helpers.java
src/com/android/providers/downloads/OpenHelper.java
tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java
tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java
tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
ui/res/values-b+sr+Latn/strings.xml [new file with mode: 0644]
ui/res/values-bn-rBD/strings.xml
ui/res/values-bs-rBA/strings.xml [new file with mode: 0644]
ui/res/values-ro/strings.xml
ui/src/com/android/providers/downloads/ui/TrampolineActivity.java

index a2f1e96..d69e42f 100644 (file)
@@ -5,11 +5,11 @@ LOCAL_MODULE_TAGS := optional
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-
 LOCAL_PACKAGE_NAME := DownloadProvider
 LOCAL_CERTIFICATE := media
 LOCAL_PRIVILEGED_MODULE := true
-LOCAL_STATIC_JAVA_LIBRARIES := guava
+LOCAL_STATIC_JAVA_LIBRARIES := guava \
+    android-support-documents-archive
 
 include $(BUILD_PACKAGE)
 
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
new file mode 100644 (file)
index 0000000..75b38d1
--- /dev/null
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" msgid="3658948994665187911">"Menadžer preuzimanja"</string>
+    <string name="permlab_downloadManager" msgid="7779544811202855500">"Pristup menadžeru preuzimanja."</string>
+    <string name="permdesc_downloadManager" msgid="4237406545998908947">"Omogućava aplikaciji da pristupa menadžeru preuzimanja i koristi ga za preuzimanje datoteka. Zlonamerne aplikacije mogu pomoću toga da ometaju preuzimanja i pristupaju privatnim informacijama."</string>
+    <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Napredne funkcije menadžera preuzimanja."</string>
+    <string name="permdesc_downloadManagerAdvanced" msgid="2659546004160962761">"Omogućava aplikaciji da pristupa naprednim funkcijama menadžera preuzimanja. Zlonamerne aplikacije mogu pomoću toga da ometaju preuzimanja i pristupaju privatnim informacijama."</string>
+    <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Šaljite obaveštenja o preuzimanjima."</string>
+    <string name="permdesc_downloadCompletedIntent" msgid="2094706189855699533">"Omogućava aplikaciji da šalje obaveštenja o dovršenim preuzimanjima. Zlonamerne aplikacije mogu pomoću toga da zbune ostale aplikacije koje preuzimaju datoteke."</string>
+    <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Pogledajte sva preuzimanja u USB memoriju"</string>
+    <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Sva preuzimanja na SD karticu"</string>
+    <string name="permdesc_seeAllExternal" msgid="1672759909065511233">"Omogućava aplikaciji da vidi sve stavke preuzete na SD karticu, bez obzira na to koja aplikacija ih je preuzela."</string>
+    <string name="permlab_downloadCacheNonPurgeable" msgid="3069534308882047412">"Rezerviši prostor u kešu za preuzimanje"</string>
+    <string name="permdesc_downloadCacheNonPurgeable" msgid="2408760720334570420">"Omogućava aplikaciji da preuzima datoteke u keš za preuzimanje koji ne može automatski da se izbriše kada je menadžeru preuzimanja potrebno još prostora."</string>
+    <string name="permlab_downloadWithoutNotification" msgid="8837971946078327262">"preuzmi datoteke bez obaveštenja"</string>
+    <string name="permdesc_downloadWithoutNotification" msgid="8483135034298639727">"Omogućava aplikaciji da preuzima datoteke preko menadžera preuzimanja bez prikazivanja ikakvog obaveštenja korisniku."</string>
+    <string name="permlab_accessAllDownloads" msgid="2436240495424393717">"Pristupi svim sistemskim preuzimanjima"</string>
+    <string name="permdesc_accessAllDownloads" msgid="1871832254578267128">"Omogućava aplikaciji da pregleda i menja sva preuzimanja koja je pokrenula bilo koja aplikacija u sistemu."</string>
+    <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Bez naslova&gt;"</string>
+    <string name="notification_download_complete" msgid="5443563299253103667">"Preuzimanje je završeno."</string>
+    <string name="notification_download_failed" msgid="8612136111952014978">"Preuzimanje nije uspelo."</string>
+    <string name="notification_need_wifi_for_size" msgid="2556172885154833575">"Veličina stavke zahteva Wi-Fi."</string>
+    <string name="notification_paused_in_background" msgid="4328508073283591772">"Pauzirano u pozadini."</string>
+    <string name="wifi_required_title" msgid="1995971416871498179">"Preuzimanje je preveliko za mrežu operatera"</string>
+    <string name="wifi_required_body" msgid="3067694630143784449">"Morate da koristite Wi-Fi da biste dovršili ovo preuzimanje od <xliff:g id="SIZE">%s </xliff:g>. \n\nDodirnite <xliff:g id="QUEUE_TEXT">%s </xliff:g> da biste započeli ovo preuzimanje kada se sledeći put povežete sa Wi-Fi mrežom."</string>
+    <string name="wifi_recommended_title" msgid="7441589306734687400">"Želite li da stavite u red za buduće preuzimanje?"</string>
+    <string name="wifi_recommended_body" msgid="1314735166699936073">"Ovim preuzimanjem od <xliff:g id="SIZE">%s </xliff:g> možete da skratite vek trajanja baterije i/ili preterano koristite mobilnu vezu za prenos podataka, što može da dovede do troškova kod mobilnog operatera shodno tarifnom paketu.\n\n Dodirnite <xliff:g id="QUEUE_TEXT">%s</xliff:g> da biste započeli ovo preuzimanje kada se ponovo povežete sa Wi-Fi mrežom."</string>
+    <string name="button_queue_for_wifi" msgid="422576726189179221">"Red"</string>
+    <string name="button_cancel_download" msgid="2430166148737975604">"Otkaži"</string>
+    <string name="button_start_now" msgid="792123674007840864">"Započni odmah"</string>
+    <plurals name="notif_summary_active" formatted="false" msgid="7290448463204837173">
+      <item quantity="one">Preuzima se <xliff:g id="NUMBER">%d</xliff:g> datoteka</item>
+      <item quantity="few">Preuzimaju se <xliff:g id="NUMBER">%d</xliff:g> datoteke</item>
+      <item quantity="other">Preuzima se <xliff:g id="NUMBER">%d</xliff:g> datoteka</item>
+    </plurals>
+    <plurals name="notif_summary_waiting" formatted="false" msgid="2814217662029273005">
+      <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> datoteka je na čekanju</item>
+      <item quantity="few"><xliff:g id="NUMBER">%d</xliff:g> datoteke su na čekanju</item>
+      <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> datoteka je na čekanju</item>
+    </plurals>
+    <string name="download_remaining" msgid="3139295890887972718">"Još <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="download_no_application_title" msgid="7935659741162801699">"Nije moguće otvoriti datoteku"</string>
+    <string name="root_downloads" msgid="4098414876292351487">"Preuzimanja"</string>
+    <string name="download_queued" msgid="3302638231377947451">"Stavljeno je na čekanje"</string>
+    <string name="download_running" msgid="3925050393361158266">"U toku je"</string>
+    <string name="download_error" msgid="5144180777324573236">"Nije uspelo"</string>
+    <string name="download_running_percent" msgid="4305080769167320204">"U toku, <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-bs-rBA/strings.xml b/res/values-bs-rBA/strings.xml
new file mode 100644 (file)
index 0000000..a738b80
--- /dev/null
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" msgid="3658948994665187911">"Upravitelj za preuzimanja"</string>
+    <string name="permlab_downloadManager" msgid="7779544811202855500">"Pristupite upravitelju za preuzimanja."</string>
+    <string name="permdesc_downloadManager" msgid="4237406545998908947">"Dopušta aplikacijama da pristupaju upravitelju za preuzimanja i koriste ga za preuzimanje datoteka. Zlonamjerne aplikacije to mogu koristiti da poremete preuzimanja i pristupaju privatnim informacijama."</string>
+    <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Napredne funkcije upravitelja za preuzimanja."</string>
+    <string name="permdesc_downloadManagerAdvanced" msgid="2659546004160962761">"Dopušta aplikaciji da pristupa naprednim funkcijama upravitelja za preuzimanja. Zlonamjerne aplikacije to mogu koristiti da poremete preuzimanja i pristupaju privatnim informacijama."</string>
+    <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Šaljite obavještenja o preuzimanju."</string>
+    <string name="permdesc_downloadCompletedIntent" msgid="2094706189855699533">"Dopušta aplikaciji da šalje obavještenja o završenim ažuriranjima. Zlonamjerne aplikacije ovo mogu koristiti da zbune druge aplikacije koje preuzimaju datoteke."</string>
+    <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Prikaži sva preuzimanja na USB pohranu"</string>
+    <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Prikaži sva preuzimanja na SD karticu"</string>
+    <string name="permdesc_seeAllExternal" msgid="1672759909065511233">"Dopušta aplikaciji da vidi sva preuzimanja na SD kartici, bez obzira na to koja ih je aplikacija izvršila."</string>
+    <string name="permlab_downloadCacheNonPurgeable" msgid="3069534308882047412">"Rezerviraj mjesto u keš memoriji preuzimanja"</string>
+    <string name="permdesc_downloadCacheNonPurgeable" msgid="2408760720334570420">"Dopušta aplikaciji da preuzme datoteke u keš memoriju preuzimanja, koja se ne može automatski izbrisati kada upravitelju za preuzimanja treba više prostora."</string>
+    <string name="permlab_downloadWithoutNotification" msgid="8837971946078327262">"preuzimanje datoteka bez obavještenja"</string>
+    <string name="permdesc_downloadWithoutNotification" msgid="8483135034298639727">"Dopušta aplikaciji da preuzima datoteke preko upravitelja za preuzimanja bez prikazivanja obavještenja korisniku."</string>
+    <string name="permlab_accessAllDownloads" msgid="2436240495424393717">"Pristup svim preuzimanjima sistema"</string>
+    <string name="permdesc_accessAllDownloads" msgid="1871832254578267128">"Dopušta aplikaciji da prikaže i modificira sva preuzimanja koja pokrene bilo koja aplikacija u sistemu."</string>
+    <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Bez naslova&gt;"</string>
+    <string name="notification_download_complete" msgid="5443563299253103667">"Preuzimanje završeno."</string>
+    <string name="notification_download_failed" msgid="8612136111952014978">"Preuzimanje neuspješno."</string>
+    <string name="notification_need_wifi_for_size" msgid="2556172885154833575">"Veličina preuzimanja zahtjeva Wi-Fi."</string>
+    <string name="notification_paused_in_background" msgid="4328508073283591772">"Pauzirano u pozadini."</string>
+    <string name="wifi_required_title" msgid="1995971416871498179">"Preuzimanje je preveliko za mrežu operatera"</string>
+    <string name="wifi_required_body" msgid="3067694630143784449">"Morate koristiti Wi-Fi kako biste dovršili ovo preuzimanje od <xliff:g id="SIZE">%s </xliff:g>. \n\nDodirnite <xliff:g id="QUEUE_TEXT">%s </xliff:g> kako biste pokrenuli ovo preuzimanje kada se narednog puta povežete na Wi-Fi mrežu."</string>
+    <string name="wifi_recommended_title" msgid="7441589306734687400">"Staviti u redoslijed za preuzimanje kasnije?"</string>
+    <string name="wifi_recommended_body" msgid="1314735166699936073">"Pokretanje ovog preuzimanja od <xliff:g id="SIZE">%s </xliff:g> sada može skratiti vijek trajanja baterije i/ili dovesti do prekomjernog korištenja mobilne veze za prenos podataka te se može desiti da vam operater naplati troškove ovisno o pretplati za prenos podataka koju imate.\n\n Dodirnite <xliff:g id="QUEUE_TEXT">%s</xliff:g> kako biste pokrenuli ovo preuzimanje kada se narednog puta povežete na Wi-Fi mrežu."</string>
+    <string name="button_queue_for_wifi" msgid="422576726189179221">"Redoslijed"</string>
+    <string name="button_cancel_download" msgid="2430166148737975604">"Otkaži"</string>
+    <string name="button_start_now" msgid="792123674007840864">"Pokreni sada"</string>
+    <plurals name="notif_summary_active" formatted="false" msgid="7290448463204837173">
+      <item quantity="one">Preuzima se <xliff:g id="NUMBER">%d</xliff:g> datoteka</item>
+      <item quantity="few">Preuzimaju se <xliff:g id="NUMBER">%d</xliff:g> datoteke</item>
+      <item quantity="other">Preuzima se <xliff:g id="NUMBER">%d</xliff:g> datoteka</item>
+    </plurals>
+    <plurals name="notif_summary_waiting" formatted="false" msgid="2814217662029273005">
+      <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> datoteka na čekanju</item>
+      <item quantity="few"><xliff:g id="NUMBER">%d</xliff:g> datoteke na čekanju</item>
+      <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> datoteka na čekanju</item>
+    </plurals>
+    <string name="download_remaining" msgid="3139295890887972718">"<xliff:g id="DURATION">%s</xliff:g> lijevo"</string>
+    <string name="download_no_application_title" msgid="7935659741162801699">"Nije moguće otvoriti datoteku"</string>
+    <string name="root_downloads" msgid="4098414876292351487">"Preuzimanja"</string>
+    <string name="download_queued" msgid="3302638231377947451">"U redoslijedu"</string>
+    <string name="download_running" msgid="3925050393361158266">"U toku"</string>
+    <string name="download_error" msgid="5144180777324573236">"Neuspješno"</string>
+    <string name="download_running_percent" msgid="4305080769167320204">"U toku, <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+</resources>
index 77e5a35..aadf3ce 100644 (file)
     <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Vedeți desc. în stoc. USB"</string>
     <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Vizualizați toate descărcările pe cardul SD"</string>
     <string name="permdesc_seeAllExternal" msgid="1672759909065511233">"Permite aplicației să vizualizeze toate descărcările efectuate pe cardul SD, indiferent de aplicația care le-a descărcat."</string>
-    <string name="permlab_downloadCacheNonPurgeable" msgid="3069534308882047412">"Rezervați spaţiu în memoria cache de descărcare"</string>
-    <string name="permdesc_downloadCacheNonPurgeable" msgid="2408760720334570420">"Permite aplic. să descarce fişiere în memoria cache de desc., care nu poate fi ştearsă în mod automat când managerul de desc. are nevoie de mai mult spaţiu."</string>
+    <string name="permlab_downloadCacheNonPurgeable" msgid="3069534308882047412">"Rezervați spațiu în memoria cache de descărcare"</string>
+    <string name="permdesc_downloadCacheNonPurgeable" msgid="2408760720334570420">"Permite aplic. să descarce fişiere în memoria cache de desc., care nu poate fi ştearsă în mod automat când managerul de desc. are nevoie de mai mult spațiu."</string>
     <string name="permlab_downloadWithoutNotification" msgid="8837971946078327262">"descărcarea fişierelor fără notificare"</string>
-    <string name="permdesc_downloadWithoutNotification" msgid="8483135034298639727">"Permite aplicației să descarce fişiere prin intermediul managerului de descărcări fără a afişa notificări utilizatorului."</string>
+    <string name="permdesc_downloadWithoutNotification" msgid="8483135034298639727">"Permite aplicației să descarce fişiere prin intermediul managerului de descărcări fără a afișa notificări utilizatorului."</string>
     <string name="permlab_accessAllDownloads" msgid="2436240495424393717">"Accesați toate descărcările din sistem"</string>
     <string name="permdesc_accessAllDownloads" msgid="1871832254578267128">"Permite aplicației să vizualizeze și să modifice toate descărcările inițiate de orice aplicație din sistem."</string>
     <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Fără titlu&gt;"</string>
     <string name="notification_need_wifi_for_size" msgid="2556172885154833575">"Dimen. desc. nec. Wi-Fi"</string>
     <string name="notification_paused_in_background" msgid="4328508073283591772">"Întreruptă în fundal."</string>
     <string name="wifi_required_title" msgid="1995971416871498179">"Descărcare prea mare pentru reţeaua operatorului"</string>
-    <string name="wifi_required_body" msgid="3067694630143784449">"Trebuie să utilizaţi Wi-Fi pentru a finaliza această descărcare de <xliff:g id="SIZE">%s </xliff:g>. \n\nAtingeţi <xliff:g id="QUEUE_TEXT">%s </xliff:g> pentru a începe această descărcare data viitoare când vă conectaţi la o rețea Wi-Fi."</string>
+    <string name="wifi_required_body" msgid="3067694630143784449">"Trebuie să utilizaţi Wi-Fi pentru a finaliza această descărcare de <xliff:g id="SIZE">%s </xliff:g>. \n\nAtingeți <xliff:g id="QUEUE_TEXT">%s </xliff:g> pentru a începe această descărcare data viitoare când vă conectaţi la o rețea Wi-Fi."</string>
     <string name="wifi_recommended_title" msgid="7441589306734687400">"Puneți în așteptare pentru descărcare ulterioară?"</string>
     <string name="wifi_recommended_body" msgid="1314735166699936073">"Pornirea ac.desc.de <xliff:g id="SIZE">%s </xliff:g> acum impl.scurt.dur.de viaţă a bater.și/sau utiliz.exces.a conex.de date mob.și tax.suplim.din partea oper.de telef.mob.,cf.plan.de date.\n\n Ating. <xliff:g id="QUEUE_TEXT">%s</xliff:g> pt.a înc.desc.la conect.la Wi-Fi."</string>
     <string name="button_queue_for_wifi" msgid="422576726189179221">"Listă de așteptare"</string>
     <string name="button_cancel_download" msgid="2430166148737975604">"Anulați"</string>
-    <string name="button_start_now" msgid="792123674007840864">"Începeţi acum"</string>
+    <string name="button_start_now" msgid="792123674007840864">"Începeți acum"</string>
     <plurals name="notif_summary_active" formatted="false" msgid="7290448463204837173">
       <item quantity="few">Se descarcă <xliff:g id="NUMBER">%d</xliff:g> fișiere</item>
       <item quantity="other">Se descarcă <xliff:g id="NUMBER">%d</xliff:g> de fișiere</item>
index 6c0150c..c2ecd07 100644 (file)
@@ -52,7 +52,7 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> ta fayl navbatda</item>
       <item quantity="one">1 ta fayl navbatda</item>
     </plurals>
-    <string name="download_remaining" msgid="3139295890887972718">"<xliff:g id="DURATION">%s</xliff:g> o‘tib ketdi"</string>
+    <string name="download_remaining" msgid="3139295890887972718">"<xliff:g id="DURATION">%s</xliff:g> qoldi"</string>
     <string name="download_no_application_title" msgid="7935659741162801699">"Fayl ochilmadi"</string>
     <string name="root_downloads" msgid="4098414876292351487">"Yuklanishlar"</string>
     <string name="download_queued" msgid="3302638231377947451">"Navbatga qo‘shildi"</string>
index 7b8fcd2..6cea808 100644 (file)
@@ -54,6 +54,9 @@ public class Constants {
     /** the intent that gets sent when clicking an incomplete/failed download  */
     public static final String ACTION_LIST = "android.intent.action.DOWNLOAD_LIST";
 
+    /** the intent that gets sent when canceling a download  */
+    public static final String ACTION_CANCEL = "android.intent.action.DOWNLOAD_CANCEL";
+
     /** the intent that gets sent when deleting the notification of a completed download */
     public static final String ACTION_HIDE = "android.intent.action.DOWNLOAD_HIDE";
 
index 60c249f..2ff8b63 100644 (file)
@@ -122,6 +122,15 @@ public class DownloadNotifier {
         }
     }
 
+    private static boolean isClusterDeleted(Collection<DownloadInfo> cluster) {
+        boolean wasDeleted = true;
+        for (DownloadInfo info : cluster) {
+            wasDeleted = wasDeleted && info.mDeleted;
+        }
+
+        return wasDeleted;
+    }
+
     private void updateWithLocked(Collection<DownloadInfo> downloads) {
         final Resources res = mContext.getResources();
 
@@ -139,6 +148,11 @@ public class DownloadNotifier {
             final int type = getNotificationTagType(tag);
             final Collection<DownloadInfo> cluster = clustered.get(tag);
 
+            // If each of the downloads was canceled, don't show notification for the cluster
+            if (isClusterDeleted(cluster)) {
+                continue;
+            }
+
             final Notification.Builder builder = new Notification.Builder(mContext);
             builder.setColor(res.getColor(
                     com.android.internal.R.color.system_notification_accent_color));
@@ -164,16 +178,31 @@ public class DownloadNotifier {
 
             // Build action intents
             if (type == TYPE_ACTIVE || type == TYPE_WAITING) {
+                long[] downloadIds = getDownloadIds(cluster);
+
                 // build a synthetic uri for intent identification purposes
                 final Uri uri = new Uri.Builder().scheme("active-dl").appendPath(tag).build();
                 final Intent intent = new Intent(Constants.ACTION_LIST,
                         uri, mContext, DownloadReceiver.class);
                 intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
-                        getDownloadIds(cluster));
+                        downloadIds);
                 builder.setContentIntent(PendingIntent.getBroadcast(mContext,
                         0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
                 builder.setOngoing(true);
 
+                // Add a Cancel action
+                final Uri cancelUri = new Uri.Builder().scheme("cancel-dl").appendPath(tag).build();
+                final Intent cancelIntent = new Intent(Constants.ACTION_CANCEL,
+                        cancelUri, mContext, DownloadReceiver.class);
+                cancelIntent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS, downloadIds);
+                cancelIntent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG, tag);
+
+                builder.addAction(
+                    android.R.drawable.ic_menu_close_clear_cancel,
+                    res.getString(R.string.button_cancel_download),
+                    PendingIntent.getBroadcast(mContext,
+                            0, cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+
             } else if (type == TYPE_COMPLETE) {
                 final DownloadInfo info = cluster.iterator().next();
                 final Uri uri = ContentUris.withAppendedId(
index e79aff5..78b4294 100644 (file)
@@ -1270,7 +1270,13 @@ public final class DownloadProvider extends ContentProvider {
             throw new FileNotFoundException("No filename found.");
         }
 
-        final File file = new File(path);
+        final File file;
+        try {
+            file = new File(path).getCanonicalFile();
+        } catch (IOException e) {
+            throw new FileNotFoundException(e.getMessage());
+        }
+
         if (!Helpers.isFilenameValid(getContext(), file)) {
             throw new FileNotFoundException("Invalid file: " + file);
         }
index 28e2a67..2f50dcf 100644 (file)
@@ -21,6 +21,7 @@ import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY
 import static com.android.providers.downloads.Constants.TAG;
 
 import android.app.DownloadManager;
+import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -45,6 +46,21 @@ import com.google.common.annotations.VisibleForTesting;
  * Receives system broadcasts (boot, network connectivity)
  */
 public class DownloadReceiver extends BroadcastReceiver {
+    /**
+     * Intent extra included with {@link #ACTION_CANCEL} intents, indicating the IDs (as array of
+     * long) of the downloads that were canceled.
+     */
+    public static final String EXTRA_CANCELED_DOWNLOAD_IDS =
+            "com.android.providers.downloads.extra.CANCELED_DOWNLOAD_IDS";
+
+    /**
+     * Intent extra included with {@link #ACTION_CANCEL} intents, indicating the tag of the
+     * notification corresponding to the download(s) that were canceled; this notification must be
+     * canceled.
+     */
+    public static final String EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG =
+            "com.android.providers.downloads.extra.CANCELED_DOWNLOAD_NOTIFICATION_TAG";
+
     private static Handler sAsyncHandler;
 
     static {
@@ -107,6 +123,18 @@ public class DownloadReceiver extends BroadcastReceiver {
                     }
                 });
             }
+        } else if (Constants.ACTION_CANCEL.equals(action)) {
+            long[] downloadIds = intent.getLongArrayExtra(
+                    DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS);
+            DownloadManager manager = (DownloadManager) context.getSystemService(
+                    Context.DOWNLOAD_SERVICE);
+            manager.remove(downloadIds);
+
+            String notifTag = intent.getStringExtra(
+                    DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG);
+            NotificationManager notifManager = (NotificationManager) context.getSystemService(
+                    Context.NOTIFICATION_SERVICE);
+            notifManager.cancel(notifTag, 0);
         }
     }
 
index b0b7329..7845ce0 100644 (file)
@@ -33,11 +33,15 @@ import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.IDeviceIdleController;
 import android.os.Message;
 import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.provider.Downloads;
 import android.text.TextUtils;
 import android.util.Log;
@@ -84,6 +88,7 @@ public class DownloadService extends Service {
     SystemFacade mSystemFacade;
 
     private AlarmManager mAlarmManager;
+    private IDeviceIdleController mDeviceIdleController;
 
     /** Observer to get notified when the content observer's data changes */
     private DownloadManagerContentObserver mObserver;
@@ -192,6 +197,12 @@ public class DownloadService extends Service {
         }
 
         mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+        mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
+                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+        try {
+            mDeviceIdleController.downloadServiceActive(new Binder());
+        } catch (RemoteException e) {
+        }
 
         mUpdateThread = new HandlerThread(TAG + "-UpdateThread");
         mUpdateThread.start();
@@ -330,6 +341,10 @@ public class DownloadService extends Service {
                     if (DEBUG_LIFECYCLE) Log.v(TAG, "Nothing left; stopped");
                     getContentResolver().unregisterContentObserver(mObserver);
                     mScanner.shutdown();
+                    try {
+                        mDeviceIdleController.downloadServiceInactive();
+                    } catch (RemoteException e) {
+                    }
                     mUpdateThread.quit();
                 }
             }
index 1b5dc84..cc04d4d 100644 (file)
@@ -35,6 +35,7 @@ import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsProvider;
+import android.support.provider.DocumentArchiveHelper;
 import android.text.TextUtils;
 import android.webkit.MimeTypeMap;
 
@@ -65,11 +66,14 @@ public class DownloadStorageProvider extends DocumentsProvider {
     };
 
     private DownloadManager mDm;
+    private DocumentArchiveHelper mArchiveHelper;
 
     @Override
     public boolean onCreate() {
         mDm = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
         mDm.setAccessAllDownloads(true);
+        mDm.setAccessFilename(true);
+        mArchiveHelper = new DocumentArchiveHelper(this, ':');
         return true;
     }
 
@@ -152,6 +156,10 @@ public class DownloadStorageProvider extends DocumentsProvider {
 
     @Override
     public Cursor queryDocument(String docId, String[] projection) throws FileNotFoundException {
+        if (mArchiveHelper.isArchivedDocument(docId)) {
+            return mArchiveHelper.queryDocument(docId, projection);
+        }
+
         final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
 
         if (DOC_ID_ROOT.equals(docId)) {
@@ -164,6 +172,8 @@ public class DownloadStorageProvider extends DocumentsProvider {
                 cursor = mDm.query(new Query().setFilterById(Long.parseLong(docId)));
                 copyNotificationUri(result, cursor);
                 if (cursor.moveToFirst()) {
+                    // We don't know if this queryDocument() call is from Downloads (manage)
+                    // or Files. Safely assume it's Files.
                     includeDownloadFromCursor(result, cursor);
                 }
             } finally {
@@ -177,6 +187,11 @@ public class DownloadStorageProvider extends DocumentsProvider {
     @Override
     public Cursor queryChildDocuments(String docId, String[] projection, String sortOrder)
             throws FileNotFoundException {
+        if (mArchiveHelper.isArchivedDocument(docId) ||
+                mArchiveHelper.isSupportedArchiveType(getDocumentType(docId))) {
+            return mArchiveHelper.queryChildDocuments(docId, projection, sortOrder);
+        }
+
         final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
 
         // Delegate to real provider
@@ -200,6 +215,10 @@ public class DownloadStorageProvider extends DocumentsProvider {
     public Cursor queryChildDocumentsForManage(
             String parentDocumentId, String[] projection, String sortOrder)
             throws FileNotFoundException {
+        if (mArchiveHelper.isArchivedDocument(parentDocumentId)) {
+            return mArchiveHelper.queryDocument(parentDocumentId, projection);
+        }
+
         final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
 
         // Delegate to real provider
@@ -256,6 +275,10 @@ public class DownloadStorageProvider extends DocumentsProvider {
     @Override
     public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
             throws FileNotFoundException {
+        if (mArchiveHelper.isArchivedDocument(docId)) {
+            return mArchiveHelper.openDocument(docId, mode, signal);
+        }
+
         // Delegate to real provider
         final long token = Binder.clearCallingIdentity();
         try {
@@ -332,10 +355,14 @@ public class DownloadStorageProvider extends DocumentsProvider {
         }
 
         int flags = Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_WRITE;
-        if (mimeType != null && mimeType.startsWith("image/")) {
+        if (mimeType.startsWith("image/")) {
             flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
         }
 
+        if (mArchiveHelper.isSupportedArchiveType(mimeType)) {
+            flags |= Document.FLAG_ARCHIVE;
+        }
+
         final long lastModified = cursor.getLong(
                 cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));
 
@@ -345,8 +372,18 @@ public class DownloadStorageProvider extends DocumentsProvider {
         row.add(Document.COLUMN_SUMMARY, summary);
         row.add(Document.COLUMN_SIZE, size);
         row.add(Document.COLUMN_MIME_TYPE, mimeType);
-        row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
         row.add(Document.COLUMN_FLAGS, flags);
+        // Incomplete downloads get a null timestamp.  This prevents thrashy UI when a bunch of
+        // active downloads get sorted by mod time.
+        if (status != DownloadManager.STATUS_RUNNING) {
+            row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
+        }
+
+        final String localFilePath = cursor.getString(
+                cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_FILENAME));
+        if (localFilePath != null) {
+            row.add(DocumentArchiveHelper.COLUMN_LOCAL_FILE_PATH, localFilePath);
+        }
     }
 
     /**
index d1cc545..d01cbff 100644 (file)
@@ -357,8 +357,6 @@ public class Helpers {
     static boolean isFilenameValidInExternalPackage(Context context, File file,
             String packageName) {
         try {
-            file = file.getCanonicalFile();
-
             if (containsCanonical(buildExternalStorageAppFilesDirs(packageName), file) ||
                     containsCanonical(buildExternalStorageAppObbDirs(packageName), file) ||
                     containsCanonical(buildExternalStorageAppCacheDirs(packageName), file) ||
@@ -380,8 +378,6 @@ public class Helpers {
      */
     static boolean isFilenameValid(Context context, File file, boolean allowInternal) {
         try {
-            file = file.getCanonicalFile();
-
             if (allowInternal) {
                 if (containsCanonical(context.getFilesDir(), file)
                         || containsCanonical(context.getCacheDir(), file)
index 4eb319c..7a74c88 100644 (file)
@@ -30,6 +30,8 @@ import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.StrictMode;
+import android.provider.DocumentsContract;
 import android.provider.Downloads.Impl.RequestHeaders;
 import android.util.Log;
 
@@ -49,11 +51,14 @@ public class OpenHelper {
 
         intent.addFlags(intentFlags);
         try {
+            StrictMode.disableDeathOnFileUriExposure();
             context.startActivity(intent);
             return true;
         } catch (ActivityNotFoundException e) {
             Log.w(TAG, "Failed to start " + intent + ": " + e);
             return false;
+        } finally {
+            StrictMode.enableDeathOnFileUriExposure();
         }
     }
 
@@ -65,6 +70,7 @@ public class OpenHelper {
         final DownloadManager downManager = (DownloadManager) context.getSystemService(
                 Context.DOWNLOAD_SERVICE);
         downManager.setAccessAllDownloads(true);
+        downManager.setAccessFilename(true);
 
         final Cursor cursor = downManager.query(new DownloadManager.Query().setFilterById(id));
         try {
@@ -77,6 +83,9 @@ public class OpenHelper {
             String mimeType = getCursorString(cursor, COLUMN_MEDIA_TYPE);
             mimeType = DownloadDrmHelper.getOriginalMimeType(context, file, mimeType);
 
+            final Uri documentUri = DocumentsContract.buildDocumentUri(
+                    Constants.STORAGE_AUTHORITY, String.valueOf(id));
+
             final Intent intent = new Intent(Intent.ACTION_VIEW);
 
             if ("application/vnd.android.package-archive".equals(mimeType)) {
@@ -89,13 +98,12 @@ public class OpenHelper {
                 intent.putExtra(Intent.EXTRA_REFERRER, getRefererUri(context, id));
                 intent.putExtra(Intent.EXTRA_ORIGINATING_UID, getOriginatingUid(context, id));
             } else if ("file".equals(localUri.getScheme())) {
+                intent.setDataAndType(documentUri, mimeType);
                 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                         | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-                intent.setDataAndType(
-                        ContentUris.withAppendedId(ALL_DOWNLOADS_CONTENT_URI, id), mimeType);
             } else {
-                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                intent.setDataAndType(localUri, mimeType);
+                throw new UnsupportedOperationException(
+                        "Unsupported scheme: " + localUri.getScheme());
             }
 
             return intent;
index 7633941..82fa934 100644 (file)
@@ -51,7 +51,7 @@ public class PublicApiAccessTest extends AndroidTestCase {
     protected void setUp() throws Exception {
         super.setUp();
         mContentResolver = getContext().getContentResolver();
-        mManager = new DownloadManager(mContentResolver, getContext().getPackageName());
+        mManager = new DownloadManager(getContext());
     }
 
     @Override
index 28c5dc7..6934b86 100644 (file)
@@ -18,11 +18,13 @@ package com.android.providers.downloads;
 
 import static org.mockito.Mockito.mock;
 
+import android.app.DownloadManager;
 import android.app.NotificationManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ProviderInfo;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
@@ -99,6 +101,7 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
 
         private final ContentResolver mResolver;
         private final NotificationManager mNotifManager;
+        private final DownloadManager mDownloadManager;
 
         boolean mHasServiceBeenStarted = false;
 
@@ -106,6 +109,7 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
             super(realContext, FILENAME_PREFIX);
             mResolver = new MockContentResolverWithNotify(this);
             mNotifManager = mock(NotificationManager.class);
+            mDownloadManager = mock(DownloadManager.class);
         }
 
         /**
@@ -123,6 +127,8 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
         public Object getSystemService(String name) {
             if (Context.NOTIFICATION_SERVICE.equals(name)) {
                 return mNotifManager;
+            } else if (Context.DOWNLOAD_SERVICE.equals(name)) {
+                return mDownloadManager;
             }
 
             return super.getSystemService(name);
@@ -162,7 +168,10 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
 
         final DownloadProvider provider = new DownloadProvider();
         provider.mSystemFacade = mSystemFacade;
-        provider.attachInfo(mTestContext, null);
+
+        ProviderInfo info = new ProviderInfo();
+        info.authority = "downloads";
+        provider.attachInfo(mTestContext, info);
 
         mResolver.addProvider(PROVIDER_AUTHORITY, provider);
 
index 2846c7a..c0a1108 100644 (file)
@@ -22,6 +22,8 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 
 import android.app.DownloadManager;
+import android.content.ContentResolver;
+import android.content.ContextWrapper;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
@@ -217,7 +219,17 @@ public abstract class AbstractPublicApiTest extends AbstractDownloadProviderFunc
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mManager = new DownloadManager(mResolver, PACKAGE_NAME);
+        mManager = new DownloadManager(new ContextWrapper(mContext) {
+            @Override
+            public ContentResolver getContentResolver() {
+                return mResolver;
+            }
+
+            @Override
+            public String getPackageName() {
+                return PACKAGE_NAME;
+            }
+        });
     }
 
     protected DownloadManager.Request getRequest()
index d1048b0..17fed6d 100644 (file)
@@ -49,6 +49,8 @@ import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.Suppress;
 import android.text.format.DateUtils;
 
+import com.android.providers.downloads.Constants;
+import com.android.providers.downloads.DownloadReceiver;
 import com.google.mockwebserver.MockResponse;
 import com.google.mockwebserver.RecordedRequest;
 import com.google.mockwebserver.SocketPolicy;
@@ -71,6 +73,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
 
     protected File mTestDirectory;
     private NotificationManager mNotifManager;
+    private DownloadManager mDownloadManager;
 
     public PublicApiFunctionalTest() {
         super(new FakeSystemFacade());
@@ -82,6 +85,8 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
 
         mNotifManager = (NotificationManager) getContext()
                 .getSystemService(Context.NOTIFICATION_SERVICE);
+        mDownloadManager = (DownloadManager) getContext()
+                .getSystemService(Context.DOWNLOAD_SERVICE);
 
         mTestDirectory = new File(Environment.getExternalStorageDirectory() + File.separator
                                   + "download_manager_functional_test");
@@ -552,6 +557,23 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
         assertEquals(PACKAGE_NAME, broadcast.getPackage());
     }
 
+    public void testNotificationCancelDownloadClicked() throws Exception {
+        Download download = enqueueRequest(getRequest());
+
+        DownloadReceiver receiver = new DownloadReceiver();
+        receiver.mSystemFacade = mSystemFacade;
+        Intent intent = new Intent(Constants.ACTION_CANCEL);
+        intent.setData(Uri.parse(Downloads.Impl.CONTENT_URI + "/" + download.mId));
+
+        long[] downloadIds = {download.mId};
+        intent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS, downloadIds);
+        intent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG, "tag");
+        receiver.onReceive(mContext, intent);
+
+        verify(mNotifManager, times(1)).cancel("tag", 0);
+        verify(mDownloadManager, times(1)).remove(downloadIds);
+    }
+
     public void testBasicConnectivityChanges() throws Exception {
         enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
 
diff --git a/ui/res/values-b+sr+Latn/strings.xml b/ui/res/values-b+sr+Latn/strings.xml
new file mode 100644 (file)
index 0000000..8545790
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2010 The Android Open Source 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" msgid="3070921713463294774">"Preuzimanja"</string>
+    <string name="download_title_sorted_by_date" msgid="5898014492155434221">"Preuzimanja – Sortirano prema datumu"</string>
+    <string name="download_title_sorted_by_size" msgid="1417193166677094813">"Preuzimanja – Sortirano prema veličini"</string>
+    <string name="no_downloads" msgid="1029667411186146836">"Nema preuzimanja."</string>
+    <string name="missing_title" msgid="830115697868833773">"&lt;Nepoznato&gt;"</string>
+    <string name="button_sort_by_size" msgid="7331549713691146251">"Sortiraj prema veličini"</string>
+    <string name="button_sort_by_date" msgid="8800842892684101528">"Sortiraj prema datumu"</string>
+    <string name="download_queued" msgid="104973307780629904">"Stavljeno na čekanje"</string>
+    <string name="download_running" msgid="4656462962155580641">"U toku"</string>
+    <string name="download_success" msgid="7006048006543495236">"Dovršeno"</string>
+    <string name="download_error" msgid="8081329546008568251">"Neuspešno"</string>
+    <string name="dialog_title_not_available" msgid="5746317632356158515">"Preuzimanje nije moguće"</string>
+    <string name="dialog_failed_body" msgid="587545111677064427">"Želite li da kasnije probate da preuzmete datoteku ili želite da je izbrišete iz reda?"</string>
+    <string name="dialog_title_queued_body" msgid="6760681913815015219">"Stavljena je u red"</string>
+    <string name="dialog_queued_body" msgid="708552801635572720">"Ova datoteka je stavljena u red za preuzimanje, pa još uvek nije dostupna."</string>
+    <string name="dialog_file_missing_body" msgid="3223012612774276284">"Nije moguće pronaći preuzetu datoteku."</string>
+    <string name="dialog_insufficient_space_on_external" msgid="8692452156251449195">"Nije moguće završiti preuzimanje. Nema dovoljno prostora u eksternoj memoriji."</string>
+    <string name="dialog_insufficient_space_on_cache" msgid="6313630206163908994">"Nije moguće završiti preuzimanje. Nema dovoljno prostora u internoj memoriji za preuzimanje."</string>
+    <string name="dialog_cannot_resume" msgid="8664509751358983543">"Preuzimanje je prekinuto i nije ga moguće nastaviti."</string>
+    <string name="dialog_file_already_exists" msgid="8308563940663449590">"Preuzimanje nije moguće. Odredišna datoteka već postoji."</string>
+    <string name="dialog_media_not_found" msgid="4468088418758018765">"Preuzimanje nije moguće. Eksterni medijum nije dostupan."</string>
+    <string name="download_no_application_title" msgid="7024782176657362251">"Nije moguće otvoriti datoteku"</string>
+    <string name="remove_download" msgid="6372920256257247857">"Ukloni"</string>
+    <string name="delete_download" msgid="76629022653866471">"Izbriši"</string>
+    <string name="keep_queued_download" msgid="5144882786014818569">"Zadrži"</string>
+    <string name="cancel_running_download" msgid="5232704030969221112">"Otkaži"</string>
+    <string name="retry_download" msgid="7617100787922717912">"Pokušaj ponovo"</string>
+    <string name="deselect_all" msgid="6348198946254776764">"Opozovi sve izbore"</string>
+    <string name="select_all" msgid="634074918366265804">"Izaberi sve"</string>
+    <string name="selected_count" msgid="2101564570019753277">"Izabrano je <xliff:g id="NUMBER">%1$d</xliff:g> od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="download_share_dialog" msgid="3355867339806448955">"Deljenje preko"</string>
+</resources>
index 5aca371..a65a994 100644 (file)
@@ -46,5 +46,5 @@
     <string name="deselect_all" msgid="6348198946254776764">"সবগুলিকে নির্বাচনমুক্ত করুন"</string>
     <string name="select_all" msgid="634074918366265804">"সবগুলি নির্বাচন করুন"</string>
     <string name="selected_count" msgid="2101564570019753277">"<xliff:g id="TOTAL">%2$d</xliff:g>টির মধ্যে <xliff:g id="NUMBER">%1$d</xliff:g>টি নির্বাচিত"</string>
-    <string name="download_share_dialog" msgid="3355867339806448955">"এর মাধ্যমে ভাগ করুন"</string>
+    <string name="download_share_dialog" msgid="3355867339806448955">"এর মাধ্যমে শেয়ার করুন"</string>
 </resources>
diff --git a/ui/res/values-bs-rBA/strings.xml b/ui/res/values-bs-rBA/strings.xml
new file mode 100644 (file)
index 0000000..d2d1197
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2010 The Android Open Source 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" msgid="3070921713463294774">"Preuzimanja"</string>
+    <string name="download_title_sorted_by_date" msgid="5898014492155434221">"Preuzimanja - sortirana po datumu"</string>
+    <string name="download_title_sorted_by_size" msgid="1417193166677094813">"Preuzimanja - sortirana po veličini"</string>
+    <string name="no_downloads" msgid="1029667411186146836">"Nema preuzimanja."</string>
+    <string name="missing_title" msgid="830115697868833773">"&lt;Nepoznato&gt;"</string>
+    <string name="button_sort_by_size" msgid="7331549713691146251">"Sortiraj po veličini"</string>
+    <string name="button_sort_by_date" msgid="8800842892684101528">"Sortiraj po datumu"</string>
+    <string name="download_queued" msgid="104973307780629904">"U redoslijedu"</string>
+    <string name="download_running" msgid="4656462962155580641">"U toku"</string>
+    <string name="download_success" msgid="7006048006543495236">"Završeno"</string>
+    <string name="download_error" msgid="8081329546008568251">"Neuspješno"</string>
+    <string name="dialog_title_not_available" msgid="5746317632356158515">"Nije bilo moguće preuzeti"</string>
+    <string name="dialog_failed_body" msgid="587545111677064427">"Da li želite ponovo pokušati s preuzimanjem datoteke kasnije ili je želite izbrisati s redoslijeda?"</string>
+    <string name="dialog_title_queued_body" msgid="6760681913815015219">"Datoteka je u redoslijedu"</string>
+    <string name="dialog_queued_body" msgid="708552801635572720">"Datoteka je na redoslijedu za kasnije preuzimanje tako da još nije dostupna."</string>
+    <string name="dialog_file_missing_body" msgid="3223012612774276284">"Nije moguće pronaći preuzetu datoteku."</string>
+    <string name="dialog_insufficient_space_on_external" msgid="8692452156251449195">"Nije moguće dovršiti preuzimanje. Nema dovoljno prostora na eksternoj pohrani."</string>
+    <string name="dialog_insufficient_space_on_cache" msgid="6313630206163908994">"Nije moguće dovršiti preuzimanje. Nema dovoljno prostora na internoj pohrani za preuzimanja."</string>
+    <string name="dialog_cannot_resume" msgid="8664509751358983543">"Preuzimanje je prekinuto i ne može se nastaviti."</string>
+    <string name="dialog_file_already_exists" msgid="8308563940663449590">"Nije moguće preuzeti. Odredišna datoteka već postoji."</string>
+    <string name="dialog_media_not_found" msgid="4468088418758018765">"Nije moguće preuzeti. Eksterni medij nije dostupan."</string>
+    <string name="download_no_application_title" msgid="7024782176657362251">"Nije moguće otvoriti datoteku"</string>
+    <string name="remove_download" msgid="6372920256257247857">"Ukloni"</string>
+    <string name="delete_download" msgid="76629022653866471">"Izbriši"</string>
+    <string name="keep_queued_download" msgid="5144882786014818569">"Zadrži"</string>
+    <string name="cancel_running_download" msgid="5232704030969221112">"Otkaži"</string>
+    <string name="retry_download" msgid="7617100787922717912">"Pokušaj ponovo"</string>
+    <string name="deselect_all" msgid="6348198946254776764">"Poništi odabir svih"</string>
+    <string name="select_all" msgid="634074918366265804">"Odaberi sve"</string>
+    <string name="selected_count" msgid="2101564570019753277">"Odabrano <xliff:g id="NUMBER">%1$d</xliff:g> od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
+    <string name="download_share_dialog" msgid="3355867339806448955">"Podijeli preko"</string>
+</resources>
index b387e44..f250f51 100644 (file)
@@ -32,8 +32,8 @@
     <string name="dialog_title_queued_body" msgid="6760681913815015219">"Fișier în coadă"</string>
     <string name="dialog_queued_body" msgid="708552801635572720">"Fişierul este adăugat în coadă pentru descărcare ulterioară, prin urmare nu este disponibil încă."</string>
     <string name="dialog_file_missing_body" msgid="3223012612774276284">"Nu se poate găsi fişierul descărcat."</string>
-    <string name="dialog_insufficient_space_on_external" msgid="8692452156251449195">"Nu se poate finaliza descărcarea. Nu există suficient spaţiu de stocare extern."</string>
-    <string name="dialog_insufficient_space_on_cache" msgid="6313630206163908994">"Nu se poate finaliza descărcarea. Nu există suficient spaţiu de stocare intern."</string>
+    <string name="dialog_insufficient_space_on_external" msgid="8692452156251449195">"Nu se poate finaliza descărcarea. Nu există suficient spațiu de stocare extern."</string>
+    <string name="dialog_insufficient_space_on_cache" msgid="6313630206163908994">"Nu se poate finaliza descărcarea. Nu există suficient spațiu de stocare intern."</string>
     <string name="dialog_cannot_resume" msgid="8664509751358983543">"Descărcarea a fost întreruptă și nu poate fi reluată."</string>
     <string name="dialog_file_already_exists" msgid="8308563940663449590">"Nu se poate descărca. Fişierul de destinaţie există deja."</string>
     <string name="dialog_media_not_found" msgid="4468088418758018765">"Nu se poate descărca. Nu este disponibil un mediu de stocare extern."</string>
@@ -46,5 +46,5 @@
     <string name="deselect_all" msgid="6348198946254776764">"Deselectați-le pe toate"</string>
     <string name="select_all" msgid="634074918366265804">"Selectaţi-le pe toate"</string>
     <string name="selected_count" msgid="2101564570019753277">"Au fost selectate <xliff:g id="NUMBER">%1$d</xliff:g> din <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
-    <string name="download_share_dialog" msgid="3355867339806448955">"Distribuiţi prin"</string>
+    <string name="download_share_dialog" msgid="3355867339806448955">"Distribuiți prin"</string>
 </resources>
index f96c04e..104f144 100644 (file)
@@ -152,7 +152,10 @@ public class TrampolineActivity extends Activity {
         @Override
         public void onDismiss(DialogInterface dialog) {
             super.onDismiss(dialog);
-            getActivity().finish();
+            final Activity activity = getActivity();
+            if (activity != null) {
+                activity.finish();
+            }
         }
     }
 
@@ -221,7 +224,10 @@ public class TrampolineActivity extends Activity {
         @Override
         public void onDismiss(DialogInterface dialog) {
             super.onDismiss(dialog);
-            getActivity().finish();
+            final Activity activity = getActivity();
+            if (activity != null) {
+                activity.finish();
+            }
         }
     }
 }