4a0f4f8eb8e880760e38ac22e50217935a6e9829
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / activity / FileActivity.java
1 /* ownCloud Android client application
2 * Copyright (C) 2011 Bartek Przybylski
3 * Copyright (C) 2012-2013 ownCloud Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2,
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 package com.owncloud.android.ui.activity;
20
21 import android.accounts.Account;
22 import android.accounts.AccountManager;
23 import android.accounts.AccountManagerCallback;
24 import android.accounts.AccountManagerFuture;
25 import android.accounts.OperationCanceledException;
26 import android.content.Intent;
27 import android.net.Uri;
28 import android.os.Bundle;
29 import android.webkit.MimeTypeMap;
30
31 import com.actionbarsherlock.app.SherlockFragmentActivity;
32 import com.owncloud.android.AccountUtils;
33 import com.owncloud.android.Log_OC;
34 import com.owncloud.android.authentication.AccountAuthenticator;
35 import com.owncloud.android.datamodel.OCFile;
36 import com.owncloud.android.files.FileHandler;
37
38 import eu.alefzero.webdav.WebdavUtils;
39
40 /**
41 * Activity with common behaviour for activities handling {@link OCFile}s in ownCloud {@link Account}s .
42 *
43 * @author David A. Velasco
44 */
45 public abstract class FileActivity extends SherlockFragmentActivity implements FileHandler {
46
47 public static final String EXTRA_FILE = "com.owncloud.android.ui.activity.FILE";
48 public static final String EXTRA_ACCOUNT = "com.owncloud.android.ui.activity.ACCOUNT";
49
50 public static final String TAG = FileActivity.class.getSimpleName();
51
52
53 /** OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located. */
54 private Account mAccount;
55
56 /** Main {@link OCFile} handled by the activity.*/
57 private OCFile mFile;
58
59 /** Flag to signal that the activity will is finishing to enforce the creation of an ownCloud {@link Account} */
60 private boolean mRedirectingToSetupAccount = false;
61
62 private FileHandlerImpl mFileHandler;
63
64
65 @Override
66 protected void onCreate(Bundle savedInstanceState) {
67 super.onCreate(savedInstanceState);
68
69 /// Load of saved instance state: keep this always before initDataFromCurrentAccount()
70 if(savedInstanceState != null) {
71 mFile = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE);
72 mAccount = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT);
73 } else {
74 mAccount = getIntent().getParcelableExtra(FileActivity.EXTRA_ACCOUNT);
75 mFile = getIntent().getParcelableExtra(FileActivity.EXTRA_FILE);
76 }
77
78 if (mAccount != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), mAccount.name)) {
79 onAccountChanged();
80 }
81
82 mFileHandler = new FileHandlerImpl();
83 }
84
85
86 /**
87 * Validate the ownCloud {@link Account} associated to the Activity any time it is
88 * started, and if not valid tries to move to a different Account.
89 */
90 @Override
91 protected void onStart() {
92 Log_OC.e(TAG, "onStart en FileActivity");
93 super.onStart();
94 /// Validate account, and try to fix if wrong
95 if (mAccount == null || !AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), mAccount.name)) {
96 if (!AccountUtils.accountsAreSetup(getApplicationContext())) {
97 /// no account available: force account creation
98 mAccount = null;
99 createFirstAccount();
100 mRedirectingToSetupAccount = true;
101
102 } else {
103 /// get 'last current account' as default account
104 mAccount = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext());
105 onAccountChanged();
106 }
107 }
108 }
109
110
111 /**
112 * Launches the account creation activity. To use when no ownCloud account is available
113 */
114 private void createFirstAccount() {
115 AccountManager am = AccountManager.get(getApplicationContext());
116 am.addAccount(AccountAuthenticator.ACCOUNT_TYPE,
117 AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD,
118 null,
119 null,
120 this,
121 new AccountCreationCallback(),
122 null);
123 }
124
125
126 /**
127 * {@inheritDoc}
128 */
129 @Override
130 protected void onSaveInstanceState(Bundle outState) {
131 super.onSaveInstanceState(outState);
132 outState.putParcelable(FileActivity.EXTRA_FILE, mFile);
133 outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount);
134 }
135
136
137 /**
138 * Getter for the main {@link OCFile} handled by the activity.
139 *
140 * @return Main {@link OCFile} handled by the activity.
141 */
142 public OCFile getFile() {
143 return mFile;
144 }
145
146
147 /**
148 * Setter for the main {@link OCFile} handled by the activity.
149 *
150 * @param file Main {@link OCFile} to be handled by the activity.
151 */
152 public void setFile(OCFile file) {
153 mFile = file;
154 }
155
156
157 /**
158 * Getter for the ownCloud {@link Account} where the main {@link OCFile} handled by the activity is located.
159 *
160 * @return OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located.
161 */
162 public Account getAccount() {
163 return mAccount;
164 }
165
166
167 /**
168 * @return 'True' when the Activity is finishing to enforce the setup of a new account.
169 */
170 protected boolean isRedirectingToSetupAccount() {
171 return mRedirectingToSetupAccount;
172 }
173
174
175 /**
176 * Helper class handling a callback from the {@link AccountManager} after the creation of
177 * a new ownCloud {@link Account} finished, successfully or not.
178 *
179 * At this moment, only called after the creation of the first account.
180 *
181 * @author David A. Velasco
182 */
183 public class AccountCreationCallback implements AccountManagerCallback<Bundle> {
184
185 @Override
186 public void run(AccountManagerFuture<Bundle> future) {
187 FileActivity.this.mRedirectingToSetupAccount = false;
188 if (future != null) {
189 try {
190 Bundle result;
191 result = future.getResult();
192 String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
193 String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
194 if (AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), name)) {
195 FileActivity.this.mAccount = new Account(name, type);
196 FileActivity.this.onAccountChanged();
197 }
198 } catch (OperationCanceledException e) {
199 Log_OC.e(TAG, "Account creation canceled");
200
201 } catch (Exception e) {
202 Log_OC.e(TAG, "Account creation finished in exception: ", e);
203 }
204
205 } else {
206 Log_OC.e(TAG, "Account creation callback with null bundle");
207 }
208 if (mAccount == null) {
209 finish();
210 }
211 }
212
213 }
214
215
216 public void openFile(OCFile file) {
217 mFileHandler.openFile(file);
218 }
219
220
221 /**
222 * Called when the ownCloud {@link Account} associated to the Activity was just updated.
223 *
224 * Child classes must grant that state depending on the {@link Account} is updated.
225 */
226 protected abstract void onAccountChanged();
227
228
229 public class FileHandlerImpl implements FileHandler {
230
231 public void openFile(OCFile file) {
232 if (file != null) {
233 String storagePath = file.getStoragePath();
234 String encodedStoragePath = WebdavUtils.encodePath(storagePath);
235
236 Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW);
237 intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype());
238 intentForSavedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
239
240 Intent intentForGuessedMimeType = null;
241 if (storagePath.lastIndexOf('.') >= 0) {
242 String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
243 if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) {
244 intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW);
245 intentForGuessedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), guessedMimeType);
246 intentForGuessedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
247 }
248 }
249
250 Intent chooserIntent = null;
251 if (intentForGuessedMimeType != null) {
252 chooserIntent = Intent.createChooser(intentForGuessedMimeType, null);
253 } else {
254 chooserIntent = Intent.createChooser(intentForSavedMimeType, null);
255 }
256
257 startActivity(chooserIntent);
258
259 } else {
260 Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
261 }
262 }
263 }
264 }