Merge branch 'develop' into regular_authentication_in_saml_server

This commit is contained in:
David A. Velasco 2014-03-21 11:02:36 +01:00
commit a3bf6883fc
19 changed files with 517 additions and 347 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
ownCloud Android client application
Copyright (C) 2014 ownCloud Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView android:id="@+id/icon"
android:layout_width="@android:dimen/notification_large_icon_width"
android:layout_height="@android:dimen/notification_large_icon_height"
android:scaleType="center"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:minHeight="64dp"
android:orientation="vertical"
android:paddingRight="12dp"
android:paddingLeft="12dp"
>
<TextView android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
style="@style/Theme.ownCloud.NotificationText.Title"
/>
<TextView android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-2dp"
android:layout_marginBottom="-2dp"
android:singleLine="true"
android:fadingEdge="horizontal"
android:ellipsize="marquee"
style="@style/Theme.ownCloud.NotificationText.Content"
/>
<FrameLayout android:id="@+id/progressHolder"
android:layout_width="match_parent"
android:layout_height="12dp"
>
<!-- the FrameLayout is needed to change visibility of the
progress bar in Android 2.2, even though
https://code.google.com/p/android/issues/detail?id=11040 -->
<ProgressBar
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="?android:attr/progressBarStyleHorizontal"
/>
</FrameLayout>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
ownCloud Android client application
Copyright (C) 2014 ownCloud Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="5dp"
android:paddingLeft="5dp"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="3dp"
>
<ImageView android:id="@+id/icon"
android:layout_width="25dp"
android:layout_height="25dp"
android:scaleType="centerInside"
/>
<TextView android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:paddingLeft="4dp"
style="@style/Theme.ownCloud.NotificationText.Title"
/>
</LinearLayout>
<TextView android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
style="@style/Theme.ownCloud.NotificationText.Content"
/>
<FrameLayout android:id="@+id/progressHolder"
android:layout_width="match_parent"
android:layout_height="10dp"
android:paddingTop="2dp"
android:paddingBottom="2dp"
>
<!-- the FrameLayout is needed to change visibility of the
progress bar in Android 2.2, even though
https://code.google.com/p/android/issues/detail?id=11040 -->
<ProgressBar
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="?android:attr/progressBarStyleHorizontal"
/>
</FrameLayout>
</LinearLayout>

View file

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
ownCloud Android client application
Copyright (C) 2012 Bartek Przybylski
Copyright (C) 2012-2013 ownCloud Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:padding="5dp">
<ImageView android:id="@+id/status_icon"
android:layout_width="wrap_content" android:layout_height="fill_parent"
android:layout_alignParentLeft="true" />
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_toRightOf="@id/status_icon">
<TextView android:id="@+id/status_text" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_alignParentTop="true" />
<ProgressBar android:id="@+id/status_progress"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_below="@id/status_text"
android:progressDrawable="@android:drawable/progress_horizontal"
android:indeterminate="false" android:indeterminateOnly="false" />
</RelativeLayout>
</RelativeLayout>

View file

@ -6,4 +6,17 @@
<item name="android:textColor">@color/button_text_color</item>
</style>
<!-- Notifications -->
<!-- Notifications -->
<style name="Theme.ownCloud.NotificationText.Title"
parent="@android:style/TextAppearance.StatusBar.EventContent.Title" >
<item name="android:textSize">18sp</item>
<item name="android:textStyle">bold</item>
</style>
<style name="Theme.ownCloud.NotificationText.Content"
parent="@android:style/TextAppearance.StatusBar.EventContent" >
<item name="android:textSize">16sp</item>
</style>
</resources>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Notifications -->
<style name="Theme.ownCloud.NotificationText.Title"
parent="@android:style/TextAppearance.StatusBar.EventContent.Title"
/>
<style name="Theme.ownCloud.NotificationText.Content"
parent="@android:style/TextAppearance.StatusBar.EventContent"
/>
</resources>

View file

@ -16,4 +16,16 @@
<item name="android:indeterminateDrawable">@drawable/abs__progress_medium_holo</item>
</style>
<!-- Notifications -->
<style name="Theme.ownCloud.NotificationText.Title"
parent="@android:style/TextAppearance">
<item name="android:textColor">#ff000000</item>
<item name="android:textSize">18sp</item>
<item name="android:textStyle">bold</item>
</style>
<style name="Theme.ownCloud.NotificationText.Content"
parent="@android:style/TextAppearance">
<item name="android:textColor">#ff000000</item>
<item name="android:textSize">14sp</item>
</style>
</resources>

View file

@ -1,156 +0,0 @@
/* ownCloud Android client application
* Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2012-2013 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.files.managers;
import java.util.HashMap;
import java.util.Map;
import com.owncloud.android.R;
import com.owncloud.android.utils.DisplayUtils;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.widget.RemoteViews;
public class OCNotificationManager {
enum NotificationType {
NOTIFICATION_SIMPLE,
NOTIFICATION_PROGRESS
}
static public class NotificationData {
private String mText, mSubtitle;
private int mPercent;
private boolean mOngoing;
public NotificationData(String text, String subtitle, boolean ongoing) {
this(text, subtitle, -1, ongoing);
}
public NotificationData(int percent, boolean ongoing) {
this(null, null, percent, ongoing);
}
public NotificationData(String text, int percent, boolean ongoing) {
this(text, null, percent, ongoing);
}
public NotificationData(String text, String subtitle, int percent, boolean ongoing) {
mText = text;
mPercent = percent;
mSubtitle = subtitle;
mOngoing = ongoing;
}
public String getText() { return mText; }
public int getPercent() { return mPercent; }
public String getSubtitle() { return mSubtitle; }
public boolean getOngoing() { return mOngoing; }
}
static private OCNotificationManager mInstance = null;
private class NotificationTypePair {
public Notification mNotificaiton;
public NotificationType mType;
public NotificationTypePair(Notification n, NotificationType type) {
mNotificaiton = n;
mType = type;
}
}
private Context mContext;
private Map<Integer, NotificationTypePair> mNotificationMap;
private int mNotificationCounter;
NotificationManager mNM;
static OCNotificationManager getInstance(Context context) {
if (mInstance == null)
mInstance = new OCNotificationManager(context);
return mInstance;
}
OCNotificationManager(Context context) {
mContext = context;
mNotificationMap = new HashMap<Integer, NotificationTypePair>();
mNM = (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationCounter = 0;
}
public int postNotification(NotificationType type, NotificationData data) {
mNotificationCounter++;
Notification notification = null;
switch (type) {
case NOTIFICATION_SIMPLE:
notification = new Notification(DisplayUtils.getSeasonalIconId(), data.getText(), System.currentTimeMillis());
break;
case NOTIFICATION_PROGRESS:
notification = new Notification();
notification.contentView = new RemoteViews(mContext.getPackageName(), R.layout.progressbar_layout);
notification.contentView.setTextViewText(R.id.status_text,
data.getText());
notification.contentView.setImageViewResource(R.id.status_icon,
R.id.icon);
notification.contentView.setProgressBar(R.id.status_progress,
100,
data.getPercent(),
false);
break;
default:
return -1;
}
if (data.getOngoing()) {
notification.flags |= notification.flags | Notification.FLAG_ONGOING_EVENT;
}
mNotificationMap.put(mNotificationCounter, new NotificationTypePair(notification, type));
return mNotificationCounter;
}
public boolean updateNotification(int notification_id, NotificationData data) {
if (!mNotificationMap.containsKey(notification_id)) {
return false;
}
NotificationTypePair pair = mNotificationMap.get(notification_id);
switch (pair.mType) {
case NOTIFICATION_PROGRESS:
pair.mNotificaiton.contentView.setProgressBar(R.id.status_text,
100,
data.getPercent(),
false);
return true;
case NOTIFICATION_SIMPLE:
pair.mNotificaiton = new Notification(DisplayUtils.getSeasonalIconId(),
data.getText(), System.currentTimeMillis());
mNM.notify(notification_id, pair.mNotificaiton);
return true;
default:
return false;
}
}
public void discardNotification(int notification_id) {
mNM.cancel(notification_id);
mNotificationMap.remove(notification_id);
}
}

View file

@ -44,12 +44,11 @@ import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.preview.PreviewImageActivity;
import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.Log_OC;
import com.owncloud.android.utils.NotificationBuilderWithProgressBar;
import android.accounts.Account;
import android.accounts.AccountsException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
@ -61,7 +60,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.widget.RemoteViews;
import android.support.v4.app.NotificationCompat;
public class FileDownloader extends Service implements OnDatatransferProgressListener {
@ -88,7 +87,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
private DownloadFileOperation mCurrentDownload = null;
private NotificationManager mNotificationManager;
private Notification mNotification;
private NotificationCompat.Builder mNotificationBuilder;
private int mLastPercent;
@ -404,13 +403,19 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
private void notifyDownloadStart(DownloadFileOperation download) {
/// create status notification with a progress bar
mLastPercent = 0;
mNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(R.string.downloader_download_in_progress_ticker), System.currentTimeMillis());
mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
mNotification.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.progressbar_layout);
mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, download.getSize() < 0);
mNotification.contentView.setTextViewText(R.id.status_text, String.format(getString(R.string.downloader_download_in_progress_content), 0, new File(download.getSavePath()).getName()));
mNotification.contentView.setImageViewResource(R.id.status_icon, DisplayUtils.getSeasonalIconId());
mNotificationBuilder =
NotificationBuilderWithProgressBar.newNotificationBuilderWithProgressBar(this);
mNotificationBuilder
.setSmallIcon(R.drawable.notification_icon)
.setTicker(getString(R.string.downloader_download_in_progress_ticker))
.setContentTitle(getString(R.string.downloader_download_in_progress_ticker))
.setOngoing(true)
.setProgress(100, 0, download.getSize() < 0)
.setContentText(
String.format(getString(R.string.downloader_download_in_progress_content), 0,
new File(download.getSavePath()).getName())
);
/// includes a pending intent in the notification showing the details view of the file
Intent showDetailsIntent = null;
if (PreviewImageFragment.canBePreviewed(download.getFile())) {
@ -421,9 +426,12 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, download.getFile());
showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, download.getAccount());
showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), showDetailsIntent, 0);
mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);
mNotificationBuilder.setContentIntent(PendingIntent.getActivity(
this, (int) System.currentTimeMillis(), showDetailsIntent, 0
));
mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotificationBuilder.build());
}
@ -434,11 +442,11 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filePath) {
int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
if (percent != mLastPercent) {
mNotification.contentView.setProgressBar(R.id.status_progress, 100, percent, totalToTransfer < 0);
mNotificationBuilder.setProgress(100, percent, totalToTransfer < 0);
String fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1);
String text = String.format(getString(R.string.downloader_download_in_progress_content), percent, fileName);
mNotification.contentView.setTextViewText(R.id.status_text, text);
mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);
mNotificationBuilder.setContentText(text);
mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotificationBuilder.build());
}
mLastPercent = percent;
}
@ -455,8 +463,12 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
if (!downloadResult.isCancelled()) {
int tickerId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_ticker : R.string.downloader_download_failed_ticker;
int contentId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_content : R.string.downloader_download_failed_content;
Notification finalNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(tickerId), System.currentTimeMillis());
finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
mNotificationBuilder
.setTicker(getString(tickerId))
.setContentTitle(getString(tickerId))
.setAutoCancel(true)
.setOngoing(false)
.setProgress(0, 0, false);
boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
// (downloadResult.isTemporalRedirection() && downloadResult.isIdPRedirection()
(downloadResult.isIdPRedirection()
@ -471,11 +483,11 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
finalNotification.contentIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
finalNotification.setLatestEventInfo( getApplicationContext(),
getString(tickerId),
String.format(getString(contentId), new File(download.getSavePath()).getName()),
finalNotification.contentIntent);
mNotificationBuilder
.setContentIntent(PendingIntent.getActivity(
this, (int) System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT
))
.setContentText(String.format(getString(contentId), new File(download.getSavePath()).getName()));
mDownloadClient = null; // grant that future retries on the same account will get the fresh credentials
} else {
@ -494,10 +506,13 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
// TODO put something smart in showDetailsIntent
showDetailsIntent = new Intent();
}
finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), showDetailsIntent, 0);
finalNotification.setLatestEventInfo(getApplicationContext(), getString(tickerId), String.format(getString(contentId), new File(download.getSavePath()).getName()), finalNotification.contentIntent);
mNotificationBuilder
.setContentIntent(PendingIntent.getActivity(
this, (int) System.currentTimeMillis(), showDetailsIntent, 0
))
.setContentText(String.format(getString(contentId), new File(download.getSavePath()).getName()));
}
mNotificationManager.notify(tickerId, finalNotification);
mNotificationManager.notify(tickerId, mNotificationBuilder.build());
}
}

View file

@ -53,13 +53,12 @@ import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.activity.InstantUploadActivity;
import com.owncloud.android.ui.preview.PreviewImageActivity;
import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.Log_OC;
import com.owncloud.android.utils.NotificationBuilderWithProgressBar;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountsException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
@ -71,8 +70,8 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.support.v4.app.NotificationCompat;
import android.webkit.MimeTypeMap;
import android.widget.RemoteViews;
@ -117,9 +116,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
private UploadFileOperation mCurrentUpload = null;
private NotificationManager mNotificationManager;
private Notification mNotification;
private NotificationCompat.Builder mNotificationBuilder;
private int mLastPercent;
private RemoteViews mDefaultNotificationContentView;
public static String getUploadFinishMessage() {
@ -678,30 +676,30 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
*
* @param upload Upload operation starting.
*/
@SuppressWarnings("deprecation")
private void notifyUploadStart(UploadFileOperation upload) {
// / create status notification with a progress bar
mLastPercent = 0;
mNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(R.string.uploader_upload_in_progress_ticker),
System.currentTimeMillis());
mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
mDefaultNotificationContentView = mNotification.contentView;
mNotification.contentView = new RemoteViews(getApplicationContext().getPackageName(),
R.layout.progressbar_layout);
mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, false);
mNotification.contentView.setTextViewText(R.id.status_text,
String.format(getString(R.string.uploader_upload_in_progress_content), 0, upload.getFileName()));
mNotification.contentView.setImageViewResource(R.id.status_icon, DisplayUtils.getSeasonalIconId());
mNotificationBuilder =
NotificationBuilderWithProgressBar.newNotificationBuilderWithProgressBar(this);
mNotificationBuilder
.setOngoing(true)
.setSmallIcon(R.drawable.notification_icon)
.setTicker(getString(R.string.uploader_upload_in_progress_ticker))
.setContentTitle(getString(R.string.uploader_upload_in_progress_ticker))
.setProgress(100, 0, false)
.setContentText(
String.format(getString(R.string.uploader_upload_in_progress_content), 0, upload.getFileName()));
/// includes a pending intent in the notification showing the details view of the file
Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class);
showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, upload.getFile());
showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount());
showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
(int) System.currentTimeMillis(), showDetailsIntent, 0);
mNotificationBuilder.setContentIntent(PendingIntent.getActivity(
this, (int) System.currentTimeMillis(), showDetailsIntent, 0
));
mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotification);
mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build());
}
/**
@ -711,11 +709,11 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filePath) {
int percent = (int) (100.0 * ((double) totalTransferredSoFar) / ((double) totalToTransfer));
if (percent != mLastPercent) {
mNotification.contentView.setProgressBar(R.id.status_progress, 100, percent, false);
mNotificationBuilder.setProgress(100, percent, false);
String fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1);
String text = String.format(getString(R.string.uploader_upload_in_progress_content), percent, fileName);
mNotification.contentView.setTextViewText(R.id.status_text, text);
mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotification);
mNotificationBuilder.setContentText(text);
mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build());
}
mLastPercent = percent;
}
@ -735,12 +733,10 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
} else if (uploadResult.isSuccess()) {
// / success -> silent update of progress notification to success
// message
mNotification.flags ^= Notification.FLAG_ONGOING_EVENT; // remove
// the
// ongoing
// flag
mNotification.flags |= Notification.FLAG_AUTO_CANCEL;
mNotification.contentView = mDefaultNotificationContentView;
mNotificationBuilder
.setOngoing(false)
.setAutoCancel(true)
.setProgress(0, 0, false);
/// includes a pending intent in the notification showing the details view of the file
Intent showDetailsIntent = null;
@ -751,18 +747,20 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
}
showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, upload.getFile());
showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount());
showDetailsIntent.putExtra(FileActivity.EXTRA_FROM_NOTIFICATION, true);
showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
(int) System.currentTimeMillis(), showDetailsIntent, 0);
showDetailsIntent.putExtra(FileActivity.EXTRA_FROM_NOTIFICATION, true);;
mNotificationBuilder
.setContentIntent(PendingIntent.getActivity(
this, (int) System.currentTimeMillis(), showDetailsIntent, 0
))
.setTicker(getString(R.string.uploader_upload_succeeded_ticker))
.setContentTitle(getString(R.string.uploader_upload_succeeded_ticker))
.setContentText(
String.format(getString(R.string.uploader_upload_succeeded_content_single),
upload.getFileName())
);
mNotification.setLatestEventInfo(getApplicationContext(),
getString(R.string.uploader_upload_succeeded_ticker),
String.format(getString(R.string.uploader_upload_succeeded_content_single), upload.getFileName()),
mNotification.contentIntent);
mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotification); // NOT
// AN
mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build()); // NOT
// AN
DbHandler db = new DbHandler(this.getBaseContext());
db.removeIUPendingFile(mCurrentUpload.getOriginalStoragePath());
db.close();
@ -771,9 +769,12 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
// / fail -> explicit failure notification
mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
Notification finalNotification = new Notification(DisplayUtils.getSeasonalIconId(),
getString(R.string.uploader_upload_failed_ticker), System.currentTimeMillis());
finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationCompat.Builder errorBuilder = new NotificationCompat.Builder(this);
errorBuilder
.setSmallIcon(R.drawable.notification_icon)
.setTicker(getString(R.string.uploader_upload_failed_ticker))
.setContentTitle(getString(R.string.uploader_upload_failed_ticker))
.setAutoCancel(true);
String content = null;
boolean needsToUpdateCredentials = (uploadResult.getCode() == ResultCode.UNAUTHORIZED ||
@ -790,15 +791,13 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
finalNotification.contentIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
errorBuilder.setContentIntent(PendingIntent.getActivity(
this, (int) System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT
));
content = String.format(getString(R.string.uploader_upload_failed_content_single), upload.getFileName());
finalNotification.setLatestEventInfo(getApplicationContext(),
getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent);
mUploadClient = null; // grant that future retries on the same account will get the fresh credentials
} else {
// TODO put something smart in the contentIntent below
// finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
//}
if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL
|| uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) {
@ -823,10 +822,12 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
detailUploadIntent = new Intent(this, FailedUploadActivity.class);
detailUploadIntent.putExtra(FailedUploadActivity.MESSAGE, content);
}
finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
(int) System.currentTimeMillis(), detailUploadIntent, PendingIntent.FLAG_UPDATE_CURRENT
| PendingIntent.FLAG_ONE_SHOT);
errorBuilder
.setContentIntent(PendingIntent.getActivity(
this, (int) System.currentTimeMillis(), detailUploadIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT
))
.setContentText(content);
if (upload.isInstant()) {
DbHandler db = null;
try {
@ -847,10 +848,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
}
}
}
finalNotification.setLatestEventInfo(getApplicationContext(),
getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent);
mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification);
mNotificationManager.notify(R.string.uploader_upload_failed_ticker, errorBuilder.build());
}
}

View file

@ -30,7 +30,9 @@ import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.resources.shares.OCShare;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation;
import com.owncloud.android.lib.resources.shares.ShareType;
import com.owncloud.android.lib.resources.shares.CreateRemoteShareOperation;
import com.owncloud.android.lib.resources.files.FileUtils;
@ -40,6 +42,7 @@ import com.owncloud.android.utils.Log_OC;
public class CreateShareOperation extends SyncOperation {
private static final String TAG = CreateShareOperation.class.getSimpleName();
protected FileDataStorageManager mStorageManager;
@ -83,39 +86,24 @@ public class CreateShareOperation extends SyncOperation {
@Override
protected RemoteOperationResult run(OwnCloudClient client) {
CreateRemoteShareOperation operation = new CreateRemoteShareOperation(mPath, mShareType, mShareWith, mPublicUpload, mPassword, mPermissions);
RemoteOperationResult result = operation.execute(client);
RemoteOperation operation = null;
// Check if the share link already exists
operation = new GetRemoteSharesForFileOperation(mPath, false, false);
RemoteOperationResult result = ((GetRemoteSharesForFileOperation)operation).execute(client);
if (!result.isSuccess() || result.getData().size() <= 0) {
operation = new CreateRemoteShareOperation(mPath, mShareType, mShareWith, mPublicUpload, mPassword, mPermissions);
result = ((CreateRemoteShareOperation)operation).execute(client);
}
if (result.isSuccess()) {
if (result.getData().size() > 0) {
OCShare share = (OCShare) result.getData().get(0);
// Update DB with the response
share.setPath(mPath);
if (mPath.endsWith(FileUtils.PATH_SEPARATOR)) {
share.setIsFolder(true);
} else {
share.setIsFolder(false);
}
share.setPermissions(mPermissions);
getStorageManager().saveShare(share);
// Update OCFile with data from share: ShareByLink and publicLink
OCFile file = getStorageManager().getFileByPath(mPath);
if (file!=null) {
mSendIntent.putExtra(Intent.EXTRA_TEXT, share.getShareLink());
file.setPublicLink(share.getShareLink());
file.setShareByLink(true);
getStorageManager().saveFile(file);
Log_OC.d(TAG, "Public Link = " + file.getPublicLink());
}
}
updateData(share);
}
}
return result;
}
@ -123,5 +111,29 @@ public class CreateShareOperation extends SyncOperation {
public Intent getSendIntent() {
return mSendIntent;
}
private void updateData(OCShare share) {
// Update DB with the response
share.setPath(mPath);
if (mPath.endsWith(FileUtils.PATH_SEPARATOR)) {
share.setIsFolder(true);
} else {
share.setIsFolder(false);
}
share.setPermissions(mPermissions);
getStorageManager().saveShare(share);
// Update OCFile with data from share: ShareByLink and publicLink
OCFile file = getStorageManager().getFileByPath(mPath);
if (file!=null) {
mSendIntent.putExtra(Intent.EXTRA_TEXT, share.getShareLink());
file.setPublicLink(share.getShareLink());
file.setShareByLink(true);
getStorageManager().saveFile(file);
Log_OC.d(TAG, "Public Link = " + file.getPublicLink());
}
}
}

View file

@ -35,13 +35,10 @@ import com.owncloud.android.operations.SynchronizeFolderOperation;
import com.owncloud.android.operations.UpdateOCVersionOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.Log_OC;
import android.accounts.Account;
import android.accounts.AccountsException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.AbstractThreadedSyncAdapter;
@ -51,7 +48,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.os.Bundle;
//import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.app.NotificationCompat;
/**
* Implementation of {@link AbstractThreadedSyncAdapter} responsible for synchronizing
@ -385,8 +382,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
* Notifies the user about a failed synchronization through the status notification bar
*/
private void notifyFailedSynchronization() {
Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationCompat.Builder notificationBuilder = createNotificationBuilder();
notificationBuilder.setTicker(i18n(R.string.sync_fail_ticker));
boolean needsToUpdateCredentials = (mLastFailedResult != null &&
( mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED ||
( mLastFailedResult.isIdPRedirection() &&
@ -395,7 +392,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
)
);
// TODO put something smart in the contentIntent below for all the possible errors
notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
notificationBuilder.setContentTitle(i18n(R.string.sync_fail_ticker));
if (needsToUpdateCredentials) {
// let the user update credentials with one click
Intent updateAccountCredentials = new Intent(getContext(), AuthenticatorActivity.class);
@ -405,18 +402,17 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
notification.contentIntent = PendingIntent.getActivity(getContext(), (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
notification.setLatestEventInfo(getContext().getApplicationContext(),
getContext().getString(R.string.sync_fail_ticker),
String.format(getContext().getString(R.string.sync_fail_content_unauthorized), getAccount().name),
notification.contentIntent);
notificationBuilder
.setContentIntent(PendingIntent.getActivity(
getContext(), (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT
))
.setContentText(i18n(R.string.sync_fail_content_unauthorized, getAccount().name));
} else {
notification.setLatestEventInfo(getContext().getApplicationContext(),
getContext().getString(R.string.sync_fail_ticker),
String.format(getContext().getString(R.string.sync_fail_content), getAccount().name),
notification.contentIntent);
notificationBuilder
.setContentText(i18n(R.string.sync_fail_content, getAccount().name));
}
((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_ticker, notification);
showNotification(R.string.sync_fail_ticker, notificationBuilder);
}
@ -427,26 +423,31 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
*/
private void notifyFailsInFavourites() {
if (mFailedResultsCounter > 0) {
Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_fail_in_favourites_ticker), System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationCompat.Builder notificationBuilder = createNotificationBuilder();
notificationBuilder.setTicker(i18n(R.string.sync_fail_in_favourites_ticker));
// TODO put something smart in the contentIntent below
notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
notification.setLatestEventInfo(getContext().getApplicationContext(),
getContext().getString(R.string.sync_fail_in_favourites_ticker),
String.format(getContext().getString(R.string.sync_fail_in_favourites_content), mFailedResultsCounter + mConflictsFound, mConflictsFound),
notification.contentIntent);
((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_in_favourites_ticker, notification);
notificationBuilder
.setContentIntent(PendingIntent.getActivity(
getContext(), (int) System.currentTimeMillis(), new Intent(), 0
))
.setContentTitle(i18n(R.string.sync_fail_in_favourites_ticker))
.setContentText(i18n(R.string.sync_fail_in_favourites_content, mFailedResultsCounter + mConflictsFound, mConflictsFound));
showNotification(R.string.sync_fail_in_favourites_ticker, notificationBuilder);
} else {
Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_conflicts_in_favourites_ticker), System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationCompat.Builder notificationBuilder = createNotificationBuilder();
notificationBuilder.setTicker(i18n(R.string.sync_conflicts_in_favourites_ticker));
// TODO put something smart in the contentIntent below
notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
notification.setLatestEventInfo(getContext().getApplicationContext(),
getContext().getString(R.string.sync_conflicts_in_favourites_ticker),
String.format(getContext().getString(R.string.sync_conflicts_in_favourites_content), mConflictsFound),
notification.contentIntent);
((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_conflicts_in_favourites_ticker, notification);
notificationBuilder
.setContentIntent(PendingIntent.getActivity(
getContext(), (int) System.currentTimeMillis(), new Intent(), 0
))
.setContentTitle(i18n(R.string.sync_conflicts_in_favourites_ticker))
.setContentText(i18n(R.string.sync_conflicts_in_favourites_ticker, mConflictsFound));
showNotification(R.string.sync_conflicts_in_favourites_ticker, notificationBuilder);
}
}
@ -460,9 +461,9 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
* We won't consider a synchronization as failed when foreign files can not be copied to the ownCloud local directory.
*/
private void notifyForgottenLocalFiles() {
Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_foreign_files_forgotten_ticker), System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationCompat.Builder notificationBuilder = createNotificationBuilder();
notificationBuilder.setTicker(i18n(R.string.sync_foreign_files_forgotten_ticker));
/// includes a pending intent in the notification showing a more detailed explanation
Intent explanationIntent = new Intent(getContext(), ErrorsWhileCopyingHandlerActivity.class);
explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_ACCOUNT, getAccount());
@ -474,14 +475,45 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_REMOTE_PATHS, remotePaths);
explanationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), explanationIntent, 0);
notification.setLatestEventInfo(getContext().getApplicationContext(),
getContext().getString(R.string.sync_foreign_files_forgotten_ticker),
String.format(getContext().getString(R.string.sync_foreign_files_forgotten_content), mForgottenLocalFiles.size(), getContext().getString(R.string.app_name)),
notification.contentIntent);
((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_foreign_files_forgotten_ticker, notification);
notificationBuilder
.setContentIntent(PendingIntent.getActivity(
getContext(), (int) System.currentTimeMillis(), explanationIntent, 0
))
.setContentTitle(i18n(R.string.sync_foreign_files_forgotten_ticker))
.setContentText(i18n(R.string.sync_foreign_files_forgotten_content, mForgottenLocalFiles.size(), i18n(R.string.app_name)));
showNotification(R.string.sync_foreign_files_forgotten_ticker, notificationBuilder);
}
/**
* Creates a notification builder with some commonly used settings
*
* @return
*/
private NotificationCompat.Builder createNotificationBuilder() {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getContext());
notificationBuilder.setSmallIcon(R.drawable.notification_icon).setAutoCancel(true);
return notificationBuilder;
}
/**
* Builds and shows the notification
*
* @param id
* @param builder
*/
private void showNotification(int id, NotificationCompat.Builder builder) {
((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE))
.notify(id, builder.build());
}
/**
* Shorthand translation
*
* @param key
* @param args
* @return
*/
private String i18n(int key, Object... args) {
return getContext().getString(key, args);
}
}

View file

@ -0,0 +1,131 @@
/* ownCloud Android client application
* Copyright (C) 2014 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.utils;
import com.owncloud.android.R;
import android.app.Notification;
import android.content.Context;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.widget.RemoteViews;
/**
* Extends the support class {@link NotificationCompat.Builder} to grant that
* a progress bar is available in every Android version, because
* {@link NotificationCompat.Builder#setProgress(int, int, boolean)} has no
* real effect for Android < 4.0
*
* @author David A. Velasco
*/
public class NotificationBuilderWithProgressBar extends NotificationCompat.Builder {
/**
* Custom view to replace the original layout of the notifications
*/
private RemoteViews mContentView = null;
/**
* Fatory method.
*
* Instances of this class will be only returned in Android versions needing it.
*
* @param context Context that will use the builder to create notifications
* @return An instance of this class, or of the regular
* {@link NotificationCompat.Builder}, when it is good enough.
*/
public static NotificationCompat.Builder newNotificationBuilderWithProgressBar(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return new NotificationBuilderWithProgressBar(context);
} else {
return new NotificationCompat.Builder(context);
}
}
/**
* Constructor.
*
* @param context Context that will use the builder to create notifications.
*/
private NotificationBuilderWithProgressBar(Context context) {
super(context);
mContentView = new RemoteViews(context.getPackageName(), R.layout.notification_with_progress_bar);
setContent(mContentView);
}
/**
* {@inheritDoc}
*/
@Override
public NotificationCompat.Builder setProgress(int max, int progress, boolean indeterminate) {
mContentView.setProgressBar(R.id.progress, max, progress, indeterminate);
if (max > 0) {
mContentView.setViewVisibility(R.id.progressHolder, View.VISIBLE);
} else {
mContentView.setViewVisibility(R.id.progressHolder, View.GONE);
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public NotificationCompat.Builder setSmallIcon(int icon) {
super.setSmallIcon(icon); // necessary
mContentView.setImageViewResource(R.id.icon, icon);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public NotificationCompat.Builder setContentTitle(CharSequence title) {
super.setContentTitle(title);
mContentView.setTextViewText(R.id.title, title);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public NotificationCompat.Builder setContentText(CharSequence text) {
super.setContentText(text);
mContentView.setTextViewText(R.id.text, text);
if (text != null && text.length() > 0) {
mContentView.setViewVisibility(R.id.text, View.VISIBLE);
} else {
mContentView.setViewVisibility(R.id.text, View.GONE);
}
return this;
}
@Override
public Notification build() {
Notification result = super.build();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
// super.build() in Android 2.x totally ruins whatever was made #setContent
result.contentView = mContentView;
}
return result;
}
}