Media Cloud App - Sacramento - California State University

Media Cloud App - Sacramento - California State University
PERSONAL MEDIA CLOUD APPLICATION FOR ANDROID
Prajakta Sarurkar
B.E., Nagpur University, 2000
PROJECT
Submitted in partial satisfaction of
the requirements for the degree of
MASTER OF SCIENCE
in
COMPUTER SCIENCE
at
CALIFORNIA STATE UNIVERSITY, SACRAMENTO
SPRING
2012
© 2012
Prajakta Sarurkar
ALL RIGHTS RESERVED
ii
PERSONAL MEDIA CLOUD APPLICATION FOR ANDROID
A Project
by
Prajakta Sarurkar
Approved by:
__________________________________, Committee Chair
Du Zhang, Ph.D.
__________________________________, Second Reader
Mary Jane Lee, Ph.D.
____________________________
Date
iii
Student: Prajakta Sarurkar
I certify that this student has met the requirements for format contained in the University
format manual, and that this project is suitable for shelving in the Library and credit is to
be awarded for the project.
__________________________, Graduate Coordinator
Nikrouz Faroughi, Ph.D.
Department of Computer Science
iv
___________________
Date
Abstract
of
PERSONAL MEDIA CLOUD APPLICATION FOR ANDROID
by
Prajakta Sarurkar
Recent advances in communication technologies have enabled an exponential growth in
connected devices like Android smart phones and tablets. These devices are mainly used
for content consumption. However, limited resources available on these devices, as well
as always connected internet accessibility makes these devices ideal platforms for cloud
computing.
This project is an attempt at creating personal media cloud player app for Android smart
phone devices. The project uses off the shelf hardware components for private cloud
implementation and Java programming over Android to provide full featured media cloud
platform. This private media cloud enables users to:

Store media files (images/audio/video etc) in the cloud

Access the media files from their Android device
Additionally, the project aims at providing following features:

File browsing

Audio streaming (MP3)

Video streaming (MP4)
v

Images (JPEG/PNG)

e-radio/ Photo Slide Show
The project aims at developing an application that can be used by any Android (version
2.2 and higher) smartphone to implement above mentioned media functionality.
, Committee Chair
Du Zhang, Ph.D.
______________________
Date
vi
DEDICATION
To my family
vii
ACKNOWLEDGEMENTS
I would like to thank my project advisor Dr. Du Zhang for taking time and giving me
guidance through the project.
I would also like to thank all the professors who taught me during my masters’ course
work.
I would like to thank my family for all the support.
viii
TABLE OF CONTENTS
Dedication ......................................................................................................................... vii
Acknowledgements .......................................................................................................... viii
Table Of Contents .............................................................................................................. ix
List Of Figures .................................................................................................................. xii
List Of Tables .................................................................................................................. xiii
1 INTRODUCTION .......................................................................................................... 1
1.1
Current state of practice for Media Cloud ............................................................ 1
1.2
Scope of the project .............................................................................................. 2
1.3
Benefits of Media Cloud App .............................................................................. 3
2 BACKGROUND ............................................................................................................ 5
2.1
Current existing Cloud Media Storage ................................................................. 5
2.2
Cloud Fundamentals ............................................................................................. 8
2.3
Cloud APIs ......................................................................................................... 12
2.4
Android Apps ..................................................................................................... 14
2.5
Android application components ....................................................................... 17
2.5.1
Activities ......................................................................................................... 17
2.5.2
Services ....................................................................................................... 18
2.5.3
Content providers ........................................................................................ 18
2.5.4
Broadcast receivers ..................................................................................... 19
3 ARCHITECTURE AND TECHNOLOGY .................................................................. 21
ix
3.1
Basic Architecture of Media Player app ............................................................ 21
3.2
Features ........................................................................................................... 22
3.3
Application ..................................................................................................... 23
4 IMPLEMENTATION DETAILS ................................................................................. 25
4.1
Media cloud ........................................................................................................ 25
4.2
4.3
Android APIs .................................................................................................. 28
Android client ..................................................................................................... 30
4.3.1
Login Screen ............................................................................................... 30
4.3.2
Main Screen ................................................................................................ 31
4.3.3
File View ..................................................................................................... 32
4.3.4
Music player................................................................................................ 33
4.3.5
Image Viewer .............................................................................................. 34
4.3.6
Video player ................................................................................................ 35
4.3.7
File Uploading ............................................................................................ 36
5 PERFORMANCE EVALUATION .............................................................................. 37
6 CONCLUSION AND FUTURE WORK ..................................................................... 39
6.1
Future work ........................................................................................................ 39
6.1.1
Playlist Management ................................................................................... 39
6.1.2
File Sharing ................................................................................................. 39
6.1.3
Folder sync up ............................................................................................. 40
x
Appendix Source Code ..................................................................................................... 41
Bibliography ..................................................................................................................... 97
xi
LIST OF FIGURES
Page
Figure 1: Typical cloud configuration ................................................................................ 9
Figure 2: Cloud storage setup using Pogoplug ................................................................. 11
Figure 3: Architecture of Pogoplug device ....................................................................... 12
Figure 4: Architecture of Cloud Media player app ........................................................... 22
Figure 5: Control flow in Cloud Media player app........................................................... 24
Figure 6: Login Screen...................................................................................................... 31
Figure 7: Main Screen ....................................................................................................... 32
Figure 8: File view ............................................................................................................ 33
Figure 9: (A) - Audio player screen, (B) – Radio player screen ....................................... 34
Figure 10: (A) - Image diaglog box, (B) – Loaded image ................................................ 35
Figure 11: File uploading .................................................................................................. 36
xii
LIST OF TABLES
Page
Table 1: Media formats supported by Media Cloud App ................................................... 2
Table 2: Comparative study of various cloud implementations ......................................... 6
Table 3: Pogoplug Specifications ..................................................................................... 11
Table 4: Pogoplug APIs .................................................................................................... 27
Table 5: Android APIs ...................................................................................................... 29
Table 6: Media Cloud app performance evaluation .......................................................... 38
xiii
1
Chapter 1
INTRODUCTION
Smartphones along with Tablet computers are turning out to be the ―next big thing‖ in
crowded electronic gadget industry [1]. Customizable features, powerful gesture based
user interface, and always ON connectivity are the key features that are resulting in
widespread popularity of smartphone devices. Smartphones are also responsible for
growing interest in cloud computing, especially in the domain of media consumption [2,
3]. Always ON internet connectivity allows users to easily access data from remote
servers in the cloud [4]. This enables users to easily store digital multi-media in the cloud
and access them from anywhere, anytime.
1.1 Current state of practice for Media Cloud
Feature rich Android Smartphones and Tablet computers have enabled a wide range of
applications and new usage models, including cloud based applications. However, use of
cloud based media storage is becoming popular only after faster connection speeds
offered by 3G and 4G communication networks. Some applications such as Pandora and
You Tube do exist that allow cloud like media streaming but these applications can only
stream content available on respective web sites and not personal collection.
Recently companies such as Amazon and Apple have made media cloud service available
[5, 6] but these are targeted towards media purchased on the Amazon or iTunes
respectively. Apple’s iCloud does allow uploading personal files but it is more expensive
2
than having personal cloud device. Currently, there are a few applications available that
will allow users to access their personal cloud storage using their smartphone devices.
1.2 Scope of the project
This project aims at setting up a personal media cloud [17] using standard off the shelf
components. Additionally, the project aims at developing an Android app that will enable
Android Smartphones and Tablet computers to access the media stored on cloud and
allows media playback.
Media Type
Format
File Type
Details
Mono/Stereo,
AAC/HEAudio
.3gp/.mp4
Bit rates up to
AACv1/HE-AACv2
160kHz
Mono/Stereo,
Audio
MP3
.mp3
bit rates 8320k
MIDI Type 0
Audio
MIDI
.mid
and Type 1
Image
JPEG/GIF/PNG/BMP
.jpg/.gif//.png/.bmp
Video
H.263
.3gp/.mp4
Table 1: Media formats supported by Media Cloud App
3
The media app will support following features:

File browsing

Image Viewer

Audio Playback

Video Playback
Media app will allow streaming media over internet. Table 1 shows media formats that
will be supported by the app.
1.3 Benefits of Media Cloud App
Growing popularity of Android Smartphones and Tablet computers is helping cloud
based data storage to grow popular as well. Morevoer, in today’s digital world people are
increasingly finding ways to store the media in cloud. Cloud storage also allows people to
easily share their personal media. Media cloud app allows users to easily access media
stored in their personal cloud device using Android smartphones and tablets. It will also
address shortcomings in currently available media cloud app such as video streaming, file
upload, photo slideshow, e-radio etc.
Rest of this report is divided in several chapters. Chapter 2 includes the background
information on cloud storage as well as Android apps. Detailed information on setting up
cloud storage and Android application development is presented. Chapter 3 includes the
architecture and features of the Media Cloud App. Chapter 4 includes implementation
4
details of different modules of the Media Cloud App. Chapter 5 includes the performance
evaluation of the Media Cloud App. Chapter 6 includes the conclusion and future work.
5
Chapter 2
BACKGROUND
Chapter 1 discussed the need for an Android app that supports cloud based media storage.
This chapter provides background information including cloud fundamentals as well
Android app development.
2.1 Current existing Cloud Media Storage
Media centric cloud computing is rapidly evolving field and a number of advances are
happening in this area [4]. Table 2 shows the comparative details about various clouds
available to users. Most noteworthy are Apple’s iCloud [4], Amazon cloud media player
[5], Zumodrive [7], and Pogoplug [10].
iCloud is a well integrated cloud service with Apple. This service is integrated with
various Apple devices such iPhone, iPod, iMac etc. This service allows user to store
media such as photos, music and documents, in addition to apps, calendar etc. However
iCloud does not support video streaming.
6
CRITERIA ICLOUD
AMAZON
ZUMO
POGOPLUG
DRIVE
Cloud
Commercial
Commercial
SW Cloud
Type
Cloud Service
Cloud Service
adapter
Storage
Up to 100GB
Up to 1TB
Depends on
Depends on HD
HD
Limit
Cost/GB
Cloud App
$2/year (for
$1/year (for
~ $2/year plus
~10¢ fixed cost
100GB)
1TB)
Hardware cost (for 2TB)
(for 500GB)
Services
Apps, Music,
Music storage,
Music, picture Store any type
Photo, Docs
streaming
storage,
of file, Audio
streaming
Advantages Integrated
with Apps
Integrated with Integrates
Low cost,
Amazon
with iTunes,
standard based
Picasa
interfaces
Limitations No Video
No Video
No Video
No Automatic
Streaming
Streaming
Streaming
Sync
No Video
streaming
Table 2: Comparative study of various cloud implementations
7
Amazon, the largest online retailer recently announced online media storage service with
a cloud media player for Android devices. The newly launched service will help users in
storing application, songs and other digital media, and will also enable Android users to
stream music stored on the Amazon servers with a Cloud Drive Player application. The
application supports most commonly used file types, including AAC and MP3, and
streams the media back at the full bit rate of the original file. Cloud media player
supports some common controls like play, pause, skip and users can even build their own
playlists. However, this service will not support video streaming. Moreover, uploading
music from mobile device is not currently supported, although music files may be
uploaded from PC or Mac. This solution also does not support syncing media files from
device to the cloud.
ZumoDrive is a cloud media storage solution that supports devices running Android 1.6
and later versions. Users install the ZumoDrive application on their PC computer which
enables them to access media files such as music and photos using the ZumoDrive app on
Android device. ZumoDrive supports sharing any type of media file, however this
solution does not support video streaming. This solution also does not support syncing
media files from device to the cloud.
Pogoplug cloud app is used to connect with Pogoplug cloud adapter. Pogoplug cloud
adapter allows users to connect their own hard disk drives to cloud. Users can then access
these hard drives on their Android Smartphones and Tablet computers using Pogoplug
8
cloud app. Pogoplug cloud app lacks certain features such as video streaming, automatic
file sync, photo slide show, and e-Radio.
2.2 Cloud Fundamentals
Cloud is the term used to describe servers connected to internet such that client
applications can interact with the servers and storage as long as internet connectivity can
be guaranteed [8].
Perosnal media cloud refers to a small server in a home or small business network that
can be accessed over the Internet. Designed for sharing photos and videos, personal
clouds enable viewing and streaming from any Internet-connected personal computer and
from Android smartphones [17].
Typical cloud configuration is shown in Figure 1. As shown, a cloud system consists of a
server connected to the internet via high speed link. The server may also be connected to
a mass storage system, such as a hard drive. A client such as a smartphone or any device
capable of connecting to internet can then communicate with the server [9]. In this
configuration, the server may provide either computing services or storage services or a
combination of both. Present project requires the server to provide storage and media
streaming services. Sometimes user can connect their own hard disk drives to the server
to form personal media cloud systems.
9
STORAGE
SERVER
Cloud
CLIENT
Figure 1: Typical cloud configuration
Cloud systems are characterized with 4 properties [9, 16]:
1.
Consistency: Ability of a computer-related hardware or software component
to consistently perform according to its specifications
10
2.
Availability: Ability of the system to perform work when it is expected to
perform work
3.
Partition Tolerance: Ability of the system to perform in the event of arbitrary
message loss or failure of part of the system
4.
Response Time: Time taken to complete requested operation
With these criteria in mind, a search for suitable hardware devices was conducted. A
number of devices were studied, including,

Iomega iConnect Wireless Data Station

Verbatim MediaShare Mini Home Network Storage

Seagate FreeAgent GoFlex Net Media Sharing Device

Western Digital My Book Live Personal Cloud Storage Device

Cirago Network USB Storage Link

Pogoplug
The device named pogoplug was selected, mainly due to the open source software
components and ability to interface with third party software [10].
Pogoplug is a multimedia sharing device from CloudEngines that acts as a server
connecting to any external hard drive using USB ports. Typical cloud storage setup using
pogoplug is shown in Figure 2 [11]. Once the hard drive connection over USB port is
setup, the content on hard driver can be accessed and shared over the internet. Pogoplug
works across multiple platforms and allows streaming videos, music and photos without
any monthly fees [10]. Pogoplug specifications are indicated in Table 1 [12].
11
Figure 2: Cloud storage setup using Pogoplug
Parameter
Specification
Power Requirements
100-240V, 50-60Hz
Hard drive
USB 2.0
connection
File System Formats
NTFS, FAT32, Mac OS Extended Journaled and nonJournaled (HFS+), EXT-2/EXT-3
Network Connection
Gigabit Ethernet
Operating Systems
MS Windows XP, Vista, Windows 7, Mac OSX 10.5 and
above (Intel and PowerPC) 32bit kernel only, Linux
Web Browsers
Safari, FireFox 3, IE 7, IE 8, Google Chrome
Web APIs
Javascript, Java, PHP, .NET, C++
Table 3: Pogoplug Specifications
12
2.3 Cloud APIs
As mentioned in earlier section, primary reason we selected Pogoplug device to
implement cloud storage is because the device is based on open architecture. Internal
architecture of Pogoplug device is shown in Figure 3. As shown, Pogoplug device is a
Linux machine based on ARM compatible processor [12].
POGOPLUG API
LINUX OS
HARDWARE ABSTRACTION AND DRIVERS
NETWORK CONTROLLER
ARM CPU
Gigabit Ethernet
HDD/USB CONTROLLER
USB ports for HDDs
Figure 3: Architecture of Pogoplug device
13
All Pogoplug API methods support HTTP (and HTTPS) protocol transport mechanisms.
The API has been designed to transparently support both REST style and SOAP style
HTTP calling conventions. All responses to API call requests are either raw data
responses or structured responses depending on the API call in question. Structured
responses are provided in either SOAP, Simple XML, or JSON format depending on the
arguments used to invoke the API call [13].
All API method calls are supported through a base URL such as:
http://service.pogoplug.com/svc/api
Invoking methods are performed with URLs constructed by the following pattern:
http://service.pogoplug.com/svc/api[/format][/methodName]
Where format is optional response format (e.g. soap, xml, json) and methodName is the
name of the method to be invoked. As an example, invoking the method getVersion
would be performed on any of the following URLs:
http://service.pogoplug.com/svc/api/getVersion
http://service.pogoplug.com/svc/api/xml/getVersion
http://service.pogoplug.com/svc/api/json/getVersion
http://service.pogoplug.com/svc/api/soap/getVersion
The argument calling convention is implied by the HTTP request type. An HTTP GET
request to the URL will imply a REST style call with arguments passed on the query
string in standard browser form query string encoding. Thus, for example, invoking
method loginUser can be performed with a REST style call by performing an HTTP GET
on the following URL:
14
http://service.pogoplug.com/svc/api/[email protected]&p
assword=test
Similarly, an HTTP POST request to the URL will imply a SOAP style call with
arguments encoded inside a SOAP XML envelope passed as the request body of the
HTTP request.
The response format is implied based on the calling convention or specified specifically
in the URL. The implied response for REST style requests is JSON, and the implied
response for SOAP style requests is SOAP.
Exceptions can be returned from any API call rather than the structured response that was
expected. Exceptions will always be of the same form and encode some level of useful
information for converting to a user presentation error message.
Exceptions will be returned with HTTP 500 level response codes in the HTTP header.
2.4 Android Apps
Android applications are written in the Java programming language [14]. The Android
SDK tools compile the code—along with any data and resource files—into an Android
package, an archive file with an .apk suffix. All the code in a single .apk file is
considered to be one application and is the file that Android-powered devices use to
install the application.
Once installed on a device, each Android application lives in its own security sandbox:

The Android operating system is a multi-user Linux system in which each
application is a different user.
15

By default, the system assigns each application a unique Linux user ID (the ID is
used only by the system and is unknown to the application). The system sets
permissions for all the files in an application so that only the user ID assigned to
that application can access them.

Each process has its own virtual machine (VM), so an application's code runs in
isolation from other applications.

By default, every application runs in its own Linux process. Android starts the
process when any of the application's components need to be executed, then shuts
down the process when it's no longer needed or when the system must recover
memory for other applications.
In this way, the Android system implements the principle of least privilege. That is, each
application, by default, has access only to the components that it requires to do its work
and no more. This creates a very secure environment in which an application cannot
access parts of the system for which it is not given permission.
However, there are ways for an application to share data with other applications and for
an application to access system services:
It's possible to arrange for two applications to share the same Linux user ID, in which
case they are able to access each other's files. To conserve system resources, applications
with the same user ID can also arrange to run in the same Linux process and share the
same VM (the applications must also be signed with the same certificate).
16
An application can request permission to access device data such as the user's contacts,
SMS messages, the mountable storage (SD card), camera, Bluetooth, and more. All
application permissions must be granted by the user at install time.
A unique aspect of the Android system design is that any application can start another
application’s component [15]. For example, if you want the user to capture a photo with
the device camera, there's probably another application that does that and your
application can use it, instead of developing an activity to capture a photo yourself. You
don't need to incorporate or even link to the code from the camera application. Instead,
you can simply start the activity in the camera application that captures a photo. When
complete, the photo is even returned to your application so you can use it. To the user, it
seems as if the camera is actually a part of your application.
When the system starts a component, it starts the process for that application (if it's not
already running) and instantiates the classes needed for the component. For example, if
your application starts the activity in the camera application that captures a photo, that
activity runs in the process that belongs to the camera application, not in your
application's process. Therefore, unlike applications on most other systems, Android
applications don't have a single entry point (there's no main() function, for example).
Because the system runs each application in a separate process with file permissions that
restrict access to other applications, your application cannot directly activate a component
from another application. The Android system, however, can. So, to activate a component
17
in another application, you must deliver a message to the system that specifies your intent
to start a particular component. The system then activates the component for you.
2.5 Android application components
Application components are the essential building blocks of an Android application [15].
Each component is a different point through which the system can enter your application.
Not all components are actual entry points for the user and some depend on each other,
but each one exists as its own entity and plays a specific role—each one is a unique
building block that helps define your application's overall behavior.
There are four different types of application components. Each type serves a distinct
purpose and has a distinct lifecycle that defines how the component is created and
destroyed.
2.5.1
Activities
An activity represents a single screen with a user interface. For example, an email
application might have one activity that shows a list of new emails, another activity to
compose an email, and another activity for reading emails. Although the activities work
together to form a cohesive user experience in the email application, each one is
independent of the others. As such, a different application can start any one of these
activities (if the email application allows it). For example, a camera application can start
18
the activity in the email application that composes new mail, in order for the user to share
a picture.
An activity is implemented as a subclass of Activity and you can learn more about it in
the Activities developer guide.
2.5.2
Services
A service is a component that runs in the background to perform long-running operations
or to perform work for remote processes. A service does not provide a user interface. For
example, a service might play music in the background while the user is in a different
application, or it might fetch data over the network without blocking user interaction with
an activity. Another component, such as an activity, can start the service and let it run or
bind to it in order to interact with it.
A service is implemented as a subclass of Service.
2.5.3
Content providers
A content provider manages a shared set of application data. You can store the data in the
file system, an SQLite database, on the web, or any other persistent storage location your
application can access. Through the content provider, other applications can query or
even modify the data (if the content provider allows it). For example, the Android system
provides a content provider that manages the user's contact information. As such, any
19
application with the proper permissions can query part of the content provider (such as
ContactsContract.Data) to read and write information about a particular person.
Content providers are also useful for reading and writing data that is private to your
application and not shared. For example, the Note Pad sample application uses a content
provider to save notes.
A content provider is implemented as a subclass of ContentProvider and must implement
a standard set of APIs that enable other applications to perform transactions. For more
information, see the Content Providers developer guide.
2.5.4
Broadcast receivers
A broadcast receiver is a component that responds to system-wide broadcast
announcements. Many broadcasts originate from the system—for example, a broadcast
announcing that the screen has turned off, the battery is low, or a picture was captured.
Applications can also initiate broadcasts—for example, to let other applications know
that some data has been downloaded to the device and is available for them to use.
Although broadcast receivers don't display a user interface, they may create a status bar
notification to alert the user when a broadcast event occurs. More commonly, though, a
broadcast receiver is just a "gateway" to other components and is intended to do a very
minimal amount of work. For instance, it might initiate a service to perform some work
based on the event.
20
A broadcast receiver is implemented as a subclass of BroadcastReceiver and each
broadcast is delivered as an Intent object. For more information, see the
BroadcastReceiver class.
21
Chapter 3
ARCHITECTURE AND TECHNOLOGY
Chapter 1 and Chapter 2 provided background information about Media player app. This
chapter provides detailed information about architecture and design of the Media player
app.
3.1 Basic Architecture of Media Player app
As mentioned in Chapter 2, Media player app is designed for Android phones. Like any
cloud computing application, Media player app uses client-server model. Figure 4 shows
the basic architecture of the Media player app along with cloud storage. As shown in the
figure, cloud based Media player consists of:

Application: User interacts with cloud based Media player using the application.
Application is responsible for accepting user inputs and reacting to user’s input.
Application interacts with Androind OS via the Android APIs.

Android APIs: Media player app interacts with Android phone OS using
Android APIs. Please refer to section 4.2 for more information about Android
APIs.

Android OS: The application will use Android APIs to interact with the OS. OS
will then control the hardware to communicate with the cloud.

Cloud: Cloud is the medium that will forward the request from client to the server
that is connected to the cloud.
22

Linux OS: On the server side, incoming messages will be forwarded to the OS in
the Pogoplug controller box.

The OS will forward the requests to the HTTP server.

HTTP Server: HTTP server is crucial to making overall data transfer work.
HTTP server will resolve the incoming message and forward them the storage that
is connected to Pogoplug box.
CLIENT
SERVER
APPLICATION
POGOPLUG APIs
ANDROID APIs
HTTP SERVER
ANDROID OS
LINUX OS
Cloud
Figure 4: Architecture of Cloud Media player app
3.2 Features
Section 1.2 discussed that features supported by Cloud Media app are:
23

File browsing

Image Viewer

Audio Playback

Video Playback

Photo Slide Show

E-Radio

File upload
Also, as discussed in section 3.1, Cloud Media app needs to communicate with Pogoplug
to access the media files.
3.3 Application
Section 2.4 provided information about Android application. As explained in section 2.4,
an android application consists of activities, services, content providers, and broadcast
receivers. A typical app may or may not use all these components. Cloud Media player
app mostly consists of activities. Activities are classes that must extend the Activity
base class and must implement onCreate method. Figure 5 shows various activities
required for Cloud Media player app. Figure 5 also shows how various activities interact
with each other in the application.
24
LoginScreenActivity
RadioScreenActivity
UserScreenActivity
SlideShowActivity
FileUploaderActivity
FileScreenActivity
ImageViewerActivity
AudioPlayerActivity
VideoPlayerActivity
Figure 5: Control flow in Cloud Media player app
As shown in the figure, LoginScreenActivity is the class that is instantiated when the
application starts. When user login is successful, LoginScreenActivity will start
UserScreenActivity. UserScreenActivity will display the main screen. Next, based on
user
input
UserScreenActivity
will
start
any
one
of
FileScreenActivity,
FileUploaderActivity, VideoPlayerActivity, AudioPlayerActivity, ImageViewerActivity,
RadioPlayerActivity, and SlideShowActivity. Each of these activities will present their
own screens to the user and take appropriate actions. More details about each of the
activity classes are provided in section 4.3.
25
Chapter 4
IMPLEMENTATION DETAILS
This chapter discusses the implementation details such as Android API used, APIs used
to interact with the cloud, and structure in which the application is developed.
4.1 Media cloud
The Pogoplug device is the cloud that stores all the media files and the application uses
Pogoplug APIs to interact with the cloud. Pogoplug supports APIs using standard HTTP
GET/PUT commands. The main features provided by the cloud are the storage of the
media files and easy and structured access to this stored data.
The structured Pogoplug APIs provide object oriented API access to different object
classes within the system [13]. Major classes in the APIs are
1. User
This object represents all the details of the user. These details include the user id,
screen name, primary email address, list of registered email addresses for the user
and a field containing the details if the email id is validated or not.
2. Service
This object contains device id that owns the service, service id, service class, type
of access to this service, user’s name for the service, version string of the service,
api url to use when using the service, on line status.
26
3. Device
Device object consists of details such as device id, device name, version string,
flags about the device, user id of the owner, list of services representing services
on this device and user object representing the owner of this device.
4. File
File object represents the file stored on the cloud. It consists of file id, namespace
id, parent id (file id of the parent), user id of the owner that owns this file, file
type, name, mime type of the primary stream attached to this file, file size,
creation date of the file, modification date, thumbnail and preview. Thumbnail
and preview are the file ids of the extra stream that represents thumbnail and
preview of the file respectively. General file types are 0-Normal file, 1-Directory,
2-Extra stream and 3-Symbolic link.
The main Pogoplug APIs [13] used for implementing are given in the table below:
27
METHOD
INPUT
OUTPUT
DESCRIPTION
loginUser
Email id,
Validation token,
Authenticates a user by email and
Password
user object
password and returns a validation
token.
listServices: Validation
Sequence of
Lists all the services available to a
service objects,
user exposed by a specific device
Validation
Page offset,
Search an entire service based on
token,
Count, sequence
some criteria.
search
of file objects
Token,
device Id
searchFiles:
criteria
listFiles:
Validation
Page offset,
List the contents of some
token,
Count, sequence
directory, namespace, or service in
device Id,
of file objects
a paginated fashion.
File object
Creates a new child file or
service Id
createFile
Validation
token,
directory inside a parent directory.
device Id,
The newly created file will be
service Id,
empty, and data can be written to
file name
using the data stream API.
Table 4: Pogoplug APIs
28
4.2 Android APIs
Section 3.1 described high level architecture of the Cloud Media player app. Various
classes described in section 3.1 have to interact with Android platform in order to do
things like displaying content on the screen, accepting user input, playing audio/video
etc. This is achieved using Android APIs [14].
The Android platform provides a framework API that applications can use to interact
with the underlying Android system. The framework API consists of:

A core set of packages and classes

A set of XML elements and attributes for declaring a manifest file

A set of XML elements and attributes for declaring and accessing resources

A set of Intents

A set of permissions that applications can request, as well as permission
enforcements included in the system
29
API Method
Input
Output
Description
setContentView
Layout
None
Sets view to indicated
layout
getIntent
None
intent
Returns intent
Intent.getStringExtra
None
Argument
Returns argument
String
string
Widget ID
Returns widget ID for
findViewById
widget
specified widget
MediaPlayer.setDataSource
URL
None
Sets specified URL as
media data source
MediaPlayer.prepare
None
None
Prepare data source
for media streaming
startActivity
Activity
JSONArray.getJSONObject String
None
Start specified activity
JSONObject
Get JSONObject that
matches the specified
string
BitmapFactory.decode
URI
Bitmap
Decode image file
specified by URI and
return bitmap
Table 5: Android APIs
30
4.3 Android client
The main features provided by the Media Cloud App are streaming the audio and video
files from the cloud, displaying the images stored on the cloud, slideshow of the stored
images, and e-radio. The app also uses file management for all these files. The main
functionalities of the android client are as given below:
1. Provide an UI for the user to log in to access files on the cloud.
2. User interface for showing the files and folders stored on the cloud.
3. Music player for playing audio files and for radio
4. Image viewer for playing the slide show and for displaying the image files
5. Video player for streaming video files
6. UI for uploading the files from the android device to the cloud
4.3.1
Login Screen
Source Files: LoginScreenActivity.java, login.xml
The screenshot in Figure 6 shows the user interface for log in. User needs to provide an
email id and password to access the storage. The Pogoplug API loginUser is used to
authenticate the user. The user has access to all the stored files once he signs in the
application. Appropriate error messages are given in case the log in is unsuccessful.
31
Figure 6: Login Screen
4.3.2
Main Screen
Source Files: UserScreenActivity.java, userscreen.xml
Once the user login is successful, main screen of Cloud Media app is presented to the
user. Figure 7 shows the main screen of Cloud Media app. As shown, this figure allows
user to select one of various functions supported by the app, such as image viewer, audio
player etc. Appropriate handlers are called to take action depending on the user selection.
The Pogoplug API ―listServices‖ is used before main screen is presented to the user.
32
Figure 7: Main Screen
4.3.3
File View
Source Files: FileScreenActivity.java, filescreen.xml
Figure 8 shows the file and directory listing. This screen is displayed when user selects
File Viewer in the main screen. Appropriate Activities are called to take action depending
on the user selection. The Pogoplug API listServices and listFiles are mainly used to
show the files/directory listing.
33
Figure 8: File view
4.3.4
Music player
Source Files: AudioPlayerActivity.java, RadioScreenActivity.java, audioplayer.xml,
radio.xml
Figure 9 shows the audio/radio player for playing the music files. To play audio, the user
can access the Music folder and select the file to play. Alternatively, user can click on
Radio and songs from the Music folder will be played in a random order.
34
The player has different controls such as pause, next track, previous track, shuffle, repeat,
stop etc. In case of Radio only stop, pause and next track buttons are provided.
(A)
(B)
Figure 9: (A) - Audio player screen, (B) – Radio player screen
4.3.5
Image Viewer
Source Files: ImageViewerActivity.java, SlideShowActivity.java, imageviewer.xml,
slideshow.xml
Figure 10 is the screen shot for the image viewer. To view the images user can select
from Image folder or Slide show option. If the user choose to use the image folder, he/she
needs to select each file manually, whereas in slide show mode, all the images are
35
displayed at small interval. The images are scaled before displaying, to fit the android
device.
(A)
(B)
Figure 10: (A) - Image diaglog box, (B) – Loaded image
4.3.6
Video player
Source Files: VideoPlayerActivity.java, videoplayer.xml
Android API has video view control to enable video streaming. Path of the video file is
set and media controller is set for this videoview. Video streaming starts once this video
view is brought into focus.
36
4.3.7
File Uploading
Source Files: FileUploaderActivity.java, fileuploader.xml
The user has the ability to upload file from the android device to the cloud. This
functionality makes use of Pogoplug API createFile to achieve the goal. A dialog box is
used to indicate file upload progress.
Figure 11: File uploading
37
Chapter 5
PERFORMANCE EVALUATION
The main advantage of Media Cloud app is in the ease of use with which users can access
data stored in cloud. As discussed in Chapter 2, performance of any cloud computing
system is characterized by [9, 16]:
1.
Consistency: Ability of a computer-related hardware or software component
to consistently perform according to its specifications
2.
Availability: Ability of the system to perform work when it is expected to
perform work
3.
Partition Tolerance: Ability of the system to perform in the event of arbitrary
message loss or failure of part of the system
4.
Response Time: Time taken to complete requested operation
Media streaming is highly sensitive to response time, resulting in noticeable glitches,
interruptions during playback if response time is longer than can be tolerated. Response
time is a function of network connection speed, which itself is dependent upon the
connection technology and Radio signal strength. Following data was collected to
evaluate performance of the Media Cloud app.
As shown in the table 6, good connection speed of at least 3G or better is required to
provide good quality audio/video playback. Thus, we can conclude that personal media
cloud application exhibits good consistency and availability as long as high speed internet
connectivity (better than 3G speeds) is guaranteed.
38
CONNECTION
BW LIMIT
MEDIA
OBSERVATION
EDGE
237 Kb/s
Audio/Video
Jittery audio, no video
3G
384 Kb/s
Audio
Good quality MP3 playback
3G
384Kb/s
Video SD
Minimal interruptions
3G
384Kb/s
Video HD
Jittery video
4G
100Mb/s
Audio/Video
Good quality Audio/Video
Wi-Fi (G)
54Mb/s
Audio/Video
Good quality Audio/Video
WiFi (N)
150Mb/s
Audio/Video
Good quality Audio/Video
Table 6: Media Cloud app performance evaluation
Other aspect of performance is usability. Being a personal cloud, this system does not
face the issues associated with multi-user commercial cloud systems such as limited
space, recurring costs, limited content etc.
39
Chapter 6
CONCLUSION AND FUTURE WORK
The personal media cloud player application provides a low cost solution for personal
media cloud. Moreover, the cost is not related to storage capacity and does not require
any monthly expenses, unlike commercial media clouds such as iCloud and Amazon
cloud.
The app provides simple user interface and features like video streaming, photo
slideshow, e-Radio, file upload etc. that are not found in many of the cloud applications
available.
Based on performance studies we conclude that the personal media cloud application
exhibits good consistency and availability characteristics as long as high speed internet
connectivity (better than 3G speeds) is avaialble.
6.1 Future work
6.1.1
Playlist Management
This feature will allow users to specify playlist of media files to be played.
6.1.2
File Sharing
Users will specify email IDs to share the files with and the app will setup the share.
40
6.1.3
Folder sync up
User will specify the folders that need to be sync’ed up with cloud. User will also specify
how frequently the folders should be sync’ed up. Based on this information, the app will
periodically sync folders with the cloud.
41
APPENDIX
Source Code
********************************
AudioPlayerActivity.java
********************************
package com.android.cloudplayer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import com.android.cloudplayer.ImageViewerActivity.BGThread;
import com.android.cloudplayer.ImageViewerActivity.MyRunnable;
import android.R.drawable;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;
/**
*
* @author Prajakta Sarurkar
* This activity creates an UI for audio playback on the files.
*/
public class AudioPlayerActivity extends Activity
{
private static MediaPlayer mp;
private String devID, svcID, mediaType;
private String valToken, userID;
private String fileReq;
private boolean pauseAction = false;
42
private static boolean playAction = false;
private boolean shuffleAction = false;
private boolean repeatAction = false;
private boolean filesDone = true;
private String [] fileIDArry;
private String [] fileNameArry;
private int fileIndex;
private int fileNum;
private int fileCnt = 0;
private Handler handler;
private Thread audioThread;
private ProgressDialog prgDialog;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.audioplayer);
Intent i = getIntent();
userID = i.getStringExtra("userID");
valToken = i.getStringExtra("valToken");
devID = i.getStringExtra("devID");
svcID = i.getStringExtra("svcID");
fileIndex = i.getIntExtra("fileIndex", 0);
fileNum = i.getIntExtra("fileNum", 1);
fileIDArry = new String[fileNum];
fileNameArry = new String[fileNum];
fileIDArry = i.getStringArrayExtra("fileID");
fileNameArry = i.getStringArrayExtra("fileName");
Log.i("AudioPlayer", "Entry");
Log.i("AudioPlayer", "userID "+userID);
Log.i("AudioPlayer", "valToken "+valToken);
Log.i("AudioPlayer", "devID "+devID);
Log.i("AudioPlayer", "svcID "+svcID);
Log.i("AudioPlayer", "fileID "+fileIDArry[0]);
Log.i("AudioPlayer", "fileNum "+fileNum);
Log.i("AudioPlayer", "fileIndex "+fileIndex);
Button btnPlay = (Button) findViewById(R.id.btnPlay);
Button btnStop = (Button) findViewById(R.id.btnStop);
Button btnPause = (Button) findViewById(R.id.btnPause);
Button btnNext = (Button) findViewById(R.id.btnNext);
Button btnPrev = (Button) findViewById(R.id.btnPrev);
Button btnRepeat = (Button) findViewById(R.id.btnRepeat);
Button btnShuffle = (Button) findViewById(R.id.btnShuffle);
43
if (playAction)
{
mp.stop();
mp.release();
playAction = false;
}
if (fileNum == 1)
filesDone = true;
mp = new MediaPlayer();
Log.i("playAudio", "fileIndex " + fileIndex + "Length " + fileIDArry.length);
Log.i("playAudio", "fileID " + fileIDArry[fileIndex]);
Log.i("AudioPlayer", "To play Audio");
// Create a handler to update the UI
handler = new Handler();
audioThread = new BGThread();
audioThread.start();
Log.i("Audio Thread ", audioThread.toString());
if (audioThread != null && audioThread.isAlive()) {
prgDialog = ProgressDialog.show(this, "Audio Player", "Loading audio");
}
//playAudio();
mp.setOnCompletionListener(new OnCompletionListener()
{
@Override
public void onCompletion(MediaPlayer mp)
{
if (filesDone)
{
mp.release();
playAction = false;
finish();
}
else
{
getNextPlayIndex();
playAudio();
}
}
});
btnNext.setOnTouchListener(new OnTouchListener ()
44
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("NextB", "playAction "+playAction);
if (event.getAction() == MotionEvent.ACTION_DOWN && playAction)
{
getNextIndex();
playAudio();
}
return true;
}
});
btnPrev.setOnTouchListener(new OnTouchListener ()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("PrevB", "playAction "+playAction);
if (event.getAction() == MotionEvent.ACTION_DOWN && playAction)
{
getPrevIndex();
playAudio();
}
return true;
}
});
//
//
//
btnRepeat.setOnTouchListener(new OnTouchListener ()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("RepeatB", "playAction "+playAction);
if (event.getAction() == MotionEvent.ACTION_DOWN && playAction)
{
repeatAction = !repeatAction;
if (repeatAction)
{
filesDone = false;
Log.i("Changing color ", "Magenta");
btnRepeat.setEnabled(true);
}
else
btnRepeat.setEnabled(false);
}
return true;
}
45
});
btnShuffle.setOnTouchListener(new OnTouchListener ()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("ShuffleB", "playAction "+playAction);
if (event.getAction() == MotionEvent.ACTION_DOWN && playAction)
{
shuffleAction = !shuffleAction;
}
return true;
}
});
btnPause.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("PauseB", "playAction "+playAction);
if (event.getAction() == MotionEvent.ACTION_DOWN && playAction)
{
pauseAction = !pauseAction;
if (pauseAction)
mp.pause();
else
mp.start();
}
return true;
}
});
btnStop.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("StopB", "playAction "+playAction);
if (event.getAction() == MotionEvent.ACTION_DOWN && playAction)
{
mp.release();
playAction = false;
finish();
}
return true;
}
});
btnPlay.setOnTouchListener(new OnTouchListener()
46
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("PlayB", "playAction "+playAction);
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
if (!playAction)
{
mp = new MediaPlayer();
playAudio();
}
else if (playAction & pauseAction)
{
mp.start();
pauseAction = false;
}
}
return true;
}
});
}
/**
* Start streaming Audio file from requested location
*/
private void playAudio ()
{
Log.i("playAudio", "fileIndex " + fileIndex + "Length ");
Log.i("playAudio", "fileID " + fileIDArry[fileIndex]);
try
{
mp.reset();
mp.setDataSource("http://service.pogoplug.com/svc/files/"+valToken+"/"+devID+
"/"+svcID+"/"+fileIDArry[fileIndex]+"/strm");
mp.prepare();
mp.start();
playAction = true;
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (IllegalStateException e)
{
e.printStackTrace();
}
catch (IOException e)
47
{
e.printStackTrace();
}
}
/**
* Get Previous file
*/
private void getPrevIndex ()
{
if (fileNum > 1)
{
if (shuffleAction)
fileIndex = (((int) (Math.random()*1000)) % fileNum);
else
fileIndex = (fileIndex - 1) % fileNum;
}
}
/**
* Get Next file
*/
private void getNextPlayIndex ()
{
if (fileNum > 1)
{
if (shuffleAction)
fileIndex = (((int) (Math.random()*1000)) % fileNum);
else
fileIndex = (fileIndex + 1) % fileNum;
}
if (!repeatAction)
fileCnt ++;
if (fileCnt == fileNum)
filesDone = true;
}
private void getNextIndex ()
{
if (fileNum > 1)
{
if (shuffleAction)
fileIndex = (((int) (Math.random()*1000)) % fileNum);
else
fileIndex = (fileIndex + 1) % fileNum;
}
48
}
/**
* Thread for diaglog
*/
public class BGThread extends Thread
{
@Override
public void run()
{
playAudio();
handler.post(new MyRunnable());
}
}
public class MyRunnable implements Runnable
{
public void run()
{
//imageView.setImageBitmap(imgBitmap);
prgDialog.dismiss();
}
}
}
********************************
FileScreenActivity.java
********************************
package com.android.cloudplayer;
import org.json.JSONArray;
import android.app.Activity;
import android.os.Bundle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
49
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.ArrayAdapter;
import android.widget.Toast;
/**
*
* @author Prajakta Sarurkar
* This activity creates an UI for displaying all the directories and files.
* Appropriate action is taken in case the user clicks on a directory or file
* depending on the type of the file.
*/
public class FileScreenActivity extends Activity
{
//private JSONArray svcArr;
private String devID, svcID, parentID, sortCrit;
private String valToken, userID;
private JSONArray fileArr;
private String fileReq;
private SimpleAdapter adapter;
private ListView fileListView;
private ArrayList <Map<String,String>> fileList;
private static String searchCrit;
private String [] fileID;
private String [] fileName;
private int fileSize;
/** Called when the activity is first created. */
@Override
50
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.filescreen);
TextView txtUserID = (TextView) findViewById(R.id.txtUserID);
Intent i = getIntent();
userID = i.getStringExtra("userID");
Log.i("User ID in FileScreen", userID);
txtUserID.setText(userID);
valToken = i.getStringExtra("valToken");
devID = i.getStringExtra("devID");
svcID = i.getStringExtra("svcID");
parentID = i.getStringExtra("parentID");
sortCrit = i.getStringExtra("sortcrit");
searchCrit = i.getStringExtra("searchCrit");
try
{
if(!searchCrit.equals(""))
fileReq =
"http://service.pogoplug.com/svc/api/json/searchFiles?searchcrit=mediatype+=+" +searchCrit+
"&valtoken="+valToken+"&serviceid="+svcID +
"&deviceid="+devID;
else if(parentID.equals(""))
fileReq = "http://service.pogoplug.com/svc/api/json/listFiles?sortcrit=" +sortCrit+
"&valtoken="+valToken+"&deviceid="+devID+"&serviceid="+svcID;
else
fileReq = "http://service.pogoplug.com/svc/api/json/listFiles?sortcrit=" +sortCrit+
"&valtoken="+valToken+"&deviceid="+devID+"&serviceid="+svcID
+"&sortcrit=+type&parentid="+parentID;
Log.i("fileReq", fileReq);
String fileResp = getHTTPResponse(fileReq);
Log.i("fileResp", fileResp.toString());
JSONObject fileObj = new JSONObject (fileResp);
Log.i("Back from buildData", "BuildData");
fileArr = fileObj.optJSONArray("files");
fileList = buildData();
Log.i("Back from buildData","size "+fileList.size());
fileListView = (ListView) findViewById(R.id.listView1);
String[] from = { "fileName", "fileType" };
int[] to = { android.R.id.text1, android.R.id.text2 };
adapter = new SimpleAdapter(this, fileList,
android.R.layout.simple_list_item_2, from, to);
fileListView.setAdapter(adapter);
51
fileListView.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id)
{
try
{
JSONObject jObj = fileArr.getJSONObject(pos);
String parentID;
if (jObj.getString("type").equals("1"))
{
parentID = jObj.getString("fileid");
fileReq = "http://service.pogoplug.com/svc/api/json/listFiles?sortcrit="
+sortCrit+
"&valtoken="+valToken+"&deviceid="+devID+"&serviceid="+svcID
+"&sortcrit=+type&parentid="+parentID;
Log.i("fileReq", fileReq);
String fileResp = getHTTPResponse(fileReq);
Log.i("fileResp", fileResp.toString());
JSONObject fileObj = new JSONObject (fileResp);
clrData(fileArr.length());
adapter.notifyDataSetChanged();
//Log.i("Back from buildData", "BuildData");
fileArr = fileObj.optJSONArray("files");
updateData();
adapter.notifyDataSetChanged();
}
else if (jObj.getString("type").equals("0"))
{
fileID = new String[fileArr.length()];
fileName = new String[fileArr.length()];
int fileIndex = 0;
int fileNum = 1;
fileID[0] = jObj.getString("fileid");
fileName[0] = jObj.getString("filename");
fileSize = jObj.getInt("size");
Log.i("Mime Type",
jObj.getString("mimetype"));
if
(jObj.getString("mimetype").equals("audio/mpeg"))
{
if (searchCrit.equals("audio"))
{
fileNum = fileArr.length();
Log.i("toAudio", "Crit equals
Audio");
52
for (int index = 0;index <
fileNum;index ++)
{
fileID[index] =
fileArr.getJSONObject(index).getString("fileid");
fileName[index] =
fileArr.getJSONObject(index).getString("filename");
if
(fileID[index].equals(jObj.getString("fileid")))
fileIndex = index;
}
}
else
{
Log.i("toAudio", "Crit not equals
Audio");
fileID[0] = jObj.getString("fileid");
//fileIndex = 0;
}
Log.i("FileChk", "Selected
"+jObj.getString("filename"));
Log.i("FileChk", "Launching audio player");
Intent audioScreen = new
Intent(getApplicationContext(), AudioPlayerActivity.class);
//Sending data to another Activity
audioScreen.putExtra("userID", userID);
audioScreen.putExtra("valToken", valToken);
audioScreen.putExtra("devID", devID);
audioScreen.putExtra("svcID", svcID);
audioScreen.putExtra("fileID", fileID);
audioScreen.putExtra("fileName", fileName);
audioScreen.putExtra("fileNum", fileNum);
audioScreen.putExtra("fileIndex", fileIndex);
startActivity(audioScreen);
}
else if
(jObj.getString("mimetype").equals("video/mp4"))
{
Intent videoScreen = new
Intent(getApplicationContext(), VideoPlayerActivity.class);
//Sending data to another Activity
videoScreen.putExtra("userID", userID);
videoScreen.putExtra("valToken",
valToken);
videoScreen.putExtra("devID", devID);
videoScreen.putExtra("svcID", svcID);
videoScreen.putExtra("fileID", fileID);
53
videoScreen.putExtra("fileName",
fileName);
videoScreen.putExtra("fileNum", fileNum);
videoScreen.putExtra("fileIndex",
fileIndex);
startActivity(videoScreen);
}
else if
((jObj.getString("mimetype").equals("image/jpeg")) || (jObj.getString("mimetype").equals("image/png")) ||
(jObj.getString("mimetype").equals("image/bmp")))
{
Intent photoScreen = new
Intent(getApplicationContext(), ImageViewerActivity.class);
photoScreen.putExtra("valToken",
valToken);
photoScreen.putExtra("devID", devID);
photoScreen.putExtra("svcID", svcID);
photoScreen.putExtra("fileID", fileID[0]);
photoScreen.putExtra("fileName",
fileName[0]);
photoScreen.putExtra("fileSize", fileSize);
Log.i("fileScreen", "start ImageViewer");
startActivity(photoScreen);
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void clrData(int length) throws JSONException
{
if(fileArr != null)
{
Log.i("Inside clrData", Integer.toString(fileArr.length()));
String [] fileNameArr = new String[fileArr.length()];
String [] fileType = new String [fileArr.length()];
54
String fType;
for (int index = 0;index < length;index ++)
{
fileNameArr[index] = "";
fileType[index] = "";
fileList.set(index, putData("", ""));
}
}
}
private void updateData() throws JSONException
{
if(fileArr != null)
{
Log.i("Inside updateData", Integer.toString(fileArr.length()));
String [] fileNameArr = new String[fileArr.length()];
String [] fileType = new String [fileArr.length()];
String fType;
for (int index = 0;index < fileArr.length();index ++)
{
fileNameArr[index] =
fileArr.getJSONObject(index).getString("filename");
fType = fileArr.getJSONObject(index).getString("type");
Log.i("fType", fType);
if (fType.equals("0"))
{
fileType[index] =
fileArr.getJSONObject(index).getString("mimetype");
}
else if (fType.equals("1"))
fileType[index] = "Directory";
{
}
Log.i("fileType", fileType[index]);
fileList.set(index, putData(fileNameArr[index],fileType[index]));
//list.add(putData(fileNameArr[index],fileType[index]));
}
}
else
fileList.set(0, putData("No files to display", ""));
Log.i("file List", fileList.toString());
}
/**
*
* @return ArrayList File List
55
* @throws JSONException
*/
private ArrayList<Map<String, String>> buildData() throws JSONException
{
ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
if(fileArr != null)
{
String [] fileNameArr = new String[fileArr.length()];
String [] fileType = new String [fileArr.length()];
String fType;
for (int index = 0;index < fileArr.length();index ++)
{
fileNameArr[index] =
fileArr.getJSONObject(index).getString("filename");
fType = fileArr.getJSONObject(index).getString("type");
Log.i("fType", fType);
if (fType.equals("0"))
{
fileType[index] =
fileArr.getJSONObject(index).getString("mimetype");
}
else if (fType.equals("1"))
fileType[index] = "Directory";
{
}
Log.i("fileType", fileType[index]);
list.add(putData(fileNameArr[index],fileType[index]));
}
}
else
list.add(putData("No files to display", ""));
return list;
}
/**
*
* @param String name
* @param String type
* @return HashMap of the files with key value pair of File name and File type
*/
private HashMap<String, String> putData(String name, String type)
{
HashMap<String, String> item = new HashMap<String, String>();
item.put("fileName", name);
item.put("fileType", type);
return item;
}
56
/**
*
* @param String HTTP Request
* @return String HTTP Response
*/
@SuppressWarnings("finally")
private String getHTTPResponse (String httpReq)
{
String httpResponse = null;
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(httpReq);
try
{
Log.i("In HTTP response", httpReq);
HttpResponse response = client.execute(httpGet);
Log.i("response", response.toString());
StatusLine statusLine = response.getStatusLine();
Log.i("In HTTP response", statusLine.toString());
int statusCode = statusLine.getStatusCode();
Log.i("In HTTP response", String.valueOf(statusCode));
if (statusCode == 200)
{
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
Log.i("Content", content.toString());
BufferedReader reader = new BufferedReader(new
InputStreamReader(content));
httpResponse = reader.readLine();
} else
{
Log.i("parseJSON", "Failed to download file");
}
} catch (ClientProtocolException e)
{
Log.i("ProtocolException", "In protocol Catch");
Toast.makeText(this, "Protocol Error", Toast.LENGTH_LONG).show();
//e.printStackTrace();
} catch (IOException e)
{
Log.i("IOException", "In IO Catch");
Toast.makeText(this, "Connection Error", Toast.LENGTH_LONG).show();
//e.printStackTrace();
}
finally
{
57
Log.i("Response Return", httpResponse);
client.getConnectionManager().shutdown();
return httpResponse;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.fileoptions, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
boolean changeFlag = false;
switch (id)
{
case R.id.name:
if (sortCrit.equals("-name"))
sortCrit = "+name";
else
sortCrit = "-name";
changeFlag = true;
break;
case R.id.type:
if (sortCrit.equals("-type"))
sortCrit = "+type";
else
sortCrit = "-type";
changeFlag = true;
break;
case R.id.date:
if (sortCrit.equals("-date"))
sortCrit = "+date";
else
sortCrit = "-date";
changeFlag = true;
break;
case R.id.size:
if (sortCrit.equals("-size"))
58
sortCrit = "+size";
else
sortCrit = "-size";
changeFlag = true;
break;
}
if (changeFlag)
{
Toast.makeText(this, sortCrit.toString(), Toast.LENGTH_SHORT).show();
try
{
fileReq = "http://service.pogoplug.com/svc/api/json/listFiles?sortcrit=" +sortCrit+
"&valtoken="+valToken+"&deviceid="+devID+"&serviceid="+svcID
+"&sortcrit=+type&parentid="+parentID;
Log.i("fileReq", fileReq);
String fileResp = getHTTPResponse(fileReq);
Log.i("fileResp", fileResp.toString());
JSONObject fileObj = new JSONObject (fileResp);
Log.i("Back from buildData", "BuildData");
fileArr = fileObj.optJSONArray("files");
updateData();
adapter.notifyDataSetChanged();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
return true;
}
}
********************************
ImageViewerActivity.java
********************************
package com.android.cloudplayer;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
59
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
/**
*
* @author Prajakta Sarurkar
* This activity creates an UI for displaying Images
*/
public class ImageViewerActivity extends Activity
{
private String devID;
private String svcID;
private String valToken;
private String fileID;
private String fileName;
private int fileSize, scaling = 1;
private ProgressDialog prgDialog;
private ImageView imageView;
private Handler handler;
private Bitmap imgBitmap;
private Thread imgThread;
@Override
public void onCreate(Bundle savedInstanceState)
{
Intent i = getIntent();
valToken = i.getStringExtra("valToken");
devID = i.getStringExtra("devID");
svcID = i.getStringExtra("svcID");
fileID = i.getStringExtra("fileID");
fileName = i.getStringExtra("fileName");
fileSize = i.getIntExtra("fileSize", 0)*10;
super.onCreate(savedInstanceState);
setContentView(R.layout.imageviewer);
TextView txt = (TextView) findViewById(R.id.textView1);
txt.setText(fileName);
// Create a handler to update the UI
60
handler = new Handler();
// get the latest imageView after restart of the application
imageView = (ImageView) findViewById(R.id.imageView1);
imgThread = new BGThread();
imgThread.start();
Log.i("Image Thread ", imgThread.toString());
if (imgThread != null && imgThread.isAlive()) {
prgDialog = ProgressDialog.show(this, "Image Viewer", "Loading image");
}
}
// Save the thread
@Override
public Object onRetainNonConfigurationInstance()
{
return imgThread;
}
// dismiss dialog if activity is destroyed
@Override
protected void onDestroy()
{
if (prgDialog != null && prgDialog.isShowing()) {
prgDialog.dismiss();
prgDialog = null;
}
super.onDestroy();
}
// Utiliy method to download image from the cloud
private Bitmap getBitmap() throws IOException
{
int refSize = 4*1024*1024;
scaling = ((int) fileSize/refSize) * 2;
if (scaling == 0)
scaling = 1;
Log.i("ImageViewer", "File Size is " + Integer.toString(fileSize) + " Scaling is " +
Integer.toString(scaling));
//scaling = 1;
Log.i(" Scaling is ", Integer.toString(scaling));
//ImageView bmImage = (ImageView)findViewById(R.id.imageView1);
BitmapFactory.Options bmOptions;
bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = scaling;
bmOptions.inPurgeable = true;
bmOptions.inInputShareable = true;
61
String imageURL = "http://service.pogoplug.com/svc/files/"+valToken+"/"+devID+
"/"+svcID+"/"+fileID+"/strm";
Log.i("fileReq", imageURL);
Bitmap bitmap = null;
HttpGet httpRequest = new HttpGet(imageURL);
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = null;
try
{
response = (HttpResponse) httpClient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);
InputStream is = bufferedHttpEntity.getContent();
bitmap = BitmapFactory.decodeStream(is, null, bmOptions);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bitmap;
}
/**
* Thread for diaglog
*/
public class BGThread extends Thread
{
@Override
public void run()
{
try
{
imgBitmap = getBitmap();
handler.post(new MyRunnable());
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
}
}
}
62
public class MyRunnable implements Runnable
{
public void run()
{
imageView.setImageBitmap(imgBitmap);
prgDialog.dismiss();
}
}
}
********************************
LoginScreenActivity.java
********************************
package com.android.cloudplayer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/**
* @author Prajakta Sarurkar
* This activity accomplishes the user login and displays appropriate messages in case of errors.
*/
public class LoginScreenActivity extends Activity {
private EditText userId;
private EditText password;
63
private String valToken;
private String userID;
private JSONObject user;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
}
/**
*
* @param view
* LoginHandler is invoked when clicked on the Sign In button.
* It forms a login request using the loginuser API, and takes an appropriate action
* depending on the HTTP response.
*/
public void loginHandler(View view)
{
try
{
userId = (EditText) findViewById(R.id.editText1);
password = (EditText) findViewById(R.id.editText2);
String emailId = userId.getText().toString().trim();
if (!(android.util.Patterns.EMAIL_ADDRESS.matcher(emailId).matches()))
Toast.makeText(this, "Please enter valid email address",
Toast.LENGTH_LONG).show();
String pwd = password.getText().toString().trim();
String loginReq =
"http://service.pogoplug.com/svc/api/loginUser?email="+emailId+"&password="+pwd;
Log.i("Request URL", loginReq);
String loginResp = getHTTPResponse(loginReq);
if (loginResp != null)
{
try
{
Log.i("JSON", "instantiate json" + loginResp);
JSONObject jsonObj = new JSONObject(loginResp);
Log.i("JSON", "Value is" + jsonObj.toString());
Log.i("JSON", "Names are" + jsonObj.names().toString());
if (jsonObj.has("valtoken"))
valToken = jsonObj.getString("valtoken");
if (jsonObj.has("user"))
64
user = jsonObj.optJSONObject("user");
if(user.has("screenname"))
userID = user.getString("screenname");
Log.i("User", "ValToken" + valToken);
Log.i("User", "User" + user.names().toString());
// Added to change the screen
Intent userScreen = new Intent(getApplicationContext(),
UserScreenActivity.class);
//Sending data to another Activity
userScreen.putExtra("userID", userID);
userScreen.putExtra("valToken", valToken);
startActivity(userScreen);
}
catch (Exception e)
{
e.printStackTrace();
}
}
else
{
Log.i("JSON", "No HTTP Response");
}
}
catch(Exception ex)
{
Log.i("Inside Catch ", ex.toString());
Toast.makeText(this, "Unable to Login", Toast.LENGTH_LONG).show();
}
}
/**
*
* @param view
* CancelHandler is invoked when clicked on the Cancel button.
*/
public void cancelHandler(View view)
{
//close the application
finish();
}
/**
*
* @param String HTTP Request
* @return String HTTP Response
65
*
*/
private String getHTTPResponse (String httpReq)
{
String httpResponse = null;
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(httpReq);
Log.i("loginHandler","getHTTPResponse()" );
try
{
Log.i("loginHandler","Inside try" );
HttpResponse response = client.execute(httpGet);
Log.i("loginHandler","after calling execute" );
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
Log.i("In HTTP response", String.valueOf(statusCode));
if (statusCode == 200)
{
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new
InputStreamReader(content));
httpResponse = reader.readLine();
}
else
{
Toast.makeText(this, "Incorrect login or password",
Toast.LENGTH_LONG).show();
Log.i("parseJSON", "Failed to download file");
}
} catch (ClientProtocolException e)
{
Log.i("ProtocolException", "In protocol Catch");
Toast.makeText(this, "Protocol Error", Toast.LENGTH_LONG).show();
} catch (IOException e)
{
Log.i("IOException", "In IO Catch");
Toast.makeText(this, "Connection Error", Toast.LENGTH_LONG).show();
}
finally
{
client.getConnectionManager().shutdown();
return httpResponse;
}
}
}
66
********************************
RadioScreenActivity.java
********************************
package com.android.cloudplayer;
import org.json.JSONArray;
import android.app.Activity;
import android.app.ProgressDialog;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
import com.android.cloudplayer.AudioPlayerActivity.BGThread;
import com.android.cloudplayer.AudioPlayerActivity.MyRunnable;
import android.content.Intent;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.TextView;
/**
* @author Prajakta Sarurkar
* This activity is used for e-Radio screen
*/
public class RadioScreenActivity extends Activity {
private String devID, svcID, searchCrit;
private String valToken;
private JSONArray fileArr;
private String fileReq;
private static MediaPlayer mp;
67
private boolean pauseAction = false;
private static boolean playAction = false;
private int fileIndex, fileNum;
private String [] fileIDArry;
private String [] fileNameArry;
private TextView txtFileName;
private Handler handler;
private Thread audioThread;
private ProgressDialog prgDialog;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.radio);
txtFileName = (TextView) findViewById(R.id.txtFileName);
Button btnPause = (Button) findViewById(R.id.btnRadPause);
Button btnNext = (Button) findViewById(R.id.btnRadNext);
Log.i("txtFileName", txtFileName.toString());
Button btnStop = (Button) findViewById(R.id.btnRadStop);
Log.i("btnNext", "printing btnNext");
Log.i("btnNext", btnNext.toString());
Intent i = getIntent();
valToken = i.getStringExtra("valToken");
devID = i.getStringExtra("devID");
svcID = i.getStringExtra("svcID");
searchCrit = i.getStringExtra("searchCrit");
Log.i("Radio", "here");
try
{
fileReq =
"http://service.pogoplug.com/svc/api/json/searchFiles?searchcrit=mediatype+=+" +searchCrit+
"&valtoken="+valToken+"&serviceid="+svcID +
"&deviceid="+devID;
Log.i("fileReq", fileReq);
String fileResp = getHTTPResponse(fileReq);
Log.i("fileResp", fileResp.toString());
JSONObject fileObj = new JSONObject (fileResp);
Log.i("Back from buildData", "BuildData");
fileArr = fileObj.optJSONArray("files");
fileIDArry = new String[fileArr.length()];
68
fileNameArry = new String[fileArr.length()];
fileNum = fileArr.length();
for (int index = 0;index < fileNum;index ++)
{
fileIDArry[index] = fileArr.getJSONObject(index).getString("fileid");
fileNameArry[index] =
fileArr.getJSONObject(index).getString("filename");
}
Log.i("FileChk", "Launching audio player");
}
catch (Exception e)
{
e.printStackTrace();
}
//
//
if (!playAction)
{
mp = new MediaPlayer();
getNextIndex();
playAudio();
playAction = true;
}
handler = new Handler();
audioThread = new BGThread();
audioThread.start();
Log.i("Audio Thread ", audioThread.toString());
if (audioThread != null && audioThread.isAlive()) {
prgDialog = ProgressDialog.show(this, "Audio Player", "Loading audio");
}
mp.setOnCompletionListener(new OnCompletionListener()
{
@Override
public void onCompletion(MediaPlayer mp)
{
getNextIndex();
playAudio();
}
});
btnNext.setOnTouchListener(new OnTouchListener ()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("NextB", "playAction ");
69
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
getNextIndex();
playAudio();
}
return true;
}
});
btnPause.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("PauseB", "playAction ");
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
pauseAction = !pauseAction;
if (pauseAction)
mp.pause();
else
mp.start();
}
return true;
}
});
btnStop.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i("StopB", "playAction ");
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
playAction = false;
mp.release();
finish();
}
return true;
}
});
}
/**
* Play requested file
*/
private void playAudio ()
{
Log.i("In playAudio", "fileIndex " + fileIndex + "Length ");
70
Log.i("In playAudio", "fileID " + fileIDArry[fileIndex]);
try
{
txtFileName.setText(" ");
txtFileName.setText(fileNameArry[fileIndex]);
mp.reset();
mp.setDataSource("http://service.pogoplug.com/svc/files/"+valToken+"/"+devID+
"/"+svcID+"/"+fileIDArry[fileIndex]+"/strm");
mp.prepare();
mp.start();
Log.i("Returning from PlayAudio", "Return");
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (IllegalStateException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
private void getNextIndex ()
{
fileIndex = (((int) (Math.random()*10000)) % fileNum);
}
@SuppressWarnings("finally")
private String getHTTPResponse (String httpReq)
{
String httpResponse = null;
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(httpReq);
try
{
Log.i("In HTTP response", httpReq);
HttpResponse response = client.execute(httpGet);
Log.i("response", response.toString());
StatusLine statusLine = response.getStatusLine();
Log.i("In HTTP response", statusLine.toString());
int statusCode = statusLine.getStatusCode();
Log.i("In HTTP response", String.valueOf(statusCode));
if (statusCode == 200)
71
{
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
Log.i("Content", content.toString());
BufferedReader reader = new BufferedReader(new
InputStreamReader(content));
httpResponse = reader.readLine();
} else
{
Log.i("parseJSON", "Failed to download file");
}
} catch (ClientProtocolException e)
{
Log.i("ProtocolException", "In protocol Catch");
e.printStackTrace();
} catch (IOException e)
{
Log.i("IOException", "In IO Catch");
e.printStackTrace();
}
finally
{
Log.i("Response Return", httpResponse);
client.getConnectionManager().shutdown();
return httpResponse;
}
}
/**
* Thread for dialog
*/
public class BGThread extends Thread
{
@Override
public void run()
{
playAudio();
handler.post(new MyRunnable());
}
}
public class MyRunnable implements Runnable
{
public void run()
{
//imageView.setImageBitmap(imgBitmap);
prgDialog.dismiss();
}
72
}
}
********************************
SlideShowActivity.java
********************************
package com.android.cloudplayer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import com.android.cloudplayer.ImageViewerActivity.BGThread;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
/**
* @author Prajakta Sarurkar
* This activity is used for Slide Show screen
*/
public class SlideShowActivity extends Activity
{
private static String devID, searchCrit;
private static String svcID;
private static String valToken;
private static String fileID;
73
private static String fileName;
private String fileReq;
private JSONArray fileArr;
private static String [] fileIDArry;
private String [] fileNameArry;
private static int [] fileSizeArry;
private static int fileNum;
private static int fileSize, scaling = 1;
private static ProgressDialog prgDialog;
private static ImageView imageView;
private static Handler handler;
private static Bitmap imgBitmap;
private BGThread imgThread = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
Intent i = getIntent();
valToken = i.getStringExtra("valToken");
devID = i.getStringExtra("devID");
svcID = i.getStringExtra("svcID");
searchCrit = i.getStringExtra("searchCrit");
super.onCreate(savedInstanceState);
setContentView(R.layout.slideshow);
TextView txt = (TextView) findViewById(R.id.textView1);
txt.setText(fileName);
Log.i("Inside Slide ShowActivity", "SlideShowActivity");
// Create a handler to update the UI
handler = new Handler();
// get the latest imageView after restart of the application
imageView = (ImageView) findViewById(R.id.imageView1);
try
{
fileReq =
"http://service.pogoplug.com/svc/api/json/searchFiles?searchcrit=mediatype+=+" +searchCrit+
"&valtoken="+valToken+"&serviceid="+svcID +
"&deviceid="+devID;
Log.i("fileReq", fileReq);
String fileResp = getHTTPResponse(fileReq);
Log.i("fileResp", fileResp.toString());
JSONObject fileObj = new JSONObject (fileResp);
fileArr = fileObj.optJSONArray("files");
fileIDArry = new String[fileArr.length()];
fileNameArry = new String[fileArr.length()];
74
fileSizeArry = new int[fileArr.length()];
fileNum = fileArr.length();
Log.i("Back from buildData", Integer.toString(fileNum));
for (int index = 0;index < fileNum;index ++)
{
fileIDArry[index] = fileArr.getJSONObject(index).getString("fileid");
fileNameArry[index] =
fileArr.getJSONObject(index).getString("filename");
fileSizeArry[index] = fileArr.getJSONObject(index).getInt("size");
}
Log.i("FileChk", "Launching slide show player");
}
catch (Exception e)
{
e.printStackTrace();
}
if (imgBitmap != null)
{
imageView.setImageBitmap(imgBitmap);
}
// Check if the thread is already running
imgThread = (Thread) getLastNonConfigurationInstance();
if(imgThread == null)
{
startSlideShow();
imgThread.classPtr = this;
Log.i("Slide Show", "Back from Thread 11111");
}
//
}
// Save the thread
public void myFinish ()
{
finish();
}
@Override
public Object onRetainNonConfigurationInstance()
{
return imgThread;
}
// dismiss dialog if activity is destroyed
@Override
protected void onDestroy()
{
75
if (prgDialog != null && prgDialog.isShowing()) {
prgDialog.dismiss();
prgDialog = null;
}
super.onDestroy();
}
public void startSlideShow()
{
Log.i("Inside Activity", "Start SlideShow");
prgDialog = ProgressDialog.show(this, "Slide Show", "Loading");
imgThread = new BGThread();
imgThread.start();
}
// Utiliy method to download image from the cloud
private static Bitmap getBitmap(int index) throws IOException
{
int refSize = 4*1024*1024;
fileSize = fileSizeArry[index] * 10;
fileID = fileIDArry[index];
scaling = ((int) fileSize/refSize) * 2;
if (scaling == 0)
scaling = 1;
Log.i("ImageViewer", "Ref Size " + refSize + "File Size is " + Integer.toString(fileSize) + " Scaling is
" + Integer.toString(scaling));
BitmapFactory.Options bmOptions;
bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = scaling;
bmOptions.inPurgeable = true;
bmOptions.inInputShareable = true;
String imageURL = "http://service.pogoplug.com/svc/files/"+valToken+"/"+devID+
"/"+svcID+"/"+fileID+"/strm";
Log.i("fileReq", imageURL);
Bitmap bitmap = null;
HttpGet httpRequest = new HttpGet(imageURL);
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = null;
try
{
response = (HttpResponse) httpClient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);
InputStream is = bufferedHttpEntity.getContent();
bitmap = BitmapFactory.decodeStream(is, null, bmOptions);
} catch (ClientProtocolException e)
76
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
httpClient.getConnectionManager().shutdown();
return bitmap;
}
public class BGThread extends Thread
{
public SlideShowActivity classPtr;
@Override
public void run()
{
try
{
for (int index = 0;index < fileNum;index ++)
{
Log.i("Inside thread run", "Index is " +
Integer.toString(index));
imgBitmap = getBitmap(index);
Log.i("Inside thread run", "Back from getBitmap");
//
imageView.setImageBitmap(imgBitmap);
Log.i("Inside thread run", "set Bitmap");
handler.post(new MyRunnable());
}
try
{
Log.i("Slide Show Thread", "Before Sleeping");
sleep(3000);
classPtr.myFinish();
//
//
getLock();
notify();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
catch (IOException e)
{
e.printStackTrace();
77
}
finally
{
}
}
}
public static class MyRunnable implements Runnable
{
public void run()
{
imageView.setImageBitmap(imgBitmap);
prgDialog.dismiss();
}
}
private String getHTTPResponse (String httpReq)
{
String httpResponse = null;
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(httpReq);
try
{
Log.i("In HTTP response", httpReq);
HttpResponse response = client.execute(httpGet);
Log.i("response", response.toString());
StatusLine statusLine = response.getStatusLine();
Log.i("In HTTP response", statusLine.toString());
int statusCode = statusLine.getStatusCode();
Log.i("In HTTP response", String.valueOf(statusCode));
if (statusCode == 200)
{
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
Log.i("Content", content.toString());
BufferedReader reader = new BufferedReader(new
InputStreamReader(content));
httpResponse = reader.readLine();
} else
{
Log.i("parseJSON", "Failed to download file");
}
} catch (ClientProtocolException e)
{
Log.i("ProtocolException", "In protocol Catch");
e.printStackTrace();
} catch (IOException e)
{
78
Log.i("IOException", "In IO Catch");
e.printStackTrace();
}
finally
{
Log.i("Response Return", httpResponse);
client.getConnectionManager().shutdown();
return httpResponse;
}
}
}
********************************
UserScreenActivity.java
********************************
package com.android.cloudplayer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
/**
* @author Prajakta Sarurkar
* This activity is invoked after successful login to the application and the UI displays
* all the available media folders
*/
79
public class UserScreenActivity extends Activity
{
private JSONArray svcArr;
private String devID, svcID;
private String valToken, userID;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.userscreen);
TextView txtUserID = (TextView) findViewById(R.id.txtUserID);
Intent i = getIntent();
userID = i.getStringExtra("userID");
txtUserID.setText(userID);
valToken = i.getStringExtra("valToken");
try
{
String svcReq = "http://service.pogoplug.com/svc/api/json/listServices?valtoken="+valToken;
Log.i("svcReq", svcReq);
String svcResp = getHTTPResponse(svcReq);
if (svcResp != null)
{
Log.i("svcResp", svcResp.toString());
JSONObject svcResponseObj = new JSONObject(svcResp);
Log.i("Services", svcResponseObj.names().toString());
svcArr = svcResponseObj.optJSONArray("services");
devID = svcArr.getJSONObject(0).getString("deviceid");
svcID = svcArr.getJSONObject(0).getString("serviceid");
Log.i("Device", devID);
Log.i("Service", svcID);
}
else
{
Log.i("Server Error", "svcID null");
}
}
catch (Exception e)
{
e.printStackTrace();
80
}
}
/**
*
* @param view
* Handler to start the next activity on click of Files button
*/
public void fileHandler(View view)
{
// Added to change the screen
Intent fileScreen = new Intent(getApplicationContext(), FileScreenActivity.class);
//Sending data to another Activity
fileScreen.putExtra("userID", userID);
fileScreen.putExtra("valToken", valToken);
fileScreen.putExtra("devID", devID);
fileScreen.putExtra("svcID", svcID);
fileScreen.putExtra("parentID","");
fileScreen.putExtra("sortcrit", "-type");
fileScreen.putExtra("searchCrit","" );
startActivity(fileScreen);
}
/**
*
* @param view
* Handler to start the next activity on click of Music button
*/
public void audioHandler(View view)
{
// Added to change the screen
Intent audioScreen = new Intent(getApplicationContext(), FileScreenActivity.class);
//Sending data to another Activity
audioScreen.putExtra("userID", userID);
audioScreen.putExtra("valToken", valToken);
audioScreen.putExtra("devID", devID);
audioScreen.putExtra("svcID", svcID);
audioScreen.putExtra("parentID","");
audioScreen.putExtra("sortcrit", "-type");
audioScreen.putExtra("searchCrit","audio" );
startActivity(audioScreen);
}
/**
*
81
* @param view
* Handler to start the next activity on click of Movies button
*/
public void videoHandler(View view)
{
// Added to change the screen
Intent videoScreen = new Intent(getApplicationContext(), FileScreenActivity.class);
//Sending data to another Activity
videoScreen.putExtra("userID", userID);
videoScreen.putExtra("valToken", valToken);
videoScreen.putExtra("devID", devID);
videoScreen.putExtra("svcID", svcID);
videoScreen.putExtra("parentID","");
videoScreen.putExtra("sortcrit", "-type");
videoScreen.putExtra("searchCrit","video" );
startActivity(videoScreen);
}
/**
*
* @param view
* Handler to start the next activity on click of Radio button
*/
public void radioHandler(View view)
{
// Added to change the screen
Intent radioScreen = new Intent(getApplicationContext(), RadioScreenActivity.class);
//Sending data to another Activity
Log.i("Start Activity", "Radio");
radioScreen.putExtra("valToken", valToken);
radioScreen.putExtra("devID", devID);
radioScreen.putExtra("svcID", svcID);
radioScreen.putExtra("searchCrit","audio" );
startActivity(radioScreen);
}
/**
*
* @param view
* Handler to start the next activity on click of Images button
*/
public void imageHandler(View view)
{
// Added to change the screen
82
Intent imageScreen = new Intent(getApplicationContext(), FileScreenActivity.class);
//Sending data to another Activity
imageScreen.putExtra("userID", userID);
imageScreen.putExtra("valToken", valToken);
imageScreen.putExtra("devID", devID);
imageScreen.putExtra("svcID", svcID);
imageScreen.putExtra("parentID","");
imageScreen.putExtra("sortcrit", "-type");
imageScreen.putExtra("searchCrit","image" );
startActivity(imageScreen);
}
/**
*
* @param view
* Handler to start the next activity on click of Slide Show button
*/
public void slideShowHandler(View view)
{
// Added to change the screen
Intent showScreen = new Intent(getApplicationContext(), SlideShowActivity.class);
//Sending data to another Activity
showScreen.putExtra("userID", userID);
showScreen.putExtra("valToken", valToken);
showScreen.putExtra("devID", devID);
showScreen.putExtra("svcID", svcID);
showScreen.putExtra("searchCrit","image" );
startActivity(showScreen);
}
/**
*
* @param String HTTP Request
* @return String HTTP Response
*/
private String getHTTPResponse (String httpReq)
{
String httpResponse = null;
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(httpReq);
try
{
Log.i("In HTTP response", httpReq);
HttpResponse response = client.execute(httpGet);
Log.i("response", response.toString());
83
StatusLine statusLine = response.getStatusLine();
Log.i("In HTTP response", statusLine.toString());
int statusCode = statusLine.getStatusCode();
Log.i("In HTTP response", String.valueOf(statusCode));
if (statusCode == 200)
{
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
Log.i("Content", content.toString());
BufferedReader reader = new BufferedReader(new
InputStreamReader(content));
httpResponse = reader.readLine();
} else
{
Log.i("parseJSON", "Failed to download file");
}
} catch (ClientProtocolException e)
{
Log.i("ProtocolException", "In protocol Catch");
Toast.makeText(this, "Protocol Error", Toast.LENGTH_LONG).show();
} catch (IOException e)
{
Log.i("IOException", "In IO Catch");
Toast.makeText(this, "Connection Error", Toast.LENGTH_LONG).show();
}
finally
{
Log.i("Response Return", httpResponse);
client.getConnectionManager().shutdown();
return httpResponse;
}
}
}
********************************
VideoPlayerActivity.java
********************************
package com.android.cloudplayer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
84
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import com.android.cloudplayer.AudioPlayerActivity.BGThread;
import com.android.cloudplayer.AudioPlayerActivity.MyRunnable;
import android.R.drawable;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.VideoView;
/**
* @author Prajakta Sarurkar
* This activity is invoked for video playback
*/
public class VideoPlayerActivity extends Activity
{
private VideoView vView;
private String devID, svcID;
private String valToken, userID;
private String path = "";
private String [] fileIDArry;
private String [] fileNameArry;
private int fileIndex;
private int fileNum;
85
private Handler handler;
private Thread videoThread;
private ProgressDialog prgDialog;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.videoplayer);
Intent i = getIntent();
userID = i.getStringExtra("userID");
valToken = i.getStringExtra("valToken");
devID = i.getStringExtra("devID");
svcID = i.getStringExtra("svcID");
fileIndex = i.getIntExtra("fileIndex", 0);
fileNum = i.getIntExtra("fileNum", 1);
fileIDArry = new String[fileNum];
fileNameArry = new String[fileNum];
fileIDArry = i.getStringArrayExtra("fileID");
fileNameArry = i.getStringArrayExtra("fileName");
Log.i("VideoPlayer", "Entry");
Log.i("VideoPlayer", "userID "+userID);
Log.i("VideoPlayer", "valToken "+valToken);
Log.i("VideoPlayer", "devID "+devID);
Log.i("VideoPlayer", "svcID "+svcID);
Log.i("VideoPlayer", "fileID "+fileIDArry[0]);
Log.i("VideoPlayer", "fileNum "+fileNum);
Log.i("VideoPlayer", "fileIndex "+fileIndex);
vView = (VideoView) findViewById(R.id.videoView1);
playVideo();
}
/**
* This function is used for playing back requested video file
*
*/
private void playVideo()
{
path = "http://service.pogoplug.com/svc/files/"+valToken+"/"+devID+
"/"+svcID+"/"+fileIDArry[fileIndex]+"/strm";
Uri video = Uri.parse(path);
vView.setVideoURI(video);
//vView.setVideoPath(path);
vView.setMediaController(new MediaController(this));
vView.start();
vView.requestFocus();
86
}
public class BGThread extends Thread
{
@Override
public void run()
{
playVideo();
handler.post(new MyRunnable());
}
}
public class MyRunnable implements Runnable
{
public void run()
{
prgDialog.dismiss();
}
}
}
********************************
FileUploaderActivity.java
********************************
package com.android.cloudplayer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
87
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
/**
* @author Prajakta Sarurkar
* This activity creates an UI for uploading files from device to the cloud.
*/
public class FileUploaderActivity extends Activity
{
private String devID, svcID, valToken, userID;
private ListView fileListView;
private ArrayList <Map<String,String>> fileList;
private SimpleAdapter adapter;
private File [] fList;
private String [] fileNameArr;
private String [] fileType;
private String [] fileMimeType;
private String fileReq;
private String fileId, parentId;
private ProgressDialog prgDialog;
private Handler handler;
private Thread fileThread;
private String filePath;
private String dirMusic, dirPhoto,dirVideo, dirMisc;
private File path;
private String fileName;
private String fType;
private File fileToUpload;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.fileuploader);
Intent i = getIntent();
valToken = i.getStringExtra("valToken");
88
devID = i.getStringExtra("devID");
svcID = i.getStringExtra("svcID");
userID = i.getStringExtra("userID");
filePath = "/sdcard";
path = new File(filePath);
fileList = loadFileList(path);
fileListView = (ListView) findViewById(R.id.listView1);
String[] from = { "fileName", "fileType" };
int[] to = { android.R.id.text1, android.R.id.text2 };
adapter = new SimpleAdapter(this, fileList,
android.R.layout.simple_list_item_2, from, to);
fileListView.setAdapter(adapter);
getUploadDirectory();
fileListView.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id)
{
try
{
fileName = fileNameArr[pos];
fType = fileType[pos];
fileToUpload = fList[pos];
if(fType.equals("Directory"))
{
filePath += "/" + fileName;
Log.i("new Path ", filePath);
clrData(fList.length);
adapter.notifyDataSetChanged();
path = new File(filePath);
updateFileList(path);
adapter.notifyDataSetChanged();
}
else
{
// Create a handler to update the UI
handler = new Handler();
fileThread = new BGThread();
fileThread.start();
Log.i("File Thread ", fileThread.toString());
if (fileThread != null && fileThread.isAlive())
{
prgDialog =
ProgressDialog.show(view.getContext(), "File Uploader", "Uploading " + fileName);
89
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
);
}
// dismiss dialog if activity is destroyed
@Override
protected void onDestroy()
{
if (prgDialog != null && prgDialog.isShowing()) {
prgDialog.dismiss();
prgDialog = null;
}
super.onDestroy();
}
/**
*
* @return ArrayList File List
*/
private ArrayList<Map<String, String>> loadFileList(File path)
{
ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
Log.i("Path", path.toString());
if(path.exists())
{
fList = path.listFiles(filter);
Log.i("no of Files", Integer.toString(fList.length));
fileNameArr = new String[fList.length];
fileType = new String [fList.length];
fileMimeType = new String[fList.length];
String []fType;
for (int index = 0; index < fList.length; index++)
{
fileNameArr[index] = fList[index].getName();
if (fList[index].isDirectory())
fileType[index] = "Directory";
else if (fList[index].isFile())
{
if(fileNameArr[index].contains("."))
90
{
fType = fileNameArr[index].split("\\.");
Log.i("file Name", fType[1]);
fileMimeType[index] = fType[fType.length-1];
if(fileMimeType[index].equalsIgnoreCase("jpg"))
fileType[index] = "image/jpeg";
else
if(fileMimeType[index].equalsIgnoreCase("mp3") || fileMimeType[index].equalsIgnoreCase("amr"))
fileType[index] = "audio/mpeg";
else
if(fileMimeType[index].equalsIgnoreCase("mp4") || fileMimeType[index].equalsIgnoreCase("3gp"))
fileType[index] = "video/mp4";
else
{
fileType[index] = "File";
}
}
else
fileType[index] = "File";
}
Log.i("file Name + Mime ", fileNameArr[index] + " " +
fileMimeType[index]);
list.add(putData(fileNameArr[index],fileType[index]));
}
}
else
list.add(putData("No files to display", ""));
return list;
}
FilenameFilter filter = new FilenameFilter()
{
@Override
public boolean accept(File dir, String filename)
{
File sel = new File(dir, filename);
// Filters based on whether the file is hidden or not
return (sel.isFile() || sel.isDirectory())
&& !sel.isHidden();
}
};
private void clrData(int length) throws JSONException
{
if(fList != null)
{
Log.i("Inside clrData", Integer.toString(fList.length));
String [] fileNameArr = new String[fList.length];
String [] fileType = new String [fList.length];
91
for (int index = 0;index < length;index ++)
{
fileNameArr[index] = "";
fileType[index] = "";
fileList.set(index, putData("", ""));
}
}
}
private void updateFileList(File path)
{
Log.i("Path", path.toString());
if(path.exists())
{
fList = path.listFiles(filter);
Log.i("no of Files", Integer.toString(fList.length));
fileNameArr = new String[fList.length];
fileType = new String [fList.length];
String [] fType;
if(fList.length > 0)
{
for (int index = 0; index < fList.length; index++)
{
fileNameArr[index] = fList[index].getName();
if (fList[index].isDirectory())
fileType[index] = "Directory";
else if (fList[index].isFile())
{
if(fileNameArr[index].contains("."))
{
fType = fileNameArr[index].split("\\.");
Log.i("file Name", fType[1]);
fileMimeType[index] = fType[fType.length1];
if(fileMimeType[index].equalsIgnoreCase("jpg"))
fileType[index] = "image/jpeg";
else
if(fileMimeType[index].equalsIgnoreCase("mp3") || fileMimeType[index].equalsIgnoreCase("amr"))
{
fileType[index] = "audio/mpeg";
}
else
if(fileMimeType[index].equalsIgnoreCase("mp4") || fileMimeType[index].equalsIgnoreCase("3gp"))
fileType[index] = "video/mp4";
else
fileType[index] = "File";
92
}
else
fileType[index] = "File";
}
Log.i("file Name + List size ", fileNameArr[index] + " " +
Integer.toString(fList.length));
fileList.set(index,
putData(fileNameArr[index],fileType[index]));
}
}
else
{
fileList.set(0, putData("No files to display", ""));
}
}
else
fileList.set(0, putData("No files to display", ""));
}
/**
*
* @param String name
* @param String type
* @return HashMap of the files with key value pair of File name and File type
*/
private HashMap<String, String> putData(String name, String type)
{
HashMap<String, String> item = new HashMap<String, String>();
item.put("fileName", name);
item.put("fileType", type);
return item;
}
/**
*
* @param String HTTP Request
* @return String HTTP Response
*/
@SuppressWarnings("finally")
private String getHTTPResponse (String httpReq)
{
String httpResponse = null;
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(httpReq);
try
{
Log.i("In HTTP response", httpReq);
HttpResponse response = client.execute(httpGet);
93
Log.i("response", response.toString());
StatusLine statusLine = response.getStatusLine();
Log.i("In HTTP response", statusLine.toString());
int statusCode = statusLine.getStatusCode();
Log.i("In HTTP response", String.valueOf(statusCode));
if (statusCode == 200)
{
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
Log.i("Content", content.toString());
BufferedReader reader = new BufferedReader(new
InputStreamReader(content));
httpResponse = reader.readLine();
} else
{
Log.i("parseJSON", "Failed to download file");
}
} catch (ClientProtocolException e)
{
Log.e("ProtocolException", e.toString());
Toast.makeText(this, "Protocol Error", Toast.LENGTH_LONG).show();
} catch (IOException e)
{
Log.e("IOException", e.toString());
Toast.makeText(this, "Connection Error", Toast.LENGTH_LONG).show();
}
finally
{
Log.i("Response Return", httpResponse);
client.getConnectionManager().shutdown();
return httpResponse;
}
}
private void getUploadDirectory()
{
dirMusic = "";
dirPhoto = "";
dirVideo = "";
try
{
String name, type;
String dirReq =
"http://service.pogoplug.com/svc/api/json/listFiles?valtoken="+valToken+"&deviceid="+devID+"&service
id="+svcID;
String dirResp = getHTTPResponse(dirReq);
Log.i("fileResp", dirResp.toString());
JSONObject fileObj = new JSONObject (dirResp);
Log.i("Back from buildData", "BuildData");
94
JSONArray fileArr = fileObj.optJSONArray("files");
for (int index = 0;index < fileArr.length();index ++)
{
name = fileArr.getJSONObject(index).getString("filename");
type = fileArr.getJSONObject(index).getString("type");
if(name.equalsIgnoreCase("music") && type.equals("1"))
{
dirMusic = fileArr.getJSONObject(index).getString("fileid");
}
else if(name.equalsIgnoreCase("photo") && type.equals("1"))
{
dirPhoto = fileArr.getJSONObject(index).getString("fileid");
}
else if(name.equalsIgnoreCase("video") && type.equals("1"))
{
dirVideo = fileArr.getJSONObject(index).getString("fileid");
}
else if(name.equalsIgnoreCase("misc") && type.equals("1"))
{
dirMisc = fileArr.getJSONObject(index).getString("fileid");
}
}
}
catch(Exception ex)
{
Log.e("Exception in getUploadDir", ex.toString());
}
}
private void uploadFile()
{
try
{
if(fType.matches("audio/mpeg"))
parentId = dirMusic;
else if(fType.matches("image/jpeg"))
parentId = dirPhoto;
else if(fType.matches("video/mp4"))
parentId = dirVideo;
else
parentId = dirMisc;
if(fileName.contains(" "))
{
String newFileName = fileName.replace(" ", "_");
fileReq =
"http://service.pogoplug.com/svc/api/json/createFile?&valtoken="+valToken+"&deviceid="+devID+"&ser
viceid="+svcID
95
+"&filename="+newFileName+"&parentid="+parentId;
}
else
{
fileReq =
"http://service.pogoplug.com/svc/api/json/createFile?&valtoken="+valToken+"&deviceid="+devID+"&ser
viceid="+svcID
+"&filename="+fileName+"&parentid="+parentId;
}
Log.i("Uploader", "Req " + fileReq);
Log.i("Uploader", "After Req " + fileReq);
String fileResp = getHTTPResponse(fileReq);
JSONObject fileObj = new JSONObject (fileResp);
fileId = fileObj.getJSONObject("file").getString("fileid");
String fileURL =
"http://service.pogoplug.com/svc/files/"+valToken+"/"+devID+
"/"+svcID+"/"+fileId+"/strm";
HttpClient http = new DefaultHttpClient();
HttpPut httpRequest = new HttpPut(fileURL);
httpRequest.setEntity(new FileEntity(fileToUpload,fType));
HttpResponse response = http.execute(httpRequest);
if (response.getStatusLine().getStatusCode() == 200)
{
Intent fileScreen = new Intent(getApplicationContext(),
FileScreenActivity.class);
//Sending data to another Activity
fileScreen.putExtra("userID", userID);
fileScreen.putExtra("valToken", valToken);
fileScreen.putExtra("devID", devID);
fileScreen.putExtra("svcID", svcID);
fileScreen.putExtra("parentID",parentId);
fileScreen.putExtra("sortcrit", "-type");
fileScreen.putExtra("searchCrit","" );
startActivity(fileScreen);
}
}
catch(IOException iEx)
{
Log.e("IOExcption in uploadFile", iEx.toString());
}
catch(Exception ex)
{
96
Log.e("Excption in uploadFile", ex.toString());
}
}
/**
* Thread for diaglog
*/
public class BGThread extends Thread
{
@Override
public void run()
{
try
{
uploadFile();
handler.post(new MyRunnable());
}
catch (Exception ex)
{
Log.e("Excption in uploadFile", ex.toString());
}
}
}
public class MyRunnable implements Runnable
{
public void run()
{
prgDialog.dismiss();
}
}
}
97
BIBLIOGRAPHY
[1] Introduction to Smartphones, [Online]
Available: http://www.pcworld.com/article/246915/the_next_big_things_in_tech.html
[2] Cloud computing with Smartphones, [Online]
Available: http://www.crn.com/news/data-center/232700118/cloud-computing-onhorizon-for-smartphones.htm;jsessionid=3s+dAKuk5iJggkRLBF+M+Q**.ecappj03
[3] Cloud computing and Smartphones, [Online]
Available: http://cloudtimes.org/cloud-computing-and-smartphones/
[4] Gonzalo Huerta-Canepa et al, ―A virtual cloud computing provider for mobile
devices‖, Proceeding MCS '10 Proceedings of the 1st ACM Workshop on Mobile Cloud
Computing & Services: Social Networks and Beyond, ACM New York, NY, USA, 2010,
ISBN: 978-1-4503-0155-8
[5] Introduction to Amazon cloud drive, [online]
Available: https://www.amazon.com/clouddrive/learnmore
[6] Introduction to Apple iCloud, [online]
Available: http://www.apple.com/icloud/
[7] Introduction to Zumodrive, [online]
Available: http://www.zumodrive.com/
[8] Barrie Sosinsky, ―Cloud Computing Bible‖, Wiley Publishing, 2011, ISBN: 978-04709-0356-8
98
[9] P. Lougher and D. Shepherd, ―The Design of a Storage Server for Continuous
Media‖, The Computer Journal (1993) 36 (1): 32-42.
[10] Introduction to Pogoplug, [online]
Available: https://pogoplug.com/downloads
[11] Cloud setup using Pogoplug, [online]
Available: http://download.pogoplug.com/meet/setup.html
[12] Pogoplug specifications, [online]
Available: http://download.pogoplug.com/meet/specs.html
[13] Pogoplug API calls, [online]
Available: http://download.pogoplug.com/dev/web.html
[14] Android APIs, [online]
Available: http://developer.android.com/guide/topics/fundamentals.html
[15] Android application components, [online]
Available: http://elinux.org/Android_Architecture
[16] Nancy Lynch and Seth Gilbert, ―Brewer's conjecture and the feasibility of
consistent, available, partition-tolerant web services‖, ACM SIGACT News, Volume 33
Issue 2 (2002), pg. 51-59
[17] Definition of personal media cloud, [online]
Available:http://www.pcmag.com/encyclopedia_term/0,2542,t=personal+cloud&i=62784
,00.asp
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement