1 /* ownCloud Android client application
2 * Copyright (C) 2011 Bartek Przybylski
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
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.
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/>.
19 package eu
.alefzero
.owncloud
;
22 import java
.io
.FileInputStream
;
23 import java
.io
.FileNotFoundException
;
24 import java
.io
.IOException
;
25 import java
.util
.LinkedList
;
26 import java
.util
.Stack
;
28 import android
.accounts
.Account
;
29 import android
.accounts
.AccountManager
;
30 import android
.app
.AlertDialog
;
31 import android
.app
.Dialog
;
32 import android
.app
.ListActivity
;
33 import android
.content
.DialogInterface
;
34 import android
.content
.Intent
;
35 import android
.content
.DialogInterface
.OnCancelListener
;
36 import android
.content
.res
.Configuration
;
37 import android
.database
.Cursor
;
38 import android
.graphics
.Bitmap
;
39 import android
.graphics
.BitmapFactory
;
40 import android
.graphics
.Matrix
;
41 import android
.net
.Uri
;
42 import android
.os
.Bundle
;
43 import android
.os
.Environment
;
44 import android
.text
.TextUtils
;
45 import android
.util
.Log
;
46 import android
.view
.Menu
;
47 import android
.view
.MenuInflater
;
48 import android
.view
.MenuItem
;
49 import android
.view
.View
;
50 import android
.view
.Window
;
51 import android
.widget
.ImageView
;
52 import android
.widget
.ListView
;
53 import android
.widget
.TextView
;
54 import eu
.alefzero
.owncloud
.authenticator
.AccountAuthenticator
;
55 import eu
.alefzero
.owncloud
.db
.ProviderMeta
.ProviderTableMeta
;
57 public class OwnCloudMainScreen
extends ListActivity
{
58 private DbHandler mDBHandler
;
59 private Stack
<String
> mParents
;
60 private LinkedList
<String
> mPath
;
61 private Account mAccount
;
62 private Cursor mCursor
;
63 private boolean mIsDisplayingFile
;
65 private static final int DIALOG_CHOOSE_ACCOUNT
= 0;
67 @SuppressWarnings("unchecked")
69 public void onCreate(Bundle savedInstanceState
) {
70 super.onCreate(savedInstanceState
);
72 if (savedInstanceState
!= null
) {
73 mParents
= (Stack
<String
>)savedInstanceState
.getSerializable("parentsStack");
74 mIsDisplayingFile
= savedInstanceState
.getBoolean("isDisplayingFile");
75 mPath
= (LinkedList
<String
>)savedInstanceState
.getSerializable("path");
77 mParents
= new Stack
<String
>();
78 mPath
= new LinkedList
<String
>();
79 mIsDisplayingFile
= false
;
82 mDBHandler
= new DbHandler(getBaseContext());
83 requestWindowFeature(Window
.FEATURE_NO_TITLE
);
84 setContentView(R
.layout
.main
);
86 AccountManager accMan
= AccountManager
.get(this);
87 Account
[] accounts
= accMan
.getAccountsByType(AccountAuthenticator
.ACCOUNT_TYPE
);
89 if (accounts
.length
== 0) {
90 // using string value since in API7 this constatn is not defined
91 // in API7 < this constatant is defined in Settings.ADD_ACCOUNT_SETTINGS
92 // and Settings.EXTRA_AUTHORITIES
93 Intent intent
= new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
94 intent
.putExtra("authorities", new String
[] {AccountAuthenticator
.AUTH_TOKEN_TYPE
});
95 startActivity(intent
);
96 } else if (accounts
.length
> 1) {
97 showDialog(DIALOG_CHOOSE_ACCOUNT
);
99 mAccount
= accounts
[0];
105 public boolean onOptionsItemSelected(MenuItem item
) {
106 switch (item
.getItemId()) {
107 case R
.id
.settingsItem
:
108 Intent i
= new Intent(this, Preferences
.class);
116 protected Dialog
onCreateDialog(int id
) {
118 case DIALOG_CHOOSE_ACCOUNT
:
119 return createChooseAccountDialog();
121 throw new IllegalArgumentException("Unknown dialog id: " + id
);
126 public boolean onCreateOptionsMenu(Menu menu
) {
127 MenuInflater inflater
= getMenuInflater();
128 inflater
.inflate(R
.menu
.menu
, menu
);
133 protected void onDestroy() {
138 private Dialog
createChooseAccountDialog() {
139 final AccountManager accMan
= AccountManager
.get(this);
140 CharSequence
[] items
= new CharSequence
[accMan
.getAccountsByType(AccountAuthenticator
.ACCOUNT_TYPE
).length
];
142 for (Account a
: accMan
.getAccountsByType(AccountAuthenticator
.ACCOUNT_TYPE
)) {
146 AlertDialog
.Builder builder
= new AlertDialog
.Builder(this);
147 builder
.setTitle(R
.string
.common_choose_account
);
148 builder
.setCancelable(true
);
149 builder
.setItems(items
, new DialogInterface
.OnClickListener() {
150 public void onClick(DialogInterface dialog
, int item
) {
151 mAccount
= accMan
.getAccountsByType(AccountAuthenticator
.ACCOUNT_TYPE
)[item
];
156 builder
.setOnCancelListener(new OnCancelListener() {
157 public void onCancel(DialogInterface dialog
) {
158 OwnCloudMainScreen
.this.finish();
161 AlertDialog alert
= builder
.create();
166 public void onBackPressed() {
167 PathLayout pl
= (PathLayout
) findViewById(R
.id
.pathLayout1
);
168 if (mIsDisplayingFile
) {
169 mIsDisplayingFile
= false
;
170 setContentView(R
.layout
.main
);
171 pl
= (PathLayout
) findViewById(R
.id
.pathLayout1
);
173 if (mParents
.empty()) {
174 uri
= ProviderTableMeta
.CONTENT_URI
;
176 uri
= Uri
.withAppendedPath(ProviderTableMeta
.CONTENT_URI_DIR
, mParents
.peek());
178 mCursor
= managedQuery(uri
,
180 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+"=?",
181 new String
[]{mAccount
.name
}, null
);
183 if (mCursor
.moveToFirst()) {
184 String s
= mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_PATH
));
185 for (String str
: s
.split("/")) {
186 if (!TextUtils
.isEmpty(str
))
187 pl
.push(DisplayUtils
.HtmlDecode(str
));
190 getListView().setAdapter(new FileListListAdapter(mCursor
, this));
191 getListView().invalidate();
194 if (mParents
.size()==0) {
195 super.onBackPressed();
197 } else if (mParents
.size() == 1) {
201 mCursor
= managedQuery(ProviderTableMeta
.CONTENT_URI
,
203 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+"=?",
204 new String
[]{mAccount
.name
},
210 mCursor
= managedQuery(Uri
.withAppendedPath(ProviderTableMeta
.CONTENT_URI_DIR
, mParents
.peek()),
212 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+"=?",
213 new String
[]{mAccount
.name
},
217 setListAdapter(new FileListListAdapter(mCursor
, this));
218 getListView().invalidate();
222 protected void onListItemClick(ListView l
, View v
, int position
, long id
) {
223 super.onListItemClick(l
, v
, position
, id
);
224 PathLayout pl
= (PathLayout
) findViewById(R
.id
.pathLayout1
);
225 if (!mCursor
.moveToPosition(position
)) {
226 throw new IndexOutOfBoundsException("Incorrect item selected");
228 if (!mIsDisplayingFile
) {
229 if (mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_CONTENT_TYPE
)).equals("DIR")) {
230 String id_
= mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
._ID
));
231 String dirname
= mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_NAME
));
232 pl
.push(DisplayUtils
.HtmlDecode(dirname
));
233 mPath
.addLast(DisplayUtils
.HtmlDecode(dirname
));
235 mCursor
= managedQuery(Uri
.withAppendedPath(ProviderTableMeta
.CONTENT_URI_DIR
, id_
),
237 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+ "=?",
238 new String
[]{mAccount
.name
}, null
);
239 setListAdapter(new FileListListAdapter(mCursor
, this));
241 mIsDisplayingFile
= true
;
242 setContentView(R
.layout
.file_display
);
243 String id_
= mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
._ID
));
244 mCursor
= managedQuery(Uri
.withAppendedPath(ProviderTableMeta
.CONTENT_URI_FILE
, id_
),
249 mCursor
.moveToFirst();
251 TextView tv
= (TextView
) findViewById(R
.id
.textView1
);
252 tv
.setText(mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_NAME
)));
254 tv
= (TextView
) findViewById(R
.id
.textView2
);
255 tv
.setText(DisplayUtils
.convertMIMEtoPrettyPrint(mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_CONTENT_TYPE
))));
257 tv
= (TextView
) findViewById(R
.id
.textView3
);
258 tv
.setText(DisplayUtils
.bitsToHumanReadable(mCursor
.getLong(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_CONTENT_LENGTH
))));
260 tv
= (TextView
) findViewById(R
.id
.textView4
);
261 tv
.setText(mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_MODIFIED
)));
262 if (!TextUtils
.isEmpty(mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_STORAGE_PATH
))) &&
263 mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_CONTENT_TYPE
)).matches("image/*")) {
264 ImageView iv
= (ImageView
) findViewById(R
.id
.imageView1
);
265 Bitmap bmp
= BitmapFactory
.decodeFile(mCursor
.getString(mCursor
.getColumnIndex(ProviderTableMeta
.FILE_STORAGE_PATH
)));
266 Matrix m
= new Matrix();
268 if (bmp
.getWidth() > bmp
.getHeight()) {
269 scale
= (float) (200./bmp
.getWidth());
271 scale
= (float) (200./bmp
.getHeight());
273 m
.postScale(scale
, scale
);
274 Bitmap newBmp
= Bitmap
.createBitmap(bmp
, 0, 0, bmp
.getWidth(), bmp
.getHeight(), m
, true
);
275 iv
.setImageBitmap(newBmp
);
277 setListAdapter(new FileListActionListAdapter(mCursor
, this, mAccount
));
279 getListView().invalidate();
282 Intent i
= (Intent
) getListAdapter().getItem(position
);
283 if (i
.hasExtra("toDownload")) {
285 Uri data
= Uri
.parse(Environment
.getExternalStorageDirectory().getAbsolutePath() + "/owncloud/filename");
286 Log
.d("DUPA", data
.toString());
287 File f
= new File(data
.toString());
288 FileInputStream fis
= new FileInputStream(f
);
289 byte buffer
[] = new byte[512];
291 Log
.d("DUPA", new String(buffer
));
293 Intent intent
= new Intent(this, FileDownloader
.class);
294 intent
.putExtra(FileDownloader
.EXTRA_FILE_PATH
, "/"+((TextView
)findViewById(R
.id
.textView1
)).getText().toString());
295 intent
.putExtra(FileDownloader
.EXTRA_ACCOUNT
, mAccount
);
296 startService(intent
);
298 if (i.getBooleanExtra("toDownload", false)) {
299 startActivityForResult(i, 200);
304 } catch (ClassCastException e
) {} catch (FileNotFoundException e
) {
305 // TODO Auto-generated catch block
307 } catch (IOException e
) {
308 // TODO Auto-generated catch block
314 private void populateFileList() {
315 if (mParents
.empty()) {
316 mCursor
= getContentResolver().query(ProviderTableMeta
.CONTENT_URI
,
318 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+"=?",
319 new String
[]{mAccount
.name
},
322 mCursor
= getContentResolver().query(Uri
.withAppendedPath(ProviderTableMeta
.CONTENT_URI_DIR
, mParents
.peek()),
324 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+ "=?",
325 new String
[]{mAccount
.name
}, null
);
326 if (!mIsDisplayingFile
) {
327 PathLayout pl
= (PathLayout
) findViewById(R
.id
.pathLayout1
);
328 for (String s
: mPath
) {
333 setListAdapter(new FileListListAdapter(mCursor
, this));
334 getListView().invalidate();
338 protected void onActivityResult(int requestCode
, int resultCode
, Intent data
) {
339 super.onActivityResult(requestCode
, resultCode
, data
);
343 protected void onSaveInstanceState(Bundle outState
) {
344 super.onSaveInstanceState(outState
);
345 outState
.putSerializable("parentsStack", mParents
);
346 outState
.putSerializable("path", mPath
);
347 outState
.putBoolean("isDisplayingFile", mIsDisplayingFile
);