ucl::SharedRef<MediaItems> m_items;
};
+ enum {
+ FLAG_THUMBNAIL = 1,
+ FLAG_REMOVE = 2,
+
+ FLAGS_FROM_MEDIA_DB = (FLAG_THUMBNAIL | FLAG_REMOVE),
+ FLAGS_SIMPLE_FILE = 0
+ };
+
public:
static MediaItemSRef newInstance(media_info_h media);
+ static MediaItemSRef newInstance(std::string filePath);
virtual ~MediaItem();
bool isValid() const;
+ int getFlags() const;
MediaType getType() const;
const std::string &getId() const;
- void getResolution(int &x, int &y) const;
-
const std::string &getFilePath() const;
ucl::Result getThumbnailPath(ThumbnailPathGetCb cb) const;
protected:
friend class ucl::RefCountObj<MediaItem>;
- MediaItem(MediaType type);
+ MediaItem(int flags, MediaType type);
ucl::Result prepare(media_info_h media);
- ucl::Result prepareImage(image_meta_h imageMeta);
+ ucl::Result prepare(std::string filePath);
private:
ucl::Result initThumbPath(media_info_h media) const;
};
private:
+ const int m_flags;
const MediaType m_type;
std::string m_mediaId;
std::string m_filePath;
- int m_resolutionX;
- int m_resolutionY;
mutable media_info_h m_media;
mutable std::string m_thumbPath;
mutable std::unique_ptr<ThumbCbProxy> m_thumbCbProxy;
void startMediaContentScan();
void onScanComplete(media_content_error_e error);
+ ucl::Result handleAppControl(app_control_h appControl);
+ ucl::Result handleSingleMode(const std::string &operation,
+ app_control_h appControl);
+ ucl::Result handleGroupMode(const std::string &operation,
+ app_control_h appControl);
+
void createNoContentPage();
void createThumbnailPage();
+ void createViewerPage(std::string filePath);
void onAlbumChanged();
void onPageExitRequest(Page &page);
ucl::NaviframeSRef m_navi;
PageWRef m_page;
+
+ bool m_isGroupMode;
};
}
struct ItemParams {
int flags;
- int aspectX;
- int aspectY;
std::string imagePath;
std::string bgImagePath;
};
class Builder {
public:
Builder();
- Builder &setImageSize(int w, int h);
+ Builder &setHighResImagePath(std::string path);
+ Builder &setForceLoad(bool value);
ImageViewerSRef build(ucl::ElmWidget &parent) const;
private:
- int m_imageW;
- int m_imageH;
+ std::string m_highResPath;
+ bool m_forceLoad;
};
public:
void setLowResImagePath(const std::string &path);
- void setHighResImagePath(const std::string &path);
-
bool zoomIn(int originX, int originY);
bool zoomOut();
private:
friend class ucl::RefCountObj<ImageViewer>;
- ImageViewer(ucl::RefCountObjBase &rc, int imageW,
- int imageH, Evas_Object *scroller);
+ ImageViewer(ucl::RefCountObjBase &rc, Evas_Object *scroller,
+ const std::string &highResPath, bool forceLoad);
virtual ~ImageViewer();
- void prepare();
+ void prepare(const std::string &highResPath, bool forceLoad);
void onImagePreloaded(ucl::Widget &widget, void *eventInfo);
void onScrollerResize(ucl::Widget &widget, void *eventInfo);
};
private:
- const int m_imageW;
- const int m_imageH;
-
ucl::StyledWidgetWRef m_scroller;
ucl::Layout m_layout;
ucl::Widget m_grid;
ucl::Widget m_lowResImage;
ucl::Widget m_highResImage;
+ int m_imageW;
+ int m_imageH;
+
int m_scrollerW;
int m_scrollerH;
int m_gridW;
#undef UCL_LOG_TAG
#define UCL_LOG_TAG GALLERY_LOG_TAG
+#include "helpers.h"
+
#endif // __GALLERY_COMMON_H__
--- /dev/null
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora 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://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GALLERY_HELPERS_H__
+#define __GALLERY_HELPERS_H__
+
+#include <string>
+
+namespace gallery {
+
+ template <class T>
+ bool getProperty(T obj, int (*get)(T obj, char **value),
+ std::string &result, bool optional = false);
+
+ template <class T, class V>
+ bool getProperty(T obj, int (*get)(T obj, V *value),
+ V &result, bool mayBeZero = false);
+}
+
+#include "helpers.hpp"
+
+#endif // __GALLERY_HELPERS_H__
--- /dev/null
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora 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://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ucl/util/logging.h"
+
+namespace gallery {
+
+ template <class T>
+ inline bool getProperty(T obj,
+ int (*get)(T obj, char **value),
+ std::string &result, bool optional)
+ {
+ char *value = nullptr;
+ const int ret = get(obj, &value);
+ if ((ret != 0) || (!optional && !value)) {
+ UCL_ELOG("get() failed: %d", ret);
+ return false;
+ }
+
+ if (value) {
+ result = value;
+ free(value);
+ } else {
+ result.clear();
+ }
+
+ return true;
+ }
+
+ template <class T, class V>
+ inline bool getProperty(T obj, int (*get)(T obj, V *value),
+ V &result, bool mayBeZero)
+ {
+ const int ret = get(obj, &result);
+ if ((ret != 0) || (!mayBeZero && !result)) {
+ UCL_ELOG("get() failed: %d", ret);
+ return false;
+ }
+ return true;
+ }
+}
// MediaItem //
- MediaItem::MediaItem(const MediaType type) :
+ MediaItem::MediaItem(const int flags, const MediaType type) :
+ m_flags(flags),
m_type(type),
- m_resolutionX(0),
- m_resolutionY(0),
m_media(nullptr),
m_isValid(false)
{
"media_info_get_media_type() failed: %d", ret);
}
- auto result = makeShared<MediaItem>(toMediaType(contentType));
+ auto result = makeShared<MediaItem>(FLAGS_FROM_MEDIA_DB,
+ toMediaType(contentType));
FAIL_RETURN_VALUE(result->prepare(media), {},
"result->prepare() failed!");
return result;
}
+ MediaItemSRef MediaItem::newInstance(std::string filePath)
+ {
+ auto result = makeShared<MediaItem>(FLAGS_SIMPLE_FILE,
+ MediaType::IMAGE);
+
+ FAIL_RETURN_VALUE(result->prepare(std::move(filePath)), {},
+ "result->prepare() failed!");
+
+ return result;
+ }
+
Result MediaItem::prepare(const media_info_h media)
{
FAIL_RETURN(initThumbPath(media), "initThumbPath() failed!");
LOG_RETURN(RES_FAIL, "getProperty(file_path) failed!");
}
- if (m_type == MediaType::IMAGE) {
- image_meta_h imageMeta = nullptr;
- const int ret = media_info_get_image(media, &imageMeta);
- if ((ret != 0) || !imageMeta) {
- LOG_RETURN(RES_FAIL, "media_info_get_image() failed: %d", ret);
- }
- const Result result = prepareImage(imageMeta);
- image_meta_destroy(imageMeta);
- FAIL_RETURN(result, "prepareImage() failed!");
- }
-
m_isValid = true;
return RES_OK;
}
- Result MediaItem::prepareImage(const image_meta_h imageMeta)
- {
- if (!getProperty(imageMeta, image_meta_get_width, m_resolutionX)) {
- LOG_RETURN(RES_FAIL, "getProperty(image_width) failed!");
- }
-
- if (!getProperty(imageMeta, image_meta_get_height, m_resolutionY)) {
- LOG_RETURN(RES_FAIL, "getProperty(image_width) failed!");
- }
-
- return RES_OK;
- }
-
Result MediaItem::initThumbPath(const media_info_h media) const
{
if (!getProperty(media, media_info_get_thumbnail_path,
return RES_OK;
}
+ Result MediaItem::prepare(std::string filePath)
+ {
+ m_filePath = std::move(filePath);
+ m_isValid = true;
+ return RES_OK;
+ }
+
void MediaItem::freeMediaInfo() const
{
if (m_media) {
return m_isValid;
}
+ int MediaItem::getFlags() const
+ {
+ return m_flags;
+ }
+
MediaType MediaItem::getType() const
{
return m_type;
return m_mediaId;
}
- void MediaItem::getResolution(int &x, int &y) const
- {
- x = m_resolutionX;
- y = m_resolutionY;
- }
-
const std::string &MediaItem::getFilePath() const
{
return m_filePath;
Result MediaItem::removeFile()
{
+ if (!(m_flags & FLAG_REMOVE)) {
+ LOG_RETURN(RES_NOT_SUPPORTED, "Operation not suported!");
+ }
if (!ecore_file_can_write(m_filePath.c_str())) {
LOG_RETURN(RES_FAIL, "File can't be removed!");
}
Result MediaItem::getThumbnailPath(ThumbnailPathGetCb cb) const
{
+ if (!(m_flags & FLAG_THUMBNAIL)) {
+ LOG_RETURN(RES_NOT_SUPPORTED, "Operation not suported!");
+ }
if (!cb) {
return RES_INVALID_ARGUMENTS;
}
using namespace ucl;
- bool getProperty(media_info_h media,
- int (*get)(media_info_h media, char **value),
- std::string &result, const bool optional)
- {
- char *value = nullptr;
- const int ret = get(media, &value);
- if ((ret != 0) || (!optional && !value)) {
- ELOG("get() failed: %d", ret);
- return false;
- }
-
- if (value) {
- result = value;
- free(value);
- } else {
- result.clear();
- }
-
- return true;
- }
-
- bool getProperty(image_meta_h imageMeta,
- int (*get)(image_meta_h imageMeta, int *value),
- int &result, bool mayBeZero)
- {
- const int ret = get(imageMeta, &result);
- if ((ret != 0) || (!mayBeZero && !result)) {
- ELOG("get() failed: %d", ret);
- return false;
- }
- return true;
- }
-
Mutex &getMediaMutex()
{
static Mutex mutex{true};
MediaType toMediaType(media_content_type_e contentType);
- bool getProperty(media_info_h media,
- int (*get)(media_info_h media, char **value),
- std::string &result, bool optional = false);
-
- bool getProperty(image_meta_h imageMeta,
- int (*get)(image_meta_h imageMeta, int *value),
- int &result, bool mayBeZero = false);
-
ucl::Mutex &getMediaMutex();
}
#include "ucl/appfw/helpers.h"
#include "model/Gallery.h"
+#include "model/MediaItem.h"
#include "model/IMediaAlbum.h"
#include "presenters/NoContentPage.h"
#include "presenters/ThumbnailPage.h"
+#include "presenters/ViewerPage.h"
#include "resources.h"
#include "common.h"
SysEventProvider &sysEventProvider) :
RefCountAware(&rc),
m_sysEventProvider(sysEventProvider),
- m_isScanInProgress(false)
+ m_isScanInProgress(false),
+ m_isGroupMode(false)
{
}
{
DLOG("APP CONTROL");
+ if (isBad(handleAppControl(appControl))) {
+ DLOG("Terminating the application...");
+ m_context->exitApp();
+ return;
+ }
+
+ if (!m_win->isVisible()) {
+ DLOG("Show the window.");
+ show(*m_win);
+ }
+ }
+
+ Result Instance::handleAppControl(app_control_h appControl)
+ {
+ std::string operation;
+ if (!getProperty(appControl, app_control_get_operation, operation)) {
+ ELOG("app_control_get_operation() failed!");
+ }
+
+ app_control_launch_mode_e mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
+ if (!getProperty(appControl, app_control_get_launch_mode, mode, true)) {
+ ELOG("app_control_get_launch_mode() failed!");
+ mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
+ }
+
+ DLOG("operation: %s; mode: %d;", operation.c_str(), mode);
+
+ switch (mode) {
+ case APP_CONTROL_LAUNCH_MODE_SINGLE:
+ return handleSingleMode(operation, appControl);
+ case APP_CONTROL_LAUNCH_MODE_GROUP:
+ return handleGroupMode(operation, appControl);
+ default:
+ ELOG("Invalid mode: %d;", mode);
+ break;
+ }
+
+ return RES_OK;
+ }
+
+ Result Instance::handleSingleMode(const std::string &operation,
+ app_control_h appControl)
+ {
if (!m_page) {
if (isEmpty(m_gallery->getAlbum())) {
createNoContentPage();
} else {
createThumbnailPage();
}
+ } else if (operation == APP_CONTROL_OPERATION_MAIN) {
+ m_page->deleteTo();
}
- if (!m_win->isVisible()) {
- DLOG("Show the window.");
- show(*m_win);
+ return RES_OK;
+ }
+
+ Result Instance::handleGroupMode(const std::string &operation,
+ app_control_h appControl)
+ {
+ if (m_page) {
+ WLOG("Page is already created. Ignoring second request!");
+ return RES_OK;
+ }
+
+ if (operation == APP_CONTROL_OPERATION_VIEW) {
+ std::string uri;
+ if (!getProperty(appControl, app_control_get_uri, uri)) {
+ ELOG("app_control_get_uri() failed!");
+ return RES_FAIL;
+ }
+ createViewerPage(uri);
+ } else {
+ WLOG("Operation not supported for current mode!");
+ return RES_NOT_SUPPORTED;
}
+
+ m_isGroupMode = true;
+
+ return RES_OK;
}
void Instance::createNoContentPage()
build(DELEGATE(Instance::onPageExitRequest, this));
}
+ void Instance::createViewerPage(std::string filePath)
+ {
+ DLOG("Creating ViewerPage.");
+ m_page = ViewerPage::Builder().setNaviframe(m_navi).
+ setMedia(MediaItem::newInstance(std::move(filePath))).
+ setExitOnZoomOut(false).
+ build(DELEGATE(Instance::onPageExitRequest, this));
+ }
+
void Instance::onAlbumChanged()
{
if (isEmpty(m_gallery->getAlbum())) {
void Instance::onPageExitRequest(Page &page)
{
if (page.isAtBottom()) {
- DLOG("Bottom page. Lowering the window.");
- m_win->lower();
+ DLOG("Bottom page.");
+ if (m_isGroupMode) {
+ DLOG("In group mode. Exit the application...");
+ m_context->exitApp();
+ } else {
+ DLOG("Lowering the window.");
+ m_win->lower();
+ }
} else {
DLOG("Exit page.");
page.exit();
FAIL_LOG(result, "Failed to get thumbnail!");
ImageGrid::ItemParams params = {};
- m_media->getResolution(params.aspectX, params.aspectY);
params.imagePath = m_media->getFilePath();
params.bgImagePath = path;
addFlags(params);
Result ViewerPage::prepare()
{
- int mediaW = 0;
- int mediaH = 0;
- m_media->getResolution(mediaW, mediaH);
+ const bool hasThumb = (m_media->getFlags() & MediaItem::FLAG_THUMBNAIL);
m_imageViewer = ImageViewer::Builder().
- setImageSize(mediaW, mediaH).
+ setHighResImagePath(m_media->getFilePath()).
+ setForceLoad(!hasThumb).
build(getNaviframe());
if (!m_imageViewer) {
LOG_RETURN(RES_FAIL, "ImageViewer::build() failed!");
}
- FAIL_RETURN(m_media->getThumbnailPath(DELEGATE(
- ViewerPage::onThumbnail, this)),
- "m_media->getThumbnailPath() failed!");
-
- m_imageViewer->setHighResImagePath(m_media->getFilePath());
+ if (hasThumb) {
+ FAIL_RETURN(m_media->getThumbnailPath(DELEGATE(
+ ViewerPage::onThumbnail, this)),
+ "m_media->getThumbnailPath() failed!");
+ }
m_imageViewer->addEventHandler(IMAGE_VIEWER_ZOOM_END,
WEAK_DELEGATE(ViewerPage::onZoomEnd, asWeak(*this)));
evas_object_image_file_set(*m_bgImage,
params.bgImagePath.c_str(), NULL);
- int w = params.aspectX;
- int h = params.aspectY;
+ int w = 0;
+ int h = 0;
+ elm_image_object_size_get(m_image, &w, &h);
if ((w == 0) || (h == 0)) {
+ WLOG("Invalid image size!");
evas_object_image_size_get(*m_bgImage, &w, &h);
+ if ((w == 0) || (h == 0)) {
+ WLOG("Invalid image size!");
+ w = 1;
+ h = 1;
+ }
}
m_bgImage->setARHint(WidgetARHint::NEITHER, w, h);
// ImageViewer::Builder //
ImageViewer::Builder::Builder() :
- m_imageW(0),
- m_imageH(0)
+ m_forceLoad(false)
+ {
+ }
+
+ ImageViewer::Builder &ImageViewer::Builder::
+ setHighResImagePath(std::string path)
{
+ m_highResPath = std::move(path);
+ return *this;
}
- ImageViewer::Builder &ImageViewer::Builder::setImageSize(
- const int w, const int h)
+ ImageViewer::Builder &ImageViewer::Builder::setForceLoad(const bool value)
{
- m_imageW = w;
- m_imageH = h;
+ m_forceLoad = value;
return *this;
}
ImageViewerSRef ImageViewer::Builder::build(ElmWidget &parent) const
{
- if ((m_imageW <= 0) || (m_imageH <= 0)) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "Image size is invalid");
+ if (isEmpty(m_highResPath)) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
+ "m_highResPath is empty!");
}
auto scroller = elm_scroller_add(parent);
LOG_RETURN_VALUE(RES_FAIL, {}, "elm_scroller_add() failed!");
}
- return makeShared<ImageViewer>(m_imageW, m_imageH, scroller);
+ return makeShared<ImageViewer>(scroller, m_highResPath, m_forceLoad);
}
// ImageViewer //
- ImageViewer::ImageViewer(RefCountObjBase &rc,
- const int imageW, const int imageH,
- Evas_Object *const scroller) :
+ ImageViewer::ImageViewer(RefCountObjBase &rc, Evas_Object *const scroller,
+ const std::string &highResPath, const bool forceLoad) :
ElmWidget(&rc, scroller, true),
- m_imageW(imageW),
- m_imageH(imageH),
m_scroller(makeShared<StyledWidget>(scroller)),
m_layout(elm_layout_add(*m_scroller)),
m_lowResImage(evas_object_image_filled_add(m_grid.getEvas())),
m_highResImage(evas_object_image_filled_add(m_grid.getEvas())),
+ m_imageW(0),
+ m_imageH(0),
+
m_scrollerW(0),
m_scrollerH(0),
m_gridW(0),
m_animator(nullptr),
m_state(State::ZOOMED_OUT)
{
- prepare();
+ prepare(highResPath, forceLoad);
}
ImageViewer::~ImageViewer()
}
}
- void ImageViewer::prepare()
+ void ImageViewer::prepare(const std::string &highResPath,
+ const bool forceLoad)
{
expandAndFill(*m_scroller);
m_scroller->setStyle(SCROLLER_STYLE);
ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
elm_scroller_single_direction_set(*m_scroller,
ELM_SCROLLER_SINGLE_DIRECTION_NONE);
- elm_object_scroll_freeze_push(*m_scroller);
show(*m_scroller);
expandAndFill(m_layout);
evas_object_grid_pack(m_grid, m_lowResImage, 0, 0, 1, 1);
show(m_lowResImage);
+ makeTransparent(m_lowResImage);
+
evas_object_grid_pack(m_grid, m_highResImage, 0, 0, 1, 1);
- show(m_highResImage);
+ if (forceLoad) {
+ evas_object_image_file_set(m_highResImage,
+ highResPath.c_str(), nullptr);
+ show(m_highResImage);
+ } else {
+ hide(m_highResImage);
+ m_highResImage.addEventHandler(WidgetEvent::IMAGE_PRELOADED,
+ WEAK_DELEGATE(ImageViewer::onImagePreloaded,
+ asWeak(*this)));
+ evas_object_image_file_set(m_highResImage,
+ highResPath.c_str(), nullptr);
+ evas_object_image_preload(m_highResImage, EINA_FALSE);
+ }
+
+ evas_object_image_size_get(m_highResImage, &m_imageW, &m_imageH);
+ if ((m_imageW == 0) || (m_imageH == 0)) {
+ WLOG("Invalid image size!");
+ m_imageW = 1;
+ m_imageH = 1;
+ }
m_scroller->addEventHandler(WidgetEvent::RESIZE,
WEAK_DELEGATE(ImageViewer::onScrollerResize, asWeak(*this)));
-
- m_highResImage.addEventHandler(WidgetEvent::IMAGE_PRELOADED,
- WEAK_DELEGATE(ImageViewer::onImagePreloaded, asWeak(*this)));
}
void ImageViewer::onScrollerResize(Widget &widget, void *eventInfo)
void ImageViewer::setLowResImagePath(const std::string &path)
{
evas_object_image_file_set(m_lowResImage, path.c_str(), nullptr);
- }
-
- void ImageViewer::setHighResImagePath(const std::string &path)
- {
- hide(m_highResImage);
- evas_object_image_file_set(m_highResImage, path.c_str(), nullptr);
- evas_object_image_preload(m_highResImage, EINA_FALSE);
+ makeWhite(m_lowResImage);
}
void ImageViewer::onImagePreloaded(Widget &widget, void *eventInfo)
if (pos >= impl::ANIMATION_STOP_POS) {
m_animator = nullptr;
- if (m_state == State::ZOOMING_IN) {
- m_state = State::ZOOMED_IN;
- elm_object_scroll_freeze_pop(*m_scroller);
- } else {
- m_state = State::ZOOMED_OUT;
- elm_object_scroll_freeze_push(*m_scroller);
- }
+ m_state = ((m_state == State::ZOOMING_IN) ?
+ State::ZOOMED_IN : State::ZOOMED_OUT);
callEvent(IMAGE_VIEWER_ZOOM_END, nullptr);
return ECORE_CALLBACK_CANCEL;
}
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
-<manifest xmlns="http://tizen.org/ns/packages" api-version="3.0" package="org.tizen.gallery" version="1.0.0">\r
- <profile name="wearable"/>\r
- <ui-application appid="org.tizen.gallery" exec="gallery" hw-acceleration="on" multiple="false" nodisplay="false" splash-screen-display="false" taskmanage="true" type="capp">\r
- <label>gallery</label>\r
- <icon>org.tizen.gallery.png</icon>\r
- </ui-application>\r
- <privileges>\r
- <privilege>http://tizen.org/privilege/mediastorage</privilege>\r
- <privilege>http://tizen.org/privilege/externalstorage</privilege>\r
- <privilege>http://tizen.org/privilege/content.write</privilege>\r
- </privileges>\r
-</manifest>\r
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="3.0" package="org.tizen.gallery" version="1.0.0">
+ <profile name="wearable"/>
+ <ui-application appid="org.tizen.gallery" exec="gallery" hw-acceleration="on" launch_mode="caller" multiple="false" nodisplay="false" splash-screen-display="false" taskmanage="true" type="capp">
+ <label>gallery</label>
+ <icon>org.tizen.gallery.png</icon>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/view"/>
+ <mime name="image/*"/>
+ </app-control>
+ </ui-application>
+ <privileges>
+ <privilege>http://tizen.org/privilege/mediastorage</privilege>
+ <privilege>http://tizen.org/privilege/externalstorage</privilege>
+ <privilege>http://tizen.org/privilege/content.write</privilege>
+ </privileges>
+</manifest>