1 package eu
.alefzero
.owncloud
.files
.services
;
4 import java
.net
.URLDecoder
;
6 import eu
.alefzero
.owncloud
.AccountUtils
;
7 import eu
.alefzero
.owncloud
.R
;
8 import eu
.alefzero
.owncloud
.authenticator
.AccountAuthenticator
;
9 import eu
.alefzero
.owncloud
.datamodel
.FileDataStorageManager
;
10 import eu
.alefzero
.owncloud
.datamodel
.OCFile
;
11 import eu
.alefzero
.owncloud
.files
.interfaces
.OnDatatransferProgressListener
;
12 import eu
.alefzero
.owncloud
.utils
.OwnCloudVersion
;
13 import eu
.alefzero
.webdav
.OnUploadProgressListener
;
14 import eu
.alefzero
.webdav
.WebdavClient
;
15 import android
.accounts
.Account
;
16 import android
.accounts
.AccountManager
;
17 import android
.app
.Notification
;
18 import android
.app
.NotificationManager
;
19 import android
.app
.PendingIntent
;
20 import android
.app
.Service
;
21 import android
.content
.Intent
;
22 import android
.net
.Uri
;
23 import android
.os
.Handler
;
24 import android
.os
.HandlerThread
;
25 import android
.os
.IBinder
;
26 import android
.os
.Looper
;
27 import android
.os
.Message
;
28 import android
.os
.Process
;
29 import android
.util
.Log
;
30 import android
.webkit
.MimeTypeMap
;
31 import android
.widget
.RemoteViews
;
32 import android
.widget
.Toast
;
34 public class FileUploader
extends Service
implements OnDatatransferProgressListener
{
36 public static final String KEY_LOCAL_FILE
= "LOCAL_FILE";
37 public static final String KEY_REMOTE_FILE
= "REMOTE_FILE";
38 public static final String KEY_ACCOUNT
= "ACCOUNT";
39 public static final String KEY_UPLOAD_TYPE
= "UPLOAD_TYPE";
41 public static final int UPLOAD_SINGLE_FILE
= 0;
42 public static final int UPLOAD_MULTIPLE_FILES
= 1;
44 private static final String TAG
= "FileUploader";
45 private NotificationManager mNotificationManager
;
46 private Looper mServiceLooper
;
47 private ServiceHandler mServiceHandler
;
48 private AccountManager mAccountManager
;
49 private Account mAccount
;
50 private String
[] mLocalPaths
, mRemotePaths
;
51 private boolean mResult
;
52 private int mUploadType
;
53 private Notification mNotification
;
54 private int mTotalDataToSend
, mSendData
;
55 private int mCurrentIndexUpload
, mPreviousPercent
;
58 public IBinder
onBind(Intent arg0
) {
62 private final class ServiceHandler
extends Handler
{
63 public ServiceHandler(Looper looper
) {
68 public void handleMessage(Message msg
) {
75 public void onCreate() {
77 mNotificationManager
= (NotificationManager
) getSystemService(NOTIFICATION_SERVICE
);
78 HandlerThread thread
= new HandlerThread("FileUploaderThread",
79 Process
.THREAD_PRIORITY_BACKGROUND
);
81 mServiceLooper
= thread
.getLooper();
82 mServiceHandler
= new ServiceHandler(mServiceLooper
);
83 mAccountManager
= AccountManager
.get(this);
87 public int onStartCommand(Intent intent
, int flags
, int startId
) {
88 if (!intent
.hasExtra(KEY_ACCOUNT
) && !intent
.hasExtra(KEY_UPLOAD_TYPE
)) {
89 Log
.e(TAG
, "Not enought data in intent provided");
90 return Service
.START_NOT_STICKY
;
92 mAccount
= intent
.getParcelableExtra(KEY_ACCOUNT
);
93 mUploadType
= intent
.getIntExtra(KEY_UPLOAD_TYPE
, -1);
94 if (mUploadType
== -1) {
95 Log
.e(TAG
, "Incorrect upload type provided");
96 return Service
.START_NOT_STICKY
;
98 if (mUploadType
== UPLOAD_SINGLE_FILE
) {
99 mLocalPaths
= new String
[] { intent
.getStringExtra(KEY_LOCAL_FILE
) };
100 mRemotePaths
= new String
[] { intent
101 .getStringExtra(KEY_REMOTE_FILE
) };
102 } else { // mUploadType == UPLOAD_MULTIPLE_FILES
103 mLocalPaths
= intent
.getStringArrayExtra(KEY_LOCAL_FILE
);
104 mRemotePaths
= intent
.getStringArrayExtra(KEY_REMOTE_FILE
);
107 for (int i
= 0; i
< mRemotePaths
.length
; ++i
)
108 mRemotePaths
[i
] = mRemotePaths
[i
].replace(' ', '+');
110 if (mLocalPaths
.length
!= mRemotePaths
.length
) {
111 Log
.e(TAG
, "Remote paths and local paths are not equal!");
112 return Service
.START_NOT_STICKY
;
115 Message msg
= mServiceHandler
.obtainMessage();
117 mServiceHandler
.sendMessage(msg
);
119 return Service
.START_NOT_STICKY
;
124 Toast
.makeText(this, "Upload successfull", Toast
.LENGTH_SHORT
)
127 Toast
.makeText(this, "No i kupa", Toast
.LENGTH_SHORT
).show();
131 public void uploadFile() {
132 String baseUrl
= mAccountManager
.getUserData(mAccount
,
133 AccountAuthenticator
.KEY_OC_BASE_URL
), ocVerStr
= mAccountManager
134 .getUserData(mAccount
, AccountAuthenticator
.KEY_OC_VERSION
);
135 OwnCloudVersion ocVer
= new OwnCloudVersion(ocVerStr
);
136 String webdav_path
= AccountUtils
.getWebdavPath(ocVer
);
137 Uri ocUri
= Uri
.parse(baseUrl
+ webdav_path
);
138 String username
= mAccount
.name
.substring(0,
139 mAccount
.name
.lastIndexOf('@'));
140 String password
= mAccountManager
.getPassword(mAccount
);
141 FileDataStorageManager storageManager
= new FileDataStorageManager(mAccount
, getContentResolver());
143 mTotalDataToSend
= mSendData
= mPreviousPercent
= 0;
145 mNotification
= new Notification(
146 eu
.alefzero
.owncloud
.R
.drawable
.icon
, "Uploading...",
147 System
.currentTimeMillis());
148 mNotification
.flags
|= Notification
.FLAG_ONGOING_EVENT
;
149 mNotification
.contentView
= new RemoteViews(getApplicationContext().getPackageName(), R
.layout
.progressbar_layout
);
150 mNotification
.contentView
.setProgressBar(R
.id
.status_progress
, 100, 0, false
);
151 mNotification
.contentView
.setImageViewResource(R
.id
.status_icon
, R
.drawable
.icon
);
152 // dvelasco ; contentIntent MUST be assigned to avoid app crashes in versions previous to Android 4.x ;
153 // BUT an empty Intent is not a very elegant solution; something smart should happen when a user 'clicks' on an upload in the notification bar
154 mNotification
.contentIntent
= PendingIntent
.getActivity(getApplicationContext(), 0, new Intent(), PendingIntent
.FLAG_UPDATE_CURRENT
);
156 mNotificationManager
.notify(42, mNotification
);
158 WebdavClient wc
= new WebdavClient(ocUri
);
159 wc
.allowSelfsignedCertificates();
160 wc
.setDataTransferProgressListener(this);
161 wc
.setCredentials(username
, password
);
163 for (int i
= 0; i
< mLocalPaths
.length
; ++i
) {
164 File f
= new File(mLocalPaths
[i
]);
165 mTotalDataToSend
+= f
.length();
168 Log
.d(TAG
, "Will upload " + mTotalDataToSend
+ " bytes, with " + mLocalPaths
.length
+ " files");
170 for (int i
= 0; i
< mLocalPaths
.length
; ++i
) {
171 String mimeType
= MimeTypeMap
.getSingleton()
172 .getMimeTypeFromExtension(
173 mLocalPaths
[i
].substring(mLocalPaths
[i
]
174 .lastIndexOf('.') + 1));
176 mCurrentIndexUpload
= i
;
177 if (wc
.putFile(mLocalPaths
[i
], mRemotePaths
[i
], mimeType
)) {
179 String decRemotePath
= URLDecoder
.decode(mRemotePaths
[i
]);
180 OCFile new_file
= new OCFile(decRemotePath
); // FyleSyncAdapter and this MUST use the same encoding when creating a new OCFile
181 new_file
.setMimetype(mimeType
);
182 new_file
.setFileLength(new File(mLocalPaths
[i
]).length());
183 new_file
.setModificationTimestamp(System
.currentTimeMillis());
184 new_file
.setLastSyncDate(0);
185 new_file
.setStoragePath(mLocalPaths
[i
]);
186 File f
= new File(URLDecoder
.decode(mRemotePaths
[i
]));
187 new_file
.setParentId(storageManager
.getFileByPath(f
.getParent().endsWith("/")?f
.getParent():f
.getParent()+"/").getFileId());
188 storageManager
.saveFile(new_file
);
191 // notification.contentView.setProgressBar(R.id.status_progress,
192 // mLocalPaths.length-1, mLocalPaths.length-1, false);
193 mNotificationManager
.cancel(42);
198 public void transferProgress(long progressRate
) {
199 mSendData
+= progressRate
;
200 int percent
= (int)(100*((double)mSendData
)/((double)mTotalDataToSend
));
201 if (percent
!= mPreviousPercent
) {
202 String text
= String
.format("%d%% Uploading %s file", percent
, new File(mLocalPaths
[mCurrentIndexUpload
]).getName());
203 mNotification
.contentView
.setProgressBar(R
.id
.status_progress
, 100, percent
, false
);
204 mNotification
.contentView
.setTextViewText(R
.id
.status_text
, text
);
205 mNotificationManager
.notify(42, mNotification
);
207 mPreviousPercent
= percent
;