FileDownloader.java 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package eu.alefzero.owncloud.files.services;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import android.accounts.Account;
  5. import android.accounts.AccountManager;
  6. import android.app.Notification;
  7. import android.app.NotificationManager;
  8. import android.app.PendingIntent;
  9. import android.app.Service;
  10. import android.content.ContentValues;
  11. import android.content.Intent;
  12. import android.os.Environment;
  13. import android.os.Handler;
  14. import android.os.HandlerThread;
  15. import android.os.IBinder;
  16. import android.os.Looper;
  17. import android.os.Message;
  18. import android.os.Process;
  19. import android.util.Log;
  20. import android.widget.RemoteViews;
  21. import android.widget.Toast;
  22. import eu.alefzero.owncloud.R;
  23. import eu.alefzero.owncloud.authenticator.AccountAuthenticator;
  24. import eu.alefzero.owncloud.db.ProviderMeta.ProviderTableMeta;
  25. import eu.alefzero.owncloud.files.interfaces.OnDatatransferProgressListener;
  26. import eu.alefzero.owncloud.syncadapter.FileSyncService;
  27. import eu.alefzero.webdav.WebdavClient;
  28. public class FileDownloader extends Service implements OnDatatransferProgressListener {
  29. public static final String DOWNLOAD_FINISH_MESSAGE = "DOWNLOAD_FINISH";
  30. public static final String EXTRA_DOWNLOAD_RESULT = "RESULT";
  31. public static final String EXTRA_ACCOUNT = "ACCOUNT";
  32. public static final String EXTRA_FILE_PATH = "FILE_PATH";
  33. public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
  34. public static final String EXTRA_FILE_SIZE = "FILE_SIZE";
  35. public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
  36. private static final String TAG = "FileDownloader";
  37. private NotificationManager mNotificationMngr;
  38. private Looper mServiceLooper;
  39. private ServiceHandler mServiceHandler;
  40. private Account mAccount;
  41. private String mFilePath;
  42. private String mRemotePath;
  43. private int mLastPercent;
  44. private long mTotalDownloadSize;
  45. private long mCurrentDownlodSize;
  46. private Notification mNotification;
  47. private final class ServiceHandler extends Handler {
  48. public ServiceHandler(Looper looper) {
  49. super(looper);
  50. }
  51. @Override
  52. public void handleMessage(Message msg) {
  53. downloadFile();
  54. stopSelf(msg.arg1);
  55. }
  56. }
  57. @Override
  58. public void onCreate() {
  59. super.onCreate();
  60. mNotificationMngr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
  61. HandlerThread thread = new HandlerThread("FileDownladerThread",
  62. Process.THREAD_PRIORITY_BACKGROUND);
  63. thread.start();
  64. mServiceLooper = thread.getLooper();
  65. mServiceHandler = new ServiceHandler(mServiceLooper);
  66. }
  67. @Override
  68. public IBinder onBind(Intent arg0) {
  69. return null;
  70. }
  71. @Override
  72. public int onStartCommand(Intent intent, int flags, int startId) {
  73. if (!intent.hasExtra(EXTRA_ACCOUNT)
  74. && !intent.hasExtra(EXTRA_FILE_PATH)) {
  75. Log.e(TAG, "Not enough information provided in intent");
  76. return START_STICKY;
  77. }
  78. mAccount = intent.getParcelableExtra(EXTRA_ACCOUNT);
  79. mFilePath = intent.getStringExtra(EXTRA_FILE_PATH);
  80. mRemotePath = intent.getStringExtra(EXTRA_REMOTE_PATH);
  81. Message msg = mServiceHandler.obtainMessage();
  82. msg.arg1 = startId;
  83. mServiceHandler.sendMessage(msg);
  84. mCurrentDownlodSize = mLastPercent = 0;
  85. mTotalDownloadSize = intent.getLongExtra(EXTRA_FILE_SIZE, -1);
  86. return START_NOT_STICKY;
  87. }
  88. void downloadFile() {
  89. AccountManager am = (AccountManager) getSystemService(ACCOUNT_SERVICE);
  90. WebdavClient wdc = new WebdavClient(mAccount, getApplicationContext());
  91. String username = mAccount.name.split("@")[0];
  92. String password = "";
  93. try {
  94. password = am.blockingGetAuthToken(mAccount,
  95. AccountAuthenticator.AUTH_TOKEN_TYPE, true);
  96. } catch (Exception e) {
  97. e.printStackTrace();
  98. return;
  99. }
  100. wdc.setCredentials(username, password);
  101. wdc.allowSelfsignedCertificates();
  102. wdc.setDataTransferProgressListener(this);
  103. mNotification = new Notification(R.drawable.icon, "Downloading file", System.currentTimeMillis());
  104. mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
  105. mNotification.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.progressbar_layout);
  106. mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, mTotalDownloadSize == -1);
  107. mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon);
  108. // dvelasco ; contentIntent MUST be assigned to avoid app crashes in versions previous to Android 4.x ;
  109. // BUT an empty Intent is not a very elegant solution; something smart should happen when a user 'clicks' on a download in the notification bar
  110. mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT);
  111. mNotificationMngr.notify(1, mNotification);
  112. File sdCard = Environment.getExternalStorageDirectory();
  113. File file = new File(sdCard.getAbsolutePath() + "/owncloud/" + mAccount.name + mFilePath);
  114. file.getParentFile().mkdirs();
  115. boolean download_result = false;
  116. if (wdc.downloadFile(mRemotePath, file)) {
  117. ContentValues cv = new ContentValues();
  118. cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getAbsolutePath());
  119. getContentResolver().update(
  120. ProviderTableMeta.CONTENT_URI,
  121. cv,
  122. ProviderTableMeta.FILE_NAME + "=? AND "
  123. + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
  124. new String[] {
  125. mFilePath.substring(mFilePath.lastIndexOf('/') + 1),
  126. mAccount.name });
  127. download_result = true;
  128. }
  129. mNotificationMngr.cancel(1);
  130. Intent end = new Intent(DOWNLOAD_FINISH_MESSAGE);
  131. end.putExtra(EXTRA_REMOTE_PATH, mRemotePath);
  132. end.putExtra(EXTRA_FILE_PATH, file.getAbsolutePath());
  133. end.putExtra(EXTRA_DOWNLOAD_RESULT, download_result);
  134. end.putExtra(ACCOUNT_NAME, mAccount.name);
  135. sendBroadcast(end);
  136. if (download_result) {
  137. Toast.makeText(this, R.string.downloader_download_succeed , Toast.LENGTH_SHORT).show();
  138. } else {
  139. Toast.makeText(this, R.string.downloader_download_failed , Toast.LENGTH_SHORT).show();
  140. }
  141. }
  142. @Override
  143. public void transferProgress(long progressRate) {
  144. mCurrentDownlodSize += progressRate;
  145. int percent = (int)(100.0*((double)mCurrentDownlodSize)/((double)mTotalDownloadSize));
  146. if (percent != mLastPercent) {
  147. mNotification.contentView.setProgressBar(R.id.status_progress, 100, (int)(100*mCurrentDownlodSize/mTotalDownloadSize), mTotalDownloadSize == -1);
  148. mNotification.contentView.setTextViewText(R.id.status_text, percent+"%");
  149. mNotificationMngr.notify(1, mNotification);
  150. }
  151. mLastPercent = percent;
  152. }
  153. }