Skip to content

Commit

Permalink
Add PhotoAlbum
Browse files Browse the repository at this point in the history
To access the device photo album a new ClientService was introduced
called "PhotoAlbum". Internally it used the Camera service to take
picture and sets an addition property during the "open" call. This
property is named "sourceType" and it's value is "saved_photo_album".

Change-Id: I761e6d95ed3fa80a65c5876f589ae32e121ebe4d
  • Loading branch information
hstaudacher committed Jun 1, 2015
1 parent ac92a17 commit 2c2fa2d
Show file tree
Hide file tree
Showing 12 changed files with 654 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*******************************************************************************
* Copyright (c) 2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.tabris.camera;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.Serializable;

import org.eclipse.swt.graphics.Point;
import org.junit.Test;


public class PhotoAlbumOptionsTest {

@Test
public void testIsSerializable() {
assertTrue( Serializable.class.isAssignableFrom( PhotoAlbumOptions.class ) );
}

@Test
public void testNoneOptions() {
assertNull( CameraOptions.NONE.getResolution() );
assertFalse( CameraOptions.NONE.savesToAlbum() );
assertEquals( 1.0F, CameraOptions.NONE.getCompressionQuality(), 0 );
}

@Test
public void testResolution() {
PhotoAlbumOptions albumOptions = new PhotoAlbumOptions();

albumOptions.setResolution( 500, 500 );

assertEquals( new Point( 500, 500 ), albumOptions.getResolution() );
}

@Test
public void testDefaultResolutionIsNull() {
PhotoAlbumOptions albumOptions = new PhotoAlbumOptions();

Point resolution = albumOptions.getResolution();

assertNull( resolution );
}

@Test
public void testSetsComptressionQuality() {
PhotoAlbumOptions albumOptions = new PhotoAlbumOptions();

albumOptions.setCompressionQuality( 0.5F );

assertEquals( 0.5F, albumOptions.getCompressionQuality(), 0 );
}

@Test
public void testDefaultCompressionQualityIsOne() {
PhotoAlbumOptions albumOptions = new PhotoAlbumOptions();

float compressionQuality = albumOptions.getCompressionQuality();

assertEquals( 1.0F, compressionQuality, 0 );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/*******************************************************************************
* Copyright (c) 2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.tabris.internal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;

import org.eclipse.rap.json.JsonArray;
import org.eclipse.rap.json.JsonObject;
import org.eclipse.rap.json.JsonValue;
import org.eclipse.rap.rwt.client.Client;
import org.eclipse.rap.rwt.remote.RemoteObject;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

import com.eclipsesource.tabris.TabrisClient;
import com.eclipsesource.tabris.camera.Camera;
import com.eclipsesource.tabris.camera.PhotoAlbumListener;
import com.eclipsesource.tabris.camera.PhotoAlbumOptions;
import com.eclipsesource.tabris.test.util.TabrisEnvironment;


public class PhotoAlbumImplTest {

@Rule
public TabrisEnvironment environment = new TabrisEnvironment();

private CameraImpl camera;

@Before
public void setUp() {
Client client = mock( TabrisClient.class );
camera = new CameraImpl();
when( client.getService( Camera.class ) ).thenReturn( camera );
environment.setClient( client );
new Display();
}

@Test
public void testIsSerializable() {
assertTrue( Serializable.class.isAssignableFrom( PhotoAlbumImpl.class ) );
}

@Test
public void testCameraListenerIsSerializable() {
assertTrue( Serializable.class.isAssignableFrom( PhotoAlbumListener.class ) );
}

@Test
public void testSetsNoInitialCameraOptionsWithDefaultOptions() {
RemoteObject remoteObject = environment.getServiceObject();

new PhotoAlbumImpl();

verify( remoteObject, never() ).set( eq( "resolution" ), any( JsonValue.class ) );
verify( remoteObject, never() ).set( eq( "sourceType" ), any( JsonValue.class ) );
verify( remoteObject, never() ).set( eq( "compressionQuality" ), any( JsonValue.class ) );
}

@Test
public void testSendsOpenWithOpenCall() {
PhotoAlbumImpl album = new PhotoAlbumImpl();
RemoteObject remoteObject = camera.getRemoteObject();
PhotoAlbumListener listener = mock( PhotoAlbumListener.class );
album.addPhotoAlbumListener( listener );

album.open( createOptions() );

ArgumentCaptor<JsonObject> captor = ArgumentCaptor.forClass( JsonObject.class );
verify( remoteObject ).call( eq( "open" ), captor.capture() );
JsonArray resolution = captor.getValue().get( "resolution" ).asArray();
assertEquals( 100, resolution.get( 0 ).asInt() );
assertEquals( 100, resolution.get( 1 ).asInt() );
assertEquals( captor.getValue().get( "sourceType" ).asString(), "saved_photo_album" );
assertEquals( captor.getValue().get( "compressionQuality" ).asFloat(), 0.5F, 0 );
}

@Test( expected = IllegalArgumentException.class )
public void testFailsWithNullOptions() {
PhotoAlbumImpl album = new PhotoAlbumImpl();

album.open( null );
}

@Test( expected = IllegalArgumentException.class )
public void testAddFailsWithNullListener() {
PhotoAlbumImpl album = new PhotoAlbumImpl();

album.addPhotoAlbumListener( null );
}

@Test( expected = IllegalArgumentException.class )
public void testRemoveFailsWithNullListener() {
PhotoAlbumImpl album = new PhotoAlbumImpl();

album.removePhotoAlbumListener( null );
}

@Test
public void testDelegatesError() {
PhotoAlbumImpl album = new PhotoAlbumImpl();
PhotoAlbumListener listener = mock( PhotoAlbumListener.class );
album.addPhotoAlbumListener( listener );

album.open( createOptions() );
environment.dispatchNotifyOnServiceObject( "ImageSelectionError", null );

verify( listener ).receivedImage( null );
}

@Test
public void testDelegatesErrorToAllListeners() {
PhotoAlbumImpl album = new PhotoAlbumImpl();
PhotoAlbumListener listener1 = mock( PhotoAlbumListener.class );
PhotoAlbumListener listener2 = mock( PhotoAlbumListener.class );
album.addPhotoAlbumListener( listener1 );
album.addPhotoAlbumListener( listener2 );

album.open( createOptions() );
environment.dispatchNotifyOnServiceObject( "ImageSelectionError", null );

verify( listener1 ).receivedImage( null );
verify( listener2 ).receivedImage( null );
}


@Test
public void testDelegatesCancel() {
PhotoAlbumImpl album = new PhotoAlbumImpl();
PhotoAlbumListener listener = mock( PhotoAlbumListener.class );
album.addPhotoAlbumListener( listener );

album.open( createOptions() );
environment.dispatchNotifyOnServiceObject( "ImageSelectionCancel", null );

verify( listener ).receivedImage( null );
}

@Test
public void testDelegatesCancelToAllListeners() {
PhotoAlbumImpl album = new PhotoAlbumImpl();
PhotoAlbumListener listener1 = mock( PhotoAlbumListener.class );
PhotoAlbumListener listener2 = mock( PhotoAlbumListener.class );
album.addPhotoAlbumListener( listener1 );
album.addPhotoAlbumListener( listener2 );

album.open( createOptions() );
environment.dispatchNotifyOnServiceObject( "ImageSelectionCancel", null );

verify( listener1 ).receivedImage( null );
verify( listener2 ).receivedImage( null );
}

@Test
public void testDelegatesImage() throws IOException {
String encodedImage = getEncodedImage();
PhotoAlbumImpl album = new PhotoAlbumImpl();
PhotoAlbumListener listener = mock( PhotoAlbumListener.class );
album.addPhotoAlbumListener( listener );

album.open( createOptions() );
JsonObject properties = new JsonObject();
properties.add( "image", encodedImage );
environment.dispatchNotifyOnServiceObject( "ImageSelection", properties );

verify( listener ).receivedImage( any( Image.class ) );
}

@Test
public void testDelegatesImageToAllListeners() throws IOException {
String encodedImage = getEncodedImage();
PhotoAlbumImpl album = new PhotoAlbumImpl();
PhotoAlbumListener listener1 = mock( PhotoAlbumListener.class );
PhotoAlbumListener listener2 = mock( PhotoAlbumListener.class );
album.addPhotoAlbumListener( listener1 );
album.addPhotoAlbumListener( listener2 );

album.open( createOptions() );
JsonObject properties = new JsonObject();
properties.add( "image", encodedImage );
environment.dispatchNotifyOnServiceObject( "ImageSelection", properties );

verify( listener1 ).receivedImage( any( Image.class ) );
verify( listener2 ).receivedImage( any( Image.class ) );
}

private String getEncodedImage() throws IOException {
InputStream resourceStream = getClass().getResourceAsStream( "tabris.png" );
return Base64.encodeBytes( getBytes( resourceStream ) );
}

private byte[] getBytes( InputStream is ) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[ 16384 ];
while( ( nRead = is.read( data, 0, data.length ) ) != -1 ) {
buffer.write( data, 0, nRead );
}
buffer.flush();
return buffer.toByteArray();
}

private PhotoAlbumOptions createOptions() {
PhotoAlbumOptions options = new PhotoAlbumOptions();
options.setResolution( 100, 100 );
options.setCompressionQuality( 0.5F );
return options;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.eclipsesource.tabris.TabrisClient;
import com.eclipsesource.tabris.app.App;
import com.eclipsesource.tabris.camera.Camera;
import com.eclipsesource.tabris.camera.PhotoAlbum;
import com.eclipsesource.tabris.device.ClientDevice;
import com.eclipsesource.tabris.geolocation.Geolocation;
import com.eclipsesource.tabris.interaction.AppLauncher;
Expand Down Expand Up @@ -88,6 +89,15 @@ public void testHasCameraService() {
assertNotNull( camera );
}

@Test
public void testHasPhotoAlbumService() {
TabrisClient client = new TabrisClientImpl();

PhotoAlbum album = client.getService( PhotoAlbum.class );

assertNotNull( album );
}

@Test
public void testHasCloudPushService() {
TabrisClient client = new TabrisClientImpl();
Expand Down Expand Up @@ -170,6 +180,16 @@ public void testCameraIsSingleton() {
assertSame( camera, camera2 );
}

@Test
public void testPhotoAlbumIsSingleton() {
TabrisClient client = new TabrisClientImpl();

PhotoAlbum album = client.getService( PhotoAlbum.class );
PhotoAlbum album2 = client.getService( PhotoAlbum.class );

assertSame( album, album2 );
}

@Test
public void testGeolocationIsSingleton() {
TabrisClient client = new TabrisClientImpl();
Expand Down
9 changes: 9 additions & 0 deletions com.eclipsesource.tabris/.settings/.api_filters
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@
</message_arguments>
</filter>
</resource>
<resource path="src/com/eclipsesource/tabris/internal/PhotoAlbumImpl.java" type="com.eclipsesource.tabris.internal.PhotoAlbumImpl">
<filter id="574668824">
<message_arguments>
<message_argument value="PhotoAlbum"/>
<message_argument value="PhotoAlbumImpl"/>
<message_argument value="ClientService"/>
</message_arguments>
</filter>
</resource>
<resource path="src/com/eclipsesource/tabris/internal/PrinterImpl.java" type="com.eclipsesource.tabris.internal.PrinterImpl">
<filter id="574668824">
<message_arguments>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

/**
* <p>
* The <code>Camera</code> component can be used to take and receive pictures from a mobile client's camera or photo
* album. The taken picture will be sent to the server side and a callback will be called. See
* <code>CameraCallback</code>. An instance of {@link Camera} can be accessed using
* The <code>Camera</code> component can be used to take and receive pictures from a mobile client's camera.
* The taken picture will be sent to the server side and a callback will be called. See
* <code>CameraListener</code>. An instance of {@link Camera} can be accessed using
* RWT.getClient().getService( Camera.class ).
* </p>
*
Expand All @@ -34,8 +34,8 @@ public interface Camera extends ClientService {

/**
* <p>
* Instructs the client to open the camera or photo album. The added {@link CameraListener}s will be called when the
* user has taken/selected a picture or in the case of an error.
* Instructs the client to open the camera. The added {@link CameraListener}s will be called when the
* user has taken a picture..
* </p>
*
* @param options The options that should be used as the configuration for taking a picture. Must not
Expand Down
Loading

0 comments on commit 2c2fa2d

Please sign in to comment.