bug 569497 - need finger friendly file picker for android r=mwu,mbrubeck a=blocking-fennec

This commit is contained in:
Brad Lassey 2010-09-30 11:37:36 -04:00
parent eac8985f62
commit 7b4b5b27be
12 changed files with 287 additions and 6 deletions

View File

@ -21,7 +21,7 @@
android:label="@MOZ_APP_DISPLAYNAME@"
android:configChanges="keyboard|keyboardHidden|orientation|mcc|mnc"
android:windowSoftInputMode="stateUnspecified|adjustResize"
android:launchMode="singleInstance">
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

View File

@ -42,6 +42,7 @@ import java.util.*;
import java.util.zip.*;
import java.nio.*;
import java.nio.channels.FileChannel;
import java.util.concurrent.*;
import android.os.*;
import android.app.*;
@ -54,6 +55,7 @@ import android.widget.*;
import android.hardware.*;
import android.util.*;
import android.net.*;
abstract public class GeckoApp
extends Activity
@ -519,4 +521,64 @@ abstract public class GeckoApp
if (statusCode == 0)
System.exit(0);
}
static final int FILE_PICKER_REQUEST = 1;
private SynchronousQueue<String> mFilePickerResult = new SynchronousQueue();
public String showFilePicker() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
GeckoApp.this.
startActivityForResult(
Intent.createChooser(intent,"choose a file"),
FILE_PICKER_REQUEST);
String filePickerResult = "";
try {
filePickerResult = mFilePickerResult.take();
} catch (InterruptedException e) {
Log.i("GeckoApp", "error: " + e);
}
return filePickerResult;
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
String filePickerResult = "";
if (data != null && resultCode == RESULT_OK) {
try {
ContentResolver cr = getContentResolver();
Uri uri = data.getData();
String mimeType = cr.getType(uri);
String fileExt = "." +
mimeType.substring(mimeType.lastIndexOf('/') + 1);
File file =
File.createTempFile("tmp_" +
(int)Math.floor(1000 * Math.random()),
fileExt,
new File("/data/data/org.mozilla." +
getAppName()));
FileOutputStream fos = new FileOutputStream(file);
InputStream is = cr.openInputStream(uri);
byte[] buf = new byte[4096];
int len = is.read(buf);
while (len != -1) {
fos.write(buf, 0, len);
len = is.read(buf);
}
fos.close();
filePickerResult = file.getAbsolutePath();
}catch (Exception e) {
Log.e("GeckoApp", "error : "+ e);
}
}
try {
mFilePickerResult.put(filePickerResult);
} catch (InterruptedException e) {
Log.i("GeckoApp", "error: " + e);
}
}
}

View File

@ -560,4 +560,7 @@ class GeckoAppShell
GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return metrics.densityDpi;
}
public static String showFilePicker() {
return GeckoApp.mAppContext.showFilePicker();
}
}

View File

@ -44,10 +44,9 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
ifdef MOZ_XUL
ifeq (,$(filter qt beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
ifeq (,$(filter android qt beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
DIRS = public src
endif
endif
include $(topsrcdir)/config/rules.mk

View File

@ -243,7 +243,7 @@ COMPONENT_LIBS += \
$(NULL)
endif
ifeq (,$(filter qt beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
ifeq (,$(filter android qt beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
ifdef MOZ_XUL
COMPONENT_LIBS += fileview
DEFINES += -DMOZ_FILEVIEW

View File

@ -112,6 +112,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
jGetClipboardText = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getClipboardText", "()Ljava/lang/String;");
jSetClipboardText = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setClipboardText", "(Ljava/lang/String;)V");
jShowAlertNotification = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showAlertNotification", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
jShowFilePicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePicker", "()Ljava/lang/String;");
jAlertsProgressListener_OnProgress = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "alertsProgressListener_OnProgress", "(Ljava/lang/String;JJLjava/lang/String;)V");
jAlertsProgressListener_OnCancel = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "alertsProgressListener_OnCancel", "(Ljava/lang/String;)V");
jGetDpi = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getDpi", "()I");
@ -497,6 +498,14 @@ AndroidBridge::GetDPI()
return (int) mJNIEnv->CallStaticIntMethod(mGeckoAppShellClass, jGetDpi);
}
void
AndroidBridge::ShowFilePicker(nsAString& aFilePath)
{
jstring jstr = static_cast<jstring>(mJNIEnv->CallStaticObjectMethod(
mGeckoAppShellClass, jShowFilePicker));
aFilePath.Assign(nsJNIString(jstr));
}
void
AndroidBridge::SetSurfaceView(jobject obj)
{

View File

@ -166,6 +166,8 @@ public:
int GetDPI();
void ShowFilePicker(nsAString& aFilePath);
struct AutoLocalJNIFrame {
AutoLocalJNIFrame(int nEntries = 128) : mEntries(nEntries) {
AndroidBridge::Bridge()->JNI()->PushLocalFrame(mEntries);
@ -226,6 +228,7 @@ protected:
jmethodID jGetClipboardText;
jmethodID jSetClipboardText;
jmethodID jShowAlertNotification;
jmethodID jShowFilePicker;
jmethodID jAlertsProgressListener_OnProgress;
jmethodID jAlertsProgressListener_OnCancel;
jmethodID jGetDpi;

View File

@ -63,6 +63,7 @@ CPPSRCS = \
nsScreenManagerAndroid.cpp \
nsIdleServiceAndroid.cpp \
nsClipboard.cpp \
nsFilePicker.cpp \
$(NULL)
NOT_THERE_YET_CPPSRCS = \
@ -72,7 +73,6 @@ NOT_THERE_YET_CPPSRCS = \
nsNativeThemeQt.cpp \
mozqwidget.cpp \
nsSound.cpp \
nsFilePicker.cpp \
$(NULL)
SHARED_LIBRARY_LIBS = ../xpwidgets/libxpwidgets_s.a

View File

@ -1,4 +1,5 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version

View File

@ -0,0 +1,146 @@
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Android code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brad Lassey <blassey@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsFilePicker.h"
#include "AndroidBridge.h"
#include "nsNetUtil.h"
#include "nsIURI.h"
NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
NS_IMETHODIMP nsFilePicker::Init(nsIDOMWindow *parent, const nsAString& title,
PRInt16 mode)
{
return nsIFilePicker::modeOpen == mode ? NS_OK : NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::AppendFilters(PRInt32 filterMask)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::AppendFilter(const nsAString & title, const nsAString & filter)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::GetDefaultString(nsAString & aDefaultString)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::SetDefaultString(const nsAString & aDefaultString)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::GetDefaultExtension(nsAString & aDefaultExtension)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const nsAString & aDefaultExtension)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::GetDisplayDirectory(nsILocalFile **aDisplayDirectory)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::SetDisplayDirectory(nsILocalFile *aDisplayDirectory)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::GetFile(nsILocalFile **aFile)
{
NS_ENSURE_ARG_POINTER(aFile);
*aFile = nsnull;
if (mFilePath.IsEmpty()) {
return NS_OK;
}
nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
file->InitWithPath(mFilePath);
NS_ADDREF(*aFile = file);
nsCString path;
(*aFile)->GetNativePath(path);
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::GetFileURL(nsIURI **aFileURL)
{
nsCOMPtr<nsILocalFile> file;
GetFile(getter_AddRefs(file));
nsCOMPtr<nsIURI> uri;
NS_NewFileURI(getter_AddRefs(uri), file);
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
return CallQueryInterface(uri, aFileURL);
}
NS_IMETHODIMP nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsFilePicker::Show(PRInt16 *_retval NS_OUTPARAM)
{
if (!mozilla::AndroidBridge::Bridge())
return NS_ERROR_NOT_IMPLEMENTED;
nsAutoString filePath;
mozilla::AndroidBridge::Bridge()->ShowFilePicker(filePath);
*_retval = EmptyString().Equals(filePath) ?
nsIFilePicker::returnCancel : nsIFilePicker::returnOK;
if (*_retval == nsIFilePicker::returnOK)
mFilePath.Assign(filePath);
return NS_OK;
}

View File

@ -0,0 +1,53 @@
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Android code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brad Lassey <blassey@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef NSFILEPICKER_H
#define NSFILEPICKER_H
#include "nsIFilePicker.h"
#include "nsString.h"
class nsFilePicker : public nsIFilePicker
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIFILEPICKER
private:
nsString mFilePath;
};
#endif

View File

@ -52,6 +52,7 @@
#include "nsClipboard.h"
#include "nsClipboardHelper.h"
#include "nsTransferable.h"
#include "nsFilePicker.h"
#include "nsHTMLFormatConverter.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit)
@ -62,6 +63,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceAndroid)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
NS_DEFINE_NAMED_CID(NS_TOOLKIT_CID);
@ -74,6 +76,7 @@ NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID);
NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID);
NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
@ -87,6 +90,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_TRANSFERABLE_CID, false, NULL, nsTransferableConstructor },
{ &kNS_CLIPBOARD_CID, false, NULL, nsClipboardConstructor },
{ &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor },
{ &kNS_FILEPICKER_CID, false, NULL, nsFilePickerConstructor },
{ &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor },
{ NULL }
};
@ -102,6 +106,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID },
{ "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID },
{ "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID },
{ "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID },
{ "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
{ NULL }
};