Use strings, async image loading, "unknown" status added.

This commit is contained in:
mvp76 2017-02-15 15:51:08 +01:00
parent 55c7a21c90
commit 7efa62891d
50 changed files with 335 additions and 218 deletions

View File

@ -13,6 +13,7 @@ import org.fdroid.fdroid.data.App;
import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.installer.ErrorDialogActivity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@ -43,14 +44,14 @@ public class AppUpdateStatusManager {
return new AppUpdateStatusManager(context);
}
class AppUpdateStatus {
final App app;
final Apk apk;
Status status;
PendingIntent intent;
int progressCurrent;
int progressMax;
String errorText;
public class AppUpdateStatus {
public final App app;
public final Apk apk;
public Status status;
public PendingIntent intent;
public int progressCurrent;
public int progressMax;
public String errorText;
AppUpdateStatus(App app, Apk apk, Status status, PendingIntent intent) {
this.app = app;
@ -59,7 +60,7 @@ public class AppUpdateStatusManager {
this.intent = intent;
}
String getUniqueKey() {
public String getUniqueKey() {
return apk.getUrl();
}
}
@ -86,6 +87,23 @@ public class AppUpdateStatusManager {
}
}
/**
* Get all entries associated with a package name. There may be several.
* @param packageName Package name of the app
* @return A list of entries, or an empty list
*/
public Collection<AppUpdateStatus> getByPackageName(String packageName) {
ArrayList<AppUpdateStatus> returnValues = new ArrayList<>();
synchronized (appMapping) {
for (AppUpdateStatus entry : appMapping.values()) {
if (entry.apk.packageName.equalsIgnoreCase(packageName)) {
returnValues.add(entry);
}
}
}
return returnValues;
}
private void setApkInternal(Apk apk, Status status, PendingIntent intent) {
if (apk == null) {
return;

View File

@ -97,6 +97,7 @@ public class FDroidApp extends Application {
@SuppressWarnings("unused")
BluetoothAdapter bluetoothAdapter;
NotificationHelper notificationHelper;
static {
SPONGYCASTLE_PROVIDER = new org.spongycastle.jce.provider.BouncyCastleProvider();
@ -262,7 +263,7 @@ public class FDroidApp extends Application {
CleanCacheService.schedule(this);
NotificationHelper.create(getApplicationContext());
notificationHelper = new NotificationHelper(getApplicationContext());
UpdateService.schedule(getApplicationContext());
bluetoothAdapter = getBluetoothAdapter();

View File

@ -7,6 +7,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Typeface;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
@ -15,9 +16,16 @@ import android.support.v4.content.LocalBroadcastManager;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.StyleSpan;
import android.view.View;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.utils.DiskCacheUtils;
import com.nostra13.universalimageloader.utils.MemoryCacheUtils;
import org.fdroid.fdroid.data.App;
@ -40,25 +48,23 @@ class NotificationHelper {
private static final String GROUP_UPDATES = "updates";
private static final String GROUP_INSTALLED = "installed";
private static final String LOGTAG = "NotificationHelper";
private static NotificationHelper instance;
public static NotificationHelper create(Context context) {
if (instance == null) {
instance = new NotificationHelper(context.getApplicationContext());
}
return instance;
}
private final Context context;
private final NotificationManagerCompat notificationManager;
private final AppUpdateStatusManager appUpdateStatusMananger;
private final AppUpdateStatusManager appUpdateStatusManager;
private final DisplayImageOptions displayImageOptions;
private ArrayList<AppUpdateStatusManager.AppUpdateStatus> updates;
private ArrayList<AppUpdateStatusManager.AppUpdateStatus> installed;
private NotificationHelper(Context context) {
NotificationHelper(Context context) {
this.context = context;
appUpdateStatusMananger = AppUpdateStatusManager.getInstance(context);
appUpdateStatusManager = AppUpdateStatusManager.getInstance(context);
notificationManager = NotificationManagerCompat.from(context);
displayImageOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.imageScaleType(ImageScaleType.NONE)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
// We need to listen to when notifications are cleared, so that we "forget" all that we currently know about updates
// and installs.
@ -67,12 +73,76 @@ class NotificationHelper {
filter.addAction(BROADCAST_NOTIFICATIONS_ALL_INSTALLED_CLEARED);
filter.addAction(BROADCAST_NOTIFICATIONS_UPDATE_CLEARED);
filter.addAction(BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED);
BroadcastReceiver receiverNotificationsCleared = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED:
appUpdateStatusManager.clearAllUpdates();
break;
case BROADCAST_NOTIFICATIONS_ALL_INSTALLED_CLEARED:
appUpdateStatusManager.clearAllInstalled();
break;
case BROADCAST_NOTIFICATIONS_UPDATE_CLEARED:
break;
case BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED:
String key = intent.getStringExtra(EXTRA_NOTIFICATION_KEY);
appUpdateStatusManager.removeApk(key);
break;
}
}
};
context.registerReceiver(receiverNotificationsCleared, filter);
filter = new IntentFilter();
filter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED);
filter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_ADDED);
filter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED);
filter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED);
BroadcastReceiver receiverAppStatusChanges = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED:
notificationManager.cancelAll();
updateStatusLists();
createSummaryNotifications();
for (AppUpdateStatusManager.AppUpdateStatus entry : appUpdateStatusManager.getAll()) {
createNotification(entry);
}
break;
case AppUpdateStatusManager.BROADCAST_APPSTATUS_ADDED: {
updateStatusLists();
createSummaryNotifications();
String url = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL);
AppUpdateStatusManager.AppUpdateStatus entry = appUpdateStatusManager.get(url);
if (entry != null) {
createNotification(entry);
}
break;
}
case AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED: {
String url = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL);
AppUpdateStatusManager.AppUpdateStatus entry = appUpdateStatusManager.get(url);
updateStatusLists();
if (entry != null) {
createNotification(entry);
}
if (intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false)) {
createSummaryNotifications();
}
break;
}
case AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED: {
String url = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL);
notificationManager.cancel(url, NOTIFY_ID_INSTALLED);
notificationManager.cancel(url, NOTIFY_ID_UPDATES);
updateStatusLists();
createSummaryNotifications();
break;
}
}
}
};
LocalBroadcastManager.getInstance(context).registerReceiver(receiverAppStatusChanges, filter);
}
@ -80,76 +150,100 @@ class NotificationHelper {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
}
private void updateSummaryNotifications() {
private void updateStatusLists() {
if (!notificationManager.areNotificationsEnabled()) {
return;
}
// Get the list of updates and installed available
ArrayList<AppUpdateStatusManager.AppUpdateStatus> updates = new ArrayList<>();
ArrayList<AppUpdateStatusManager.AppUpdateStatus> installed = new ArrayList<>();
for (AppUpdateStatusManager.AppUpdateStatus entry : appUpdateStatusMananger.getAll()) {
if (entry.status == AppUpdateStatusManager.Status.Unknown) {
continue;
} else if (entry.status != AppUpdateStatusManager.Status.Installed) {
updates.add(entry);
if (updates == null) {
updates = new ArrayList<>();
} else {
updates.clear();
}
if (installed == null) {
installed = new ArrayList<>();
} else {
installed.clear();
}
for (AppUpdateStatusManager.AppUpdateStatus entry : appUpdateStatusManager.getAll()) {
if (entry.status == AppUpdateStatusManager.Status.Installed) {
installed.add(entry);
} else if (entry.status != AppUpdateStatusManager.Status.Unknown) {
updates.add(entry);
}
}
}
private void createNotification(AppUpdateStatusManager.AppUpdateStatus entry) {
if (entry.status == AppUpdateStatusManager.Status.Unknown) {
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_UPDATES);
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_INSTALLED);
return;
}
if (notificationManager.areNotificationsEnabled()) {
NotificationCompat.Builder builder;
if (entry.status == AppUpdateStatusManager.Status.Installed) {
if (useStackedNotifications()) {
builder = createInstalledNotification(entry);
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_UPDATES);
notificationManager.notify(entry.getUniqueKey(), NOTIFY_ID_INSTALLED, builder.build());
} else if (installed.size() == 1) {
builder = createInstalledNotification(entry);
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_UPDATES);
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_INSTALLED);
notificationManager.notify(GROUP_INSTALLED, NOTIFY_ID_INSTALLED, builder.build());
}
} else {
if (useStackedNotifications()) {
builder = createUpdateNotification(entry);
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_INSTALLED);
notificationManager.notify(entry.getUniqueKey(), NOTIFY_ID_UPDATES, builder.build());
} else if (updates.size() == 1) {
builder = createUpdateNotification(entry);
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_UPDATES);
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_INSTALLED);
notificationManager.notify(GROUP_UPDATES, NOTIFY_ID_UPDATES, builder.build());
}
}
}
}
private void createSummaryNotifications() {
if (!notificationManager.areNotificationsEnabled()) {
return;
}
NotificationCompat.Builder builder;
if (updates.size() != 1 || useStackedNotifications()) {
if (updates.size() == 0) {
// No updates, remove summary
notificationManager.cancel(GROUP_UPDATES, NOTIFY_ID_UPDATES);
} else if (updates.size() == 1 && !useStackedNotifications()) {
// If we use stacked notifications we have already created one.
doCreateNotification(updates.get(0));
} else {
builder = createUpdateSummaryNotification(updates);
notificationManager.notify(GROUP_UPDATES, NOTIFY_ID_UPDATES, builder.build());
}
}
if (installed.size() != 1 || useStackedNotifications()) {
if (installed.size() == 0) {
// No installed, remove summary
notificationManager.cancel(GROUP_INSTALLED, NOTIFY_ID_INSTALLED);
} else if (installed.size() == 1 && !useStackedNotifications()) {
// If we use stacked notifications we have already created one.
doCreateNotification(installed.get(0));
} else {
builder = createInstalledSummaryNotification(installed);
notificationManager.notify(GROUP_INSTALLED, NOTIFY_ID_INSTALLED, builder.build());
}
}
private void createNotification(AppUpdateStatusManager.AppUpdateStatus entry) {
if (useStackedNotifications() && notificationManager.areNotificationsEnabled() && entry.status != AppUpdateStatusManager.Status.Unknown) {
doCreateNotification(entry);
}
}
private void doCreateNotification(AppUpdateStatusManager.AppUpdateStatus entry) {
NotificationCompat.Builder builder;
int id;
if (entry.status == AppUpdateStatusManager.Status.Installed) {
builder = createInstalledNotification(entry);
id = NOTIFY_ID_INSTALLED;
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_UPDATES);
} else {
builder = createUpdateNotification(entry);
id = NOTIFY_ID_UPDATES;
notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_INSTALLED);
}
notificationManager.notify(entry.getUniqueKey(), id, builder.build());
}
private NotificationCompat.Action getAction(AppUpdateStatusManager.AppUpdateStatus entry) {
if (entry.intent != null) {
if (entry.status == AppUpdateStatusManager.Status.UpdateAvailable) {
return new NotificationCompat.Action(R.drawable.ic_notify_update_24dp, "Update", entry.intent);
return new NotificationCompat.Action(R.drawable.ic_notify_update_24dp, context.getString(R.string.notification_action_update), entry.intent);
} else if (entry.status == AppUpdateStatusManager.Status.Downloading || entry.status == AppUpdateStatusManager.Status.Installing) {
return new NotificationCompat.Action(R.drawable.ic_notify_cancel_24dp, "Cancel", entry.intent);
return new NotificationCompat.Action(R.drawable.ic_notify_cancel_24dp, context.getString(R.string.notification_action_cancel), entry.intent);
} else if (entry.status == AppUpdateStatusManager.Status.ReadyToInstall) {
return new NotificationCompat.Action(R.drawable.ic_notify_install_24dp, "Install", entry.intent);
return new NotificationCompat.Action(R.drawable.ic_notify_install_24dp, context.getString(R.string.notification_action_install), entry.intent);
}
}
return null;
@ -158,17 +252,17 @@ class NotificationHelper {
private String getSingleItemTitleString(App app, AppUpdateStatusManager.Status status) {
switch (status) {
case UpdateAvailable:
return "Update Available";
return context.getString(R.string.notification_title_single_update_available);
case Downloading:
return app.name;
case ReadyToInstall:
return "Update ready to install"; // TODO - "Update"? Should just be "ready to install"?
return context.getString(app.isInstalled() ? R.string.notification_title_single_ready_to_install_update : R.string.notification_title_single_ready_to_install); // TODO - "Update"? Should just be "ready to install"?
case Installing:
return app.name;
case Installed:
return app.name;
case InstallError:
return "Install Failed";
return context.getString(R.string.notification_title_single_install_error);
}
return "";
}
@ -178,15 +272,15 @@ class NotificationHelper {
case UpdateAvailable:
return app.name;
case Downloading:
return String.format("Downloading update for \"%s\"...", app.name);
return context.getString(R.string.notification_content_single_downloading, app.name);
case ReadyToInstall:
return app.name;
case Installing:
return String.format("Installing \"%s\"...", app.name);
return context.getString(R.string.notification_content_single_installing, app.name);
case Installed:
return "Successfully installed";
return context.getString(R.string.notification_content_single_installed);
case InstallError:
return "Install Failed";
return context.getString(R.string.notification_content_single_install_error);
}
return "";
}
@ -194,17 +288,17 @@ class NotificationHelper {
private String getMultiItemContentString(App app, AppUpdateStatusManager.Status status) {
switch (status) {
case UpdateAvailable:
return "Update available";
return context.getString(R.string.notification_title_summary_update_available);
case Downloading:
return "Downloading update...";
return context.getString(app.isInstalled() ? R.string.notification_title_summary_downloading_update : R.string.notification_title_summary_downloading);
case ReadyToInstall:
return "Ready to install";
return context.getString(app.isInstalled() ? R.string.notification_title_summary_ready_to_install_update : R.string.notification_title_summary_ready_to_install);
case Installing:
return "Installing";
return context.getString(R.string.notification_title_summary_installing);
case Installed:
return "Successfully installed";
return context.getString(R.string.notification_title_summary_installed);
case InstallError:
return "Install Failed";
return context.getString(R.string.notification_title_summary_install_error);
}
return "";
}
@ -213,18 +307,12 @@ class NotificationHelper {
App app = entry.app;
AppUpdateStatusManager.Status status = entry.status;
// TODO - async image loading
int largeIconSize = context.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
Bitmap iconLarge = ImageLoader.getInstance().loadImageSync(app.iconUrl, new ImageSize(largeIconSize, largeIconSize));
// TODO - why?
final int icon = Build.VERSION.SDK_INT >= 11 ? R.drawable.ic_stat_notify_updates : R.drawable.ic_launcher;
Bitmap iconLarge = getLargeIconForEntry(entry);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setAutoCancel(false)
.setLargeIcon(iconLarge)
.setSmallIcon(icon)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getSingleItemTitleString(app, status))
.setContentText(getSingleItemContentString(app, status))
.setGroup(GROUP_UPDATES);
@ -261,7 +349,7 @@ class NotificationHelper {
}
private NotificationCompat.Builder createUpdateSummaryNotification(ArrayList<AppUpdateStatusManager.AppUpdateStatus> updates) {
String title = String.format("%d Updates", updates.size());
String title = context.getString(R.string.notification_summary_updates, updates.size());
StringBuilder text = new StringBuilder();
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
@ -285,7 +373,7 @@ class NotificationHelper {
}
if (updates.size() > MAX_UPDATES_TO_SHOW) {
int diff = updates.size() - MAX_UPDATES_TO_SHOW;
inboxStyle.setSummaryText(context.getString(R.string.update_notification_more, diff));
inboxStyle.setSummaryText(context.getString(R.string.notification_summary_more, diff));
}
// Intent to open main app list
@ -316,16 +404,14 @@ class NotificationHelper {
private NotificationCompat.Builder createInstalledNotification(AppUpdateStatusManager.AppUpdateStatus entry) {
App app = entry.app;
int largeIconSize = context.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
Bitmap iconLarge = ImageLoader.getInstance().loadImageSync(app.iconUrl, new ImageSize(largeIconSize, largeIconSize));
Bitmap iconLarge = getLargeIconForEntry(entry);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setAutoCancel(true)
.setLargeIcon(iconLarge)
.setSmallIcon(R.drawable.ic_stat_notify_updates)
.setContentTitle(app.name)
.setContentText("Successfully Installed")
.setContentText(context.getString(R.string.notification_content_single_installed))
.setGroup(GROUP_INSTALLED);
PackageManager pm = context.getPackageManager();
@ -341,7 +427,7 @@ class NotificationHelper {
}
private NotificationCompat.Builder createInstalledSummaryNotification(ArrayList<AppUpdateStatusManager.AppUpdateStatus> installed) {
String title = String.format("%d Apps Installed", installed.size());
String title = context.getString(R.string.notification_summary_installed, installed.size());
StringBuilder text = new StringBuilder();
NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
@ -357,7 +443,7 @@ class NotificationHelper {
bigTextStyle.bigText(text);
if (installed.size() > MAX_INSTALLED_TO_SHOW) {
int diff = installed.size() - MAX_INSTALLED_TO_SHOW;
bigTextStyle.setSummaryText(context.getString(R.string.update_notification_more, diff));
bigTextStyle.setSummaryText(context.getString(R.string.notification_summary_more, diff));
}
// Intent to open main app list
@ -381,65 +467,58 @@ class NotificationHelper {
return builder;
}
private BroadcastReceiver receiverNotificationsCleared = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED:
appUpdateStatusMananger.clearAllUpdates();
break;
case BROADCAST_NOTIFICATIONS_ALL_INSTALLED_CLEARED:
appUpdateStatusMananger.clearAllInstalled();
break;
case BROADCAST_NOTIFICATIONS_UPDATE_CLEARED:
break;
case BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED:
String key = intent.getStringExtra(EXTRA_NOTIFICATION_KEY);
appUpdateStatusMananger.removeApk(key);
break;
private Point getLargeIconSize() {
int w;
int h;
if (Build.VERSION.SDK_INT >= 11) {
w = context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
h = context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
} else {
w = h = context.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
}
return new Point(w, h);
}
private Bitmap getLargeIconForEntry(AppUpdateStatusManager.AppUpdateStatus entry) {
final Point largeIconSize = getLargeIconSize();
Bitmap iconLarge = null;
if (DiskCacheUtils.findInCache(entry.app.iconUrl, ImageLoader.getInstance().getDiskCache()) != null) {
iconLarge = ImageLoader.getInstance().loadImageSync(entry.app.iconUrl, new ImageSize(largeIconSize.x, largeIconSize.y), displayImageOptions);
} else {
// Load it for later!
ImageLoader.getInstance().loadImage(entry.app.iconUrl, new ImageSize(largeIconSize.x, largeIconSize.y), displayImageOptions, new ImageLoadingListener() {
AppUpdateStatusManager.AppUpdateStatus entry;
ImageLoadingListener init(AppUpdateStatusManager.AppUpdateStatus entry) {
this.entry = entry;
return this;
}
};
private BroadcastReceiver receiverAppStatusChanges = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED:
notificationManager.cancelAll();
for (AppUpdateStatusManager.AppUpdateStatus entry : appUpdateStatusMananger.getAll()) {
createNotification(entry);
public void onLoadingStarted(String imageUri, View view) {
}
updateSummaryNotifications();
break;
case AppUpdateStatusManager.BROADCAST_APPSTATUS_ADDED: {
String url = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL);
AppUpdateStatusManager.AppUpdateStatus entry = appUpdateStatusMananger.get(url);
if (entry != null) {
createNotification(entry);
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
}
updateSummaryNotifications();
break;
}
case AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED: {
String url = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL);
AppUpdateStatusManager.AppUpdateStatus entry = appUpdateStatusMananger.get(url);
if (entry != null) {
createNotification(entry);
}
if (intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false)) {
updateSummaryNotifications();
}
break;
}
case AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED: {
String url = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL);
notificationManager.cancel(url, NOTIFY_ID_INSTALLED);
notificationManager.cancel(url, NOTIFY_ID_UPDATES);
updateSummaryNotifications();
break;
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
// Need to check that the notification is still valid, and also that the image
// is indeed cached now, so we won't get stuck in an endless loop.
AppUpdateStatusManager.AppUpdateStatus oldEntry = appUpdateStatusManager.get(entry.getUniqueKey());
if (oldEntry != null && DiskCacheUtils.findInCache(oldEntry.app.iconUrl, ImageLoader.getInstance().getDiskCache()) != null) {
createNotification(oldEntry); // Update with new image!
}
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
}
}.init(entry));
}
return iconLarge;
}
};
}

View File

@ -14,6 +14,7 @@ import android.text.TextUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.fdroid.fdroid.AppDetails;
import org.fdroid.fdroid.AppUpdateStatusManager;
import org.fdroid.fdroid.Hasher;
import org.fdroid.fdroid.Utils;
@ -107,8 +108,9 @@ public class InstallManagerService extends Service {
@Override
public void onReceive(Context context, Intent intent) {
String packageName = intent.getData().getSchemeSpecificPart();
//TODO: do we need to mark as installed, or is this handled by other code already?
//appUpdateStatusManager.removeApk(packageName);
for (AppUpdateStatusManager.AppUpdateStatus status : appUpdateStatusManager.getByPackageName(packageName)) {
appUpdateStatusManager.updateApk(status.getUniqueKey(), AppUpdateStatusManager.Status.Installed, null);
}
}
};
IntentFilter intentFilter = new IntentFilter();
@ -292,7 +294,7 @@ public class InstallManagerService extends Service {
}
break;
case Downloader.ACTION_INTERRUPTED:
appUpdateStatusManager.updateApk(urlString, AppUpdateStatusManager.Status.UpdateAvailable, null);
appUpdateStatusManager.updateApk(urlString, AppUpdateStatusManager.Status.Unknown, null);
localBroadcastManager.unregisterReceiver(this);
break;
default:
@ -325,28 +327,23 @@ public class InstallManagerService extends Service {
localBroadcastManager.unregisterReceiver(this);
break;
case Installer.ACTION_INSTALL_INTERRUPTED:
appUpdateStatusManager.updateApk(downloadUrl, AppUpdateStatusManager.Status.ReadyToInstall, null);
AppUpdateStatusManager.AppUpdateStatus status = appUpdateStatusManager.get(downloadUrl);
appUpdateStatusManager.removeApk(downloadUrl);
apk = intent.getParcelableExtra(Installer.EXTRA_APK);
String errorMessage =
intent.getStringExtra(Installer.EXTRA_ERROR_MESSAGE);
// show notification if app details is not visible
if (!TextUtils.isEmpty(errorMessage)) {
if (status == null || status.app == null || !AppDetails.isAppVisible(status.app.packageName)) {
appUpdateStatusManager.setApkError(apk, errorMessage);
// App app = getAppFromActive(downloadUrl);
// if (app == null) {
// ContentResolver resolver = context.getContentResolver();
// app = AppProvider.Helper.findSpecificApp(resolver, apk.packageName, apk.repo);
// }
// TODO - show error
}
}
localBroadcastManager.unregisterReceiver(this);
break;
case Installer.ACTION_INSTALL_USER_INTERACTION:
apk = intent.getParcelableExtra(Installer.EXTRA_APK);
PendingIntent installPendingIntent =
intent.getParcelableExtra(Installer.EXTRA_USER_INTERACTION_PI);
PendingIntent installPendingIntent = intent.getParcelableExtra(Installer.EXTRA_USER_INTERACTION_PI);
appUpdateStatusManager.addApk(apk, AppUpdateStatusManager.Status.ReadyToInstall, installPendingIntent);
break;
default:

View File

@ -122,7 +122,7 @@
<string name="one_update_available">يتوفر تحديث.</string>
<string name="many_updates_available">%d يتوفر على تحديثات.</string>
<string name="fdroid_updates_available">تحديثات اف-درويد متوفرة</string>
<string name="update_notification_more">+%1$d المزيد…</string>
<string name="notification_summary_more">+%1$d المزيد…</string>
<string name="bluetooth_activity_not_found">لا توجد طريقة إرسال بلوتوث، فضلاً إختر واحدة !</string>
<string name="repo_exists_add_fingerprint">هذه المستودعات بالفعل موجودة، بهذا سوف يتم إضافة مفتاح معلومات جديد.</string>
<string name="repo_exists_enable">هذه المستودعات بالفعل موجودة، تأكد إن كنت ترغب في إعادة تمكينه.</string>

View File

@ -214,7 +214,7 @@ rehabilitar esti repositoriu pa instalar aplicaciones dende elli.</string>
<string name="back">Atrás</string>
<string name="tab_installed_apps">Instaláu</string>
<string name="update_notification_more">+%1$d más…</string>
<string name="notification_summary_more">+%1$d más…</string>
<string name="bad_fingerprint">Buelga incorreuta</string>
<string name="invalid_url">Esto nun ye una URL válida.</string>
<string name="menu_changelog">Rexistru de cambeos</string>

View File

@ -181,7 +181,7 @@
<string name="about_source">Изходен код</string>
<string name="tab_installed_apps">Инсталирани</string>
<string name="update_notification_more">+ още %1$d…</string>
<string name="notification_summary_more">+ още %1$d…</string>
<string name="update_notification_title">Актуализиране на хранилищата</string>
<string name="install_error_unknown">Инсталирането се провали поради неизвестна грешка</string>
<string name="uninstall_error_unknown">Деинсталирането се провали поради неизвестна грешка</string>

View File

@ -181,7 +181,7 @@ tornar a habilitar el dipòsit per instal·lar aplicacions d\'aquest.</string>
<string name="links">Enllaços</string>
<string name="back">Torna</string>
<string name="update_notification_more">+%1$d més…</string>
<string name="notification_summary_more">+%1$d més…</string>
<string name="pref_language">Idioma</string>
<string name="wifi">Wi-Fi</string>
<string name="category_Graphics">Gràfics</string>

View File

@ -152,7 +152,7 @@ Pro instalaci aplikací z tohoto repozitáře ho bude nejprve třeba znovu povol
<string name="links">Odkazy</string>
<string name="back">Zpět</string>
<string name="update_notification_more">+%1$d více…</string>
<string name="notification_summary_more">+%1$d více…</string>
<string name="bluetooth_activity_not_found">Nerozpoznána žádná Bluetooth metoda přenosu, nějakou vyberte!</string>
<string name="choose_bt_send">Vyberte metodu přenosu Bluetooth</string>
<string name="repo_exists_add_fingerprint">Tento repozitář je již nastaven, budou jen přidány nové klíče.</string>

View File

@ -78,7 +78,7 @@
<string name="one_update_available">1 opdatering er tilgængelig.</string>
<string name="many_updates_available">%d opdateringer er tilgængelige.</string>
<string name="fdroid_updates_available">F-Droid Opdateringer Tilgængelige</string>
<string name="update_notification_more">+%1$d flere…</string>
<string name="notification_summary_more">+%1$d flere…</string>
<string name="bluetooth_activity_not_found">Ingen Bluetooth afsendelsesmetode fundet, vælg en!</string>
<string name="choose_bt_send">Vælg Bluetooth afsendelsesmetode</string>
<string name="send_via_bluetooth">Send over Bluetooth</string>

View File

@ -182,7 +182,7 @@ um Anwendungen daraus installieren zu können.</string>
<string name="app_incompatible">Inkompatibel</string>
<string name="links">Verweise</string>
<string name="back">Zurück</string>
<string name="update_notification_more">+%1$d weitere …</string>
<string name="notification_summary_more">+%1$d weitere …</string>
<string name="bad_fingerprint">Falscher Fingerabdruck</string>
<string name="invalid_url">Das ist keine gültige Adresse.</string>
<string name="update_notification_title">Paketquellen werden aktualisiert</string>

View File

@ -142,7 +142,7 @@
<string name="back">Πίσω</string>
<string name="tab_installed_apps">Εγκατεστημένο</string>
<string name="update_notification_more">+%1$d περισσότερα…</string>
<string name="notification_summary_more">+%1$d περισσότερα…</string>
<string name="send_via_bluetooth">Αποστολή μέσω Bluetooth</string>
<string name="bad_fingerprint">Λανθασμένο δακτυλικό αποτύπωμα</string>

View File

@ -151,7 +151,7 @@
<string name="tab_installed_apps">Instalitaj</string>
<string name="tab_installed_apps_count">Instalitaj (%d)</string>
<string name="tab_updates_count">Ĝisdatigoj (%d)</string>
<string name="update_notification_more">ankoraŭ +%1$d…</string>
<string name="notification_summary_more">ankoraŭ +%1$d…</string>
<string name="bluetooth_activity_not_found">Neniu Bludenta metodo de sendo trovita, elektu iun!</string>
<string name="choose_bt_send">Elektu Bludentan metodon de sendo</string>
<string name="repo_add_fingerprint">Fingrospuro (malnepra)</string>

View File

@ -182,7 +182,7 @@ Para ver las aplicaciones que ofrece tienes que activarlo.</string>
<string name="links">Enlaces</string>
<string name="back">Volver</string>
<string name="update_notification_more">+%1$d más…</string>
<string name="notification_summary_more">+%1$d más…</string>
<string name="uninstall_system">Actualiza/Desinstala la extensión con permisos de sistema</string>
<string name="uninstall_system_summary">Abre la pantalla de detalles de la extensión con permisos de sistema para actualizarla/desinstalarla</string>
<string name="bad_fingerprint">Huella digital incorrecta</string>

View File

@ -81,7 +81,7 @@
<string name="one_update_available">Üks värskendus on saadaval.</string>
<string name="many_updates_available">%d värskendust on saadaval.</string>
<string name="fdroid_updates_available">F-Droid: värskendused saadaval</string>
<string name="update_notification_more">+%1$d veel…</string>
<string name="notification_summary_more">+%1$d veel…</string>
<string name="bluetooth_activity_not_found">Bluetoothiga saatmisviise ei leitud. Valige üks!</string>
<string name="choose_bt_send">Vali Bluetoothiga saatmise viis</string>
<string name="send_via_bluetooth">Saada Bluetoothiga</string>

View File

@ -99,7 +99,7 @@
<string name="links">Loturak</string>
<string name="back">Atzera</string>
<string name="update_notification_more">+%1$d gehiago…</string>
<string name="notification_summary_more">+%1$d gehiago…</string>
<string name="bluetooth_activity_not_found">Ez da aurkitu Bluetooth bidez bidaltzeko metodorik, aukeratu bat!</string>
<string name="choose_bt_send">Aukeratu Bluetooth bidez bidaltzeko metodoa</string>
<string name="send_via_bluetooth">Bidali Bluetooth bidez</string>

View File

@ -116,7 +116,7 @@
<string name="tab_updates_count">به‌روز رسانی‌ها (%d)</string>
<string name="one_update_available">۱ به‌روز رسانی موجود است.</string>
<string name="many_updates_available">%d به روز رسانی موجود است.</string>
<string name="update_notification_more">+%1$d بیش‌تر…</string>
<string name="notification_summary_more">+%1$d بیش‌تر…</string>
<string name="send_via_bluetooth">ارسال با بلوتوث</string>
<string name="repo_exists_add_fingerprint">این مخزن از پیش برپا شده است. این کار، اظّلاعات کلید جدیدی را می‌افزاید.</string>

View File

@ -183,7 +183,7 @@
<string name="tab_installed_apps">Asennettu</string>
<string name="tab_installed_apps_count">Asennettu (%d)</string>
<string name="tab_updates_count">Päivitykset (%d)</string>
<string name="update_notification_more">+%1$d lisää…</string>
<string name="notification_summary_more">+%1$d lisää…</string>
<string name="update_auto_download">Lataa päivitykset automaattisesti</string>
<string name="update_auto_download_summary">Lataa päivitykset taustalla</string>
<string name="uninstall_system">Päivitä/Poista Privileged Extension</string>

View File

@ -284,7 +284,7 @@ perdues. Elle ne requiert aucune autorisation particulière.</string>
<string name="interval_1h">Toutes les heures</string>
<string name="perms_description_app">Fourni par %1$s.</string>
<string name="uninstall_system_summary">Ouvrir l\'écran des détails de l\'appli F-Droid Privileged Extension pour la mettre à jour/la désinstaller</string>
<string name="update_notification_more">%1$d de plus…</string>
<string name="notification_summary_more">%1$d de plus…</string>
<string name="status_download_unknown_size">Téléchargement de
\n%2$s depuis
\n%1$s</string>

View File

@ -101,7 +101,7 @@
<string name="overwrite">Sobreescribir</string>
<string name="tab_installed_apps">Instalado</string>
<string name="update_notification_more">+%1$d máis…</string>
<string name="notification_summary_more">+%1$d máis…</string>
<string name="bluetooth_activity_not_found">Non se atopou ningún método de transmisión Bluetooth, escolla un!</string>
<string name="choose_bt_send">Escolla o método de transmisión Bluetooth</string>
<string name="send_via_bluetooth">Enviar por Bluetooth</string>

View File

@ -57,7 +57,7 @@
<string name="one_update_available">עדכון 1 זמין.</string>
<string name="many_updates_available">%d עדכונים זמינים.</string>
<string name="fdroid_updates_available">עדכוני F-Droid זמינים</string>
<string name="update_notification_more">+%1$d עוד…</string>
<string name="notification_summary_more">+%1$d עוד…</string>
<string name="bluetooth_activity_not_found">לא נמצאה שיטת שליחה של Bluetooth, בחר אחת!</string>
<string name="choose_bt_send">בחר שיטת שליחה של Bluetooth</string>
<string name="send_via_bluetooth">שלח דרך Bluetooth</string>

View File

@ -150,7 +150,7 @@
<string name="one_update_available">१ अपडेट उपलब्ध है|</string>
<string name="many_updates_available">%d अपडेटस उपलब्ध हैं|</string>
<string name="fdroid_updates_available">F-Droid अपडेट उपलब्ध</string>
<string name="update_notification_more">+%1$d और…</string>
<string name="notification_summary_more">+%1$d और…</string>
<string name="bluetooth_activity_not_found">Bluettoth से भेजने का तरीका उपलब नहीं है, एक चुने!</string>
<string name="choose_bt_send">Bluetooth से भेजने का तरीका चुने</string>
<string name="send_via_bluetooth">Bluetooth द्वारा भेजे</string>

View File

@ -81,7 +81,7 @@
<string name="one_update_available">1 ažuriranje je dostupno.</string>
<string name="many_updates_available">%d ažuriranja je dostupno.</string>
<string name="fdroid_updates_available">Ažuriranja za F-Droid dostupna</string>
<string name="update_notification_more">+%1$d više…</string>
<string name="notification_summary_more">+%1$d više…</string>
<string name="bluetooth_activity_not_found">Nije pronađena metoda slanja preko Bluetootha, odaberite jednu!</string>
<string name="choose_bt_send">Odaberi metodu slanja preko Bluetootha</string>
<string name="send_via_bluetooth">Pošalji preko Bluetootha</string>

View File

@ -126,7 +126,7 @@ Engedélyeznie kell, hogy megtekinthesse az általa kínált appokat.</string>
<string name="tab_installed_apps">Telepítve</string>
<string name="tab_installed_apps_count">Telepítve (%d)</string>
<string name="tab_updates_count">Frissítések (%d)</string>
<string name="update_notification_more">+%1$d további…</string>
<string name="notification_summary_more">+%1$d további…</string>
<string name="send_via_bluetooth">Küldés Bluetooth-on</string>
<string name="bad_fingerprint">Rossz ujjlenyomat</string>

View File

@ -166,7 +166,7 @@
<string name="repo_last_update">Terakhir diperbarui</string>
<string name="repo_name">Nama</string>
<string name="unknown">Tidak diketahui</string>
<string name="update_notification_more">+%1$d lainnya…</string>
<string name="notification_summary_more">+%1$d lainnya…</string>
<string name="menu_settings">Pengaturan</string>
<string name="rooted_on">Jangan bedakan warna apl yang membutuhkan izin root</string>
<string name="unsigned_description">Ini artinya daftar

View File

@ -69,7 +69,7 @@
<string name="one_update_available">1 uppfærsla er tiltæk.</string>
<string name="many_updates_available">%d uppfærslur eru tiltækar.</string>
<string name="fdroid_updates_available">Uppfærslur á F-Droid eru tiltækar</string>
<string name="update_notification_more">+%1$d fleiri…</string>
<string name="notification_summary_more">+%1$d fleiri…</string>
<string name="bluetooth_activity_not_found">Engin aðferð til sendingar með Bluetooth fannst, veldu eina!</string>
<string name="choose_bt_send">Veldu aðferð til sendingar með Bluetooth</string>
<string name="send_via_bluetooth">Senda með Bluetooth</string>

View File

@ -333,7 +333,7 @@ non saranno rimossi. Non è richiesto alcun accesso speciale.</string>
di questa app integrata? I dati presenti
non saranno rimossi. Non richiede alcun permesso speciale.</string>
<string name="allPerms">Tutte</string>
<string name="update_notification_more">+%1$d rimanente…</string>
<string name="notification_summary_more">+%1$d rimanente…</string>
<string name="swap_nearby">Scambio ravvicinato</string>
<string name="empty_search_installed_app_list">Nessuna app installata corrispondente.</string>
<string name="crash_dialog_comment_prompt">Puoi aggiungere altre informazioni e commenti qui:</string>

View File

@ -181,7 +181,7 @@
<string name="links">リンク</string>
<string name="back">戻る</string>
<string name="update_notification_more">+%1$d 以上…</string>
<string name="notification_summary_more">+%1$d 以上…</string>
<string name="bad_fingerprint">フィンガープリントが違います</string>
<string name="invalid_url">有効な URL ではありません。</string>
<string name="menu_changelog">変更履歴</string>

View File

@ -194,7 +194,7 @@
<string name="tab_installed_apps">설치됨</string>
<string name="tab_installed_apps_count">설치됨 (%d)</string>
<string name="tab_updates_count">업데이트 (%d)</string>
<string name="update_notification_more">+%1$d 이상…</string>
<string name="notification_summary_more">+%1$d 이상…</string>
<string name="bad_fingerprint">올바르지 않은 핑거프린트</string>
<string name="invalid_url">올바른 URL이 아닙니다.</string>
<string name="menu_settings">설정</string>

View File

@ -77,7 +77,7 @@
<string name="one_update_available">အသစ္မြမ္းမံမႈ ၁ ခုရရွိႏိုင္သည္</string>
<string name="many_updates_available">အသစ္မြမ္းမံမႈ %d ခုရရွိႏိုင္သည္.</string>
<string name="fdroid_updates_available">F-Droid အသစ္မြမ္းမံမႈရရွိႏိုင္သည္</string>
<string name="update_notification_more">+%1$d ေနာက္ထပ္..</string>
<string name="notification_summary_more">+%1$d ေနာက္ထပ္..</string>
<string name="bluetooth_activity_not_found">ဘလူးသုဒ့္ႏွင့္ပို႔ရန္နည္းလမ္းရွာမေတြ႕ပါ။ တစ္ခုေရြးပါ!</string>
<string name="choose_bt_send">ဘလူးသုဒ့္ႏွင့္ပို႔ေသာနည္းလမ္းကိုေရြးမည္</string>
<string name="send_via_bluetooth">ဘလူးသုဒ့္မွတစ္ဆင့္ပို႔မည္</string>

View File

@ -185,7 +185,7 @@ skru på denne pakkebrønnen igjen for å installere programmer fra den.</string
<string name="back">Tilbake</string>
<string name="tab_installed_apps">Installert</string>
<string name="update_notification_more">+%1$d mer…</string>
<string name="notification_summary_more">+%1$d mer…</string>
<string name="bad_fingerprint">Feil i fingeravtrykk</string>
<string name="invalid_url">Dette er ikke en gyldig nettadresse.</string>
<string name="menu_changelog">Endringslogg</string>

View File

@ -179,7 +179,7 @@ Je moet deze bron weer inschakelen indien je er apps van wil installeren.</strin
<string name="links">Links</string>
<string name="back">Terug</string>
<string name="update_notification_more">+%1$d meer…</string>
<string name="notification_summary_more">+%1$d meer…</string>
<string name="bad_fingerprint">Slechte vingerafdruk</string>
<string name="invalid_url">Dit is geen correcte URL.</string>
<string name="menu_changelog">Lijst van veranderingen</string>

View File

@ -155,7 +155,7 @@ Uwaga: Wszystkie poprzednio zainstalowane aplikacje zostaną na urządzeniu.</st
<string name="back">Powrót</string>
<string name="many_updates_available">Liczba dostępnych aktualizacji: %d.</string>
<string name="update_notification_more">+%1$d więcej…</string>
<string name="notification_summary_more">+%1$d więcej…</string>
<string name="bluetooth_activity_not_found">Nie znaleziono metody do wysłania przez Bluetooth!</string>
<string name="choose_bt_send">Wybierz metodę wysłania przez Bluetooth</string>
<string name="repo_exists_add_fingerprint">To repozytorium jest już dodane. Klucz zostanie zaktualizowany.</string>

View File

@ -186,7 +186,7 @@ reativar este repositório para instalar aplicativos a partir dele.</string>
<string name="links">Links</string>
<string name="back">Voltar</string>
<string name="update_notification_more">Mais +%1$d…</string>
<string name="notification_summary_more">Mais +%1$d…</string>
<string name="bad_fingerprint">Falha na fingerprint</string>
<string name="invalid_url">Esta não é uma URL válida.</string>
<string name="menu_changelog">Changelog</string>

View File

@ -66,7 +66,7 @@
<string name="one_update_available">1 atualização disponível.</string>
<string name="many_updates_available">%d atualizações disponíveis.</string>
<string name="fdroid_updates_available">Atualizações F-Droid disponíveis</string>
<string name="update_notification_more">+%1$d…</string>
<string name="notification_summary_more">+%1$d…</string>
<string name="bluetooth_activity_not_found">Nenhum método de envio Bluetooth encontrado. Escolha um!</string>
<string name="choose_bt_send">Escolha o método de envio Bluetooth</string>
<string name="send_via_bluetooth">Enviar por Bluetooth</string>

View File

@ -97,7 +97,7 @@
<string name="tab_installed_apps_count">Instalat (%d)</string>
<string name="tab_updates_count">Actualizari (%d)</string>
<string name="fdroid_updates_available">Actualizari disponibile in F-Droid</string>
<string name="update_notification_more">+%1$d mai mult…</string>
<string name="notification_summary_more">+%1$d mai mult…</string>
<string name="bluetooth_activity_not_found">Nu a fost gasita o metoda Bluetooth de a trimite, alegeti una!</string>
<string name="choose_bt_send">Alegeti metoda de a trimite prin Bluetooth</string>
<string name="send_via_bluetooth">Trimite prin Bluetooth</string>

View File

@ -212,7 +212,7 @@
<string name="less">Меньше</string>
<string name="back">Назад</string>
<string name="update_notification_more">Детали +%1$d …</string>
<string name="notification_summary_more">Детали +%1$d …</string>
<string name="bad_fingerprint">Неверный отпечаток ключа</string>
<string name="invalid_url">URL некорректен.</string>
<string name="menu_changelog">Список изменений</string>

View File

@ -184,7 +184,7 @@ Depes
<string name="links">Ligàmenes</string>
<string name="back">In dae segus</string>
<string name="update_notification_more">+%1$d àteru(os)…</string>
<string name="notification_summary_more">+%1$d àteru(os)…</string>
<string name="invalid_url">Custu no est unu ligàmene vàlidu.</string>
<string name="menu_changelog">Lista modìficas</string>
<string name="update_notification_title">Agiornende sos depòsitos</string>

View File

@ -187,7 +187,7 @@ znovu povoliť tento repozitár pre inštaláciu aplikácií z neho.</string>
<string name="back">Späť</string>
<string name="tab_installed_apps">Nainštalované</string>
<string name="update_notification_more">+%1$d viac…</string>
<string name="notification_summary_more">+%1$d viac…</string>
<string name="bluetooth_activity_not_found">Posielanie cez Bluetooth zlyhalo, zvoľte inú metódu!</string>
<string name="choose_bt_send">Vyberte posielanie cez Bluetooth</string>
<string name="repo_exists_and_enabled">Tento repozitár je už nastavený a povolený.</string>

View File

@ -76,7 +76,7 @@
<string name="one_update_available">Chekunatsa 1 chiripo.</string>
<string name="many_updates_available">Zvekunatsa %d zviripo.</string>
<string name="fdroid_updates_available">Zvekunatsa F-Droid zviripo</string>
<string name="update_notification_more">zvimwe +%1$d …</string>
<string name="notification_summary_more">zvimwe +%1$d …</string>
<string name="bluetooth_activity_not_found">Hapana mutowo wekutumira neBluetooth wawanikwa, sarudza imwe chete!</string>
<string name="choose_bt_send">Sarudza mutowo weBluetooth wekutumira nawo</string>
<string name="send_via_bluetooth">Tumira kuburikira neBluetooth</string>

View File

@ -188,7 +188,7 @@
<string name="back">Назад</string>
<string name="tab_installed_apps">Инсталиране</string>
<string name="update_notification_more">+још %1$d…</string>
<string name="notification_summary_more">+још %1$d…</string>
<string name="bad_fingerprint">Лош отисак</string>
<string name="invalid_url">Ово није исправна адреса.</string>
<string name="menu_changelog">Дневник измена</string>

View File

@ -191,7 +191,7 @@ Du kommer
<string name="back">Bakåt</string>
<string name="tab_installed_apps">Installerade</string>
<string name="update_notification_more">+%1$d mer…</string>
<string name="notification_summary_more">+%1$d mer…</string>
<string name="bad_fingerprint">Felaktigt fingeravtryck</string>
<string name="invalid_url">Det här är inte en giltig hemsideadress.</string>
<string name="menu_settings">Inställningar</string>

View File

@ -314,7 +314,7 @@
<string name="swap_not_visible_wifi">ไม่แสดงตัวบน Wi-Fi</string>
<string name="swap_no_peers_nearby">ไม่พบคนรอบข้างที่สามารถจะแบ่งปันโปรแกรมด้วยได้</string>
<string name="swap_qr_isnt_for_swap">QR Code ที่อ่านได้ ไม่ใช่โค้ดที่ใช้แบ่งปันโปรแกรม</string>
<string name="update_notification_more">มีอีก +%1$d…</string>
<string name="notification_summary_more">มีอีก +%1$d…</string>
<string name="perms_description_app">จัดให้โดย %1$s</string>
<string name="swap_cant_find_peers">ไม่เจอคนที่ตามหาหรือ?</string>
<string name="swap_nearby">แลกเปลี่ยนโปรแกรมกับคนข้างๆ</string>

View File

@ -203,7 +203,7 @@ bu depoyu tekrar etkinleştirmeniz gerekecektir.</string>
<string name="tab_installed_apps">Kurulu</string>
<string name="tab_installed_apps_count">Kurulu (%d)</string>
<string name="tab_updates_count">Güncellemeler (%d)</string>
<string name="update_notification_more">+%1$d daha…</string>
<string name="notification_summary_more">+%1$d daha…</string>
<string name="bad_fingerprint">Yanlış parmak izi</string>
<string name="invalid_url">Bu, geçerli bir URL değildir.</string>
<string name="menu_settings">Ayarlar</string>

View File

@ -90,7 +90,7 @@
<string name="one_update_available">Одне оновлення доступно.</string>
<string name="many_updates_available">%d оновлень доступно.</string>
<string name="fdroid_updates_available">F-Droid: доступні оновлення</string>
<string name="update_notification_more">+%1$d більше…</string>
<string name="notification_summary_more">+%1$d більше…</string>
<string name="send_via_bluetooth">Надіслати через Bluetooth</string>
<string name="menu_share">Поділитися</string>

View File

@ -168,7 +168,7 @@
<string name="about_source">Mã nguồn</string>
<string name="app_incompatible">Không tương thích</string>
<string name="tab_installed_apps">Đã cài đặt</string>
<string name="update_notification_more">+%1$d ứng dụng khác…</string>
<string name="notification_summary_more">+%1$d ứng dụng khác…</string>
<string name="invalid_url">Đây không phải là URL hợp lệ.</string>
<string name="menu_changelog">Lịch sử sửa đổi</string>
<string name="menu_bitcoin">Bitcoin</string>

View File

@ -168,7 +168,7 @@
<string name="tab_installed_apps">已安装</string>
<string name="tab_installed_apps_count">已安装(%d</string>
<string name="tab_updates_count">可更新(%d</string>
<string name="update_notification_more">+%1$d 更多…</string>
<string name="notification_summary_more">+%1$d 更多…</string>
<string name="send_via_bluetooth">用蓝牙发送</string>
<string name="bad_fingerprint">指纹错误</string>

View File

@ -228,7 +228,7 @@
<string name="install_confirm_update_system_no_perms">您想更新此應用程式嗎?
您不會失去現有的數據,
已更新的程式亦不需要任何特別的存取權。</string>
<string name="update_notification_more">還有 +%1$d 個…</string>
<string name="notification_summary_more">還有 +%1$d 個…</string>
<string name="next">下一步</string>
<string name="minsdk_up_to_maxsdk">%1$s 至 %2$s</string>
<string name="SignatureMismatch">應用程式的新版本使用了不同的鑰匙簽署。若要安裝新版本,您必須先將舊版本卸載,然後再嘗試安裝。(注意:卸載將會把應用程式內的資料刪除)</string>

View File

@ -257,7 +257,7 @@
<string name="local_repo_https">使用私密連線</string>
<string name="repo_error_empty_username">空的使用者名稱,憑證未改變</string>
<string name="update_notification_more">+%1$d 更多…</string>
<string name="notification_summary_more">+%1$d 更多…</string>
<string name="repo_exists_enable">此應用軟體倉庫已經設立。確認您要重新啟用它。</string>
<string name="repo_exists_and_enabled">進入的儲存庫已設立並已啟用。</string>
<string name="malformed_repo_uri">略過異常的應用軟體倉庫 URI%s</string>

View File

@ -88,10 +88,7 @@
<string name="tab_updates">Updates</string>
<string name="tab_installed_apps_count">Installed (%d)</string>
<string name="tab_updates_count">Updates (%d)</string>
<string name="one_update_available">1 update is available.</string>
<string name="many_updates_available">%d updates are available.</string>
<string name="fdroid_updates_available">F-Droid Updates Available</string>
<string name="update_notification_more">+%1$d more…</string>
<string name="bluetooth_activity_not_found">No Bluetooth send method found, choose one!</string>
<string name="choose_bt_send">Choose Bluetooth send method</string>
<string name="send_via_bluetooth">Send via Bluetooth</string>
@ -400,4 +397,29 @@
forcing the application to stop. Would you like to e-mail the
details to help fix the issue?</string>
<string name="crash_dialog_comment_prompt">You can add extra information and comments here:</string>
<!-- notifications -->
<string name="notification_summary_more">+%1$d more…</string>
<string name="notification_title_single_update_available">Update Available</string>
<string name="notification_title_single_ready_to_install">Ready to install</string>
<string name="notification_title_single_ready_to_install_update">Update ready to install</string>
<string name="notification_title_single_install_error">Install Failed</string>
<string name="notification_content_single_downloading">Downloading update for \"%1$s\"&#8230;</string>
<string name="notification_content_single_installing">Installing \"%1$s\"&#8230;</string>
<string name="notification_content_single_installed">Successfully installed</string>
<string name="notification_content_single_install_error">Install Failed</string>
<string name="notification_summary_updates">%1$d Updates</string>
<string name="notification_summary_installed">%1$d Apps Installed</string>
<string name="notification_title_summary_update_available">Update available</string>
<string name="notification_title_summary_downloading">Downloading&#8230;</string>
<string name="notification_title_summary_downloading_update">Downloading update&#8230;</string>
<string name="notification_title_summary_ready_to_install">Ready to install</string>
<string name="notification_title_summary_ready_to_install_update">Update ready to install</string>
<string name="notification_title_summary_installing">Installing</string>
<string name="notification_title_summary_installed">Successfully installed</string>
<string name="notification_title_summary_install_error">Install Failed</string>
<string name="notification_action_update">Update</string>
<string name="notification_action_cancel">Cancel</string>
<string name="notification_action_install">Install</string>
</resources>