diff options
author | Andrzej J. R. Hunt <andrzej@ahunt.org> | 2012-07-09 11:23:39 +0100 |
---|---|---|
committer | Michael Meeks <michael.meeks@suse.com> | 2012-08-06 10:21:48 +0100 |
commit | 096e35f1dc20d4635390412cc0302ec58b2d7f1a (patch) | |
tree | 6d76d93549f47621b4554bf1062403c0248e88a8 | |
parent | e4239e0414685f8d8dd2f34fcc970717c7bd6cb8 (diff) |
Initial commit of android remote.
Change-Id: Ia8cfce4af87d121acacf9a29632435c4c786822f
19 files changed, 629 insertions, 0 deletions
diff --git a/android/sdremote/.classpath b/android/sdremote/.classpath new file mode 100644 index 000000000000..3f9691c5dda2 --- /dev/null +++ b/android/sdremote/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath> diff --git a/android/sdremote/.project b/android/sdremote/.project new file mode 100644 index 000000000000..70ef552c8876 --- /dev/null +++ b/android/sdremote/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>ImpressRemote</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/android/sdremote/AndroidManifest.xml b/android/sdremote/AndroidManifest.xml new file mode 100644 index 000000000000..e1c76d7145e9 --- /dev/null +++ b/android/sdremote/AndroidManifest.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.libreoffice.impressremote" + android:versionCode="1" + android:versionName="1.0" > + + <uses-permission android:name="android.permission.INTERNET" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" > + <activity + android:name="TestClient" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <service android:name=".communication.CommunicationService" > + </service> + </application> + +</manifest>
\ No newline at end of file diff --git a/android/sdremote/ant.properties b/android/sdremote/ant.properties new file mode 100644 index 000000000000..b0971e891efd --- /dev/null +++ b/android/sdremote/ant.properties @@ -0,0 +1,17 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked into Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + diff --git a/android/sdremote/build.xml b/android/sdremote/build.xml new file mode 100644 index 000000000000..b47c3973b1cc --- /dev/null +++ b/android/sdremote/build.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="ImpressRemote" default="help"> + + <!-- The local.properties file is created and updated by the 'android' tool. + It contains the path to the SDK. It should *NOT* be checked into + Version Control Systems. --> + <property file="local.properties" /> + + <!-- The ant.properties file can be created by you. It is only edited by the + 'android' tool to add properties to it. + This is the place to change some Ant specific build properties. + Here are some properties you may want to change/update: + + source.dir + The name of the source directory. Default is 'src'. + out.dir + The name of the output directory. Default is 'bin'. + + For other overridable properties, look at the beginning of the rules + files in the SDK, at tools/ant/build.xml + + Properties related to the SDK location or the project target should + be updated using the 'android' tool with the 'update' action. + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. + + --> + <property file="ant.properties" /> + + <!-- The project.properties file is created and updated by the 'android' + tool, as well as ADT. + + This contains project specific properties such as project target, and library + dependencies. Lower level build properties are stored in ant.properties + (or in .classpath for Eclipse projects). + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. --> + <loadproperties srcFile="project.properties" /> + + <!-- quick check on sdk.dir --> + <fail + message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var" + unless="sdk.dir" + /> + + <!-- + Import per project custom build rules if present at the root of the project. + This is the place to put custom intermediary targets such as: + -pre-build + -pre-compile + -post-compile (This is typically used for code obfuscation. + Compiled code location: ${out.classes.absolute.dir} + If this is not done in place, override ${out.dex.input.absolute.dir}) + -post-package + -post-build + -pre-clean + --> + <import file="custom_rules.xml" optional="true" /> + + <!-- Import the actual build file. + + To customize existing targets, there are two options: + - Customize only one target: + - copy/paste the target into this file, *before* the + <import> task. + - customize it to your needs. + - Customize the whole content of build.xml + - copy/paste the content of the rules files (minus the top node) + into this file, replacing the <import> task. + - customize to your needs. + + *********************** + ****** IMPORTANT ****** + *********************** + In all cases you must update the value of version-tag below to read 'custom' instead of an integer, + in order to avoid having your file be overridden by tools such as "android update project" + --> + <!-- version-tag: 1 --> + <import file="${sdk.dir}/tools/ant/build.xml" /> + +</project> diff --git a/android/sdremote/proguard-project.txt b/android/sdremote/proguard-project.txt new file mode 100644 index 000000000000..f2fe1559a217 --- /dev/null +++ b/android/sdremote/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/android/sdremote/project.properties b/android/sdremote/project.properties new file mode 100644 index 000000000000..0840b4a05983 --- /dev/null +++ b/android/sdremote/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-15 diff --git a/android/sdremote/res/drawable-hdpi/ic_launcher.png b/android/sdremote/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000000..8074c4c571b8 --- /dev/null +++ b/android/sdremote/res/drawable-hdpi/ic_launcher.png diff --git a/android/sdremote/res/drawable-ldpi/ic_launcher.png b/android/sdremote/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000000..1095584ec21f --- /dev/null +++ b/android/sdremote/res/drawable-ldpi/ic_launcher.png diff --git a/android/sdremote/res/drawable-mdpi/ic_launcher.png b/android/sdremote/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000000..a07c69fa5a0f --- /dev/null +++ b/android/sdremote/res/drawable-mdpi/ic_launcher.png diff --git a/android/sdremote/res/layout/main.xml b/android/sdremote/res/layout/main.xml new file mode 100644 index 000000000000..b100941e7796 --- /dev/null +++ b/android/sdremote/res/layout/main.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > +<TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="Hello World, Launcher" + /> +</LinearLayout> + diff --git a/android/sdremote/res/layout/testlayout.xml b/android/sdremote/res/layout/testlayout.xml new file mode 100644 index 000000000000..2e32325aabbb --- /dev/null +++ b/android/sdremote/res/layout/testlayout.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <TextView + android:id="@+id/label_curSlide" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:text="Slide: XXX" /> + + <Button + android:id="@+id/button_next" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:text="Next" /> + + <Button + android:id="@+id/button_previous" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:text="Previous" /> + +</LinearLayout>
\ No newline at end of file diff --git a/android/sdremote/res/values/strings.xml b/android/sdremote/res/values/strings.xml new file mode 100644 index 000000000000..78fbe65af57a --- /dev/null +++ b/android/sdremote/res/values/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_name">Launcher</string> +</resources> diff --git a/android/sdremote/src/org/libreoffice/impressremote/Launcher.java b/android/sdremote/src/org/libreoffice/impressremote/Launcher.java new file mode 100644 index 000000000000..77f2645b4ec0 --- /dev/null +++ b/android/sdremote/src/org/libreoffice/impressremote/Launcher.java @@ -0,0 +1,14 @@ +package org.libreoffice.impressremote; + +import android.app.Activity; +import android.os.Bundle; + +public class Launcher extends Activity { + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } + +} diff --git a/android/sdremote/src/org/libreoffice/impressremote/TestClient.java b/android/sdremote/src/org/libreoffice/impressremote/TestClient.java new file mode 100644 index 000000000000..b3bd3b5a7b69 --- /dev/null +++ b/android/sdremote/src/org/libreoffice/impressremote/TestClient.java @@ -0,0 +1,99 @@ +package org.libreoffice.impressremote; + +import org.libreoffice.impressremote.communication.CommunicationService; +import org.libreoffice.impressremote.communication.Transmitter; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; + +public class TestClient extends Activity { + + private boolean mIsBound = false; + + private CommunicationService mCommunicationService; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.testlayout); + setupUI(); + doBindService(); + + } + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName aClassName, + IBinder aService) { + mCommunicationService = ((CommunicationService.CBinder) aService) + .getService(); + mCommunicationService.connectTo( + CommunicationService.Protocol.NETWORK, "128.232.128.144"); + + enableButtons(true); + } + + public void onServiceDisconnected(ComponentName aClassName) { + mCommunicationService = null; + enableButtons(false); + } + }; + + void doBindService() { + bindService(new Intent(this, CommunicationService.class), mConnection, + Context.BIND_AUTO_CREATE); + mIsBound = true; + } + + void doUnbindService() { + if (mIsBound) { + unbindService(mConnection); + mIsBound = false; + } + } + + private Button mButtonNext; + + private Button mButtonPrevious; + + private void setupUI() { + mButtonNext = (Button) findViewById(R.id.button_next); + mButtonPrevious = (Button) findViewById(R.id.button_previous); + + enableButtons(false); + + mButtonNext.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + mCommunicationService.getTransmitter().nextTransition(); + + } + + }); + + mButtonPrevious.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + mCommunicationService.getTransmitter().previousTransition(); + + } + + }); + + } + + private void enableButtons(boolean aEnabled) { + mButtonNext.setEnabled(aEnabled); + mButtonPrevious.setEnabled(aEnabled); + } +} diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java b/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java new file mode 100644 index 000000000000..55966442f9e6 --- /dev/null +++ b/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java @@ -0,0 +1,111 @@ +package org.libreoffice.impressremote.communication; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import org.apache.http.util.ByteArrayBuffer; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Generic Client for the remote control. To implement a Client for a specific + * transport medium you must provide input and output streams ( + * <code>mInputStream</code> and <code>mOutputStream</code> before calling any + * methods. + * + * @author Andrzej J.R. Hunt + * + */ +public abstract class Client { + + private static final String CHARSET = "UTF-16"; + + protected InputStream mInputStream; + protected OutputStream mOutputStream; + + private void listen() { + ByteArrayBuffer aBuffer = new ByteArrayBuffer(10); + byte aTemp; + + try { + while ((aTemp = (byte) mInputStream.read()) != 0x0d) { + aBuffer.append(aTemp); + } + } catch (IOException e1) { + // TODO stream couldn't be opened. + e1.printStackTrace(); + } + + String aLengthString; + try { + aLengthString = new String(aBuffer.toByteArray(), CHARSET); + } catch (UnsupportedEncodingException e1) { + throw new Error("Specified network encoding [" + CHARSET + + " not available."); + } + + int aLength = Integer.parseInt(aLengthString); + + byte[] aCommand = new byte[aLength]; + try { + mInputStream.read(aCommand, 0, aLength); + } catch (IOException e) { + // TODO close and notify that the connection has closed + e.printStackTrace(); + } + String aCommandString; + try { + aCommandString = new String(aCommand, CHARSET); + } catch (UnsupportedEncodingException e) { + throw new Error("Specified network encoding [" + CHARSET + + " not available."); + } + parseCommand(aCommandString); + + } + + private void parseCommand(String aCommand) { + JSONObject aCommandObject; + String aInstruction; + try { + aCommandObject = new JSONObject(aCommand); + aInstruction = aCommandObject.getString("command"); + if (aInstruction.equals("slide_changed")) { + // TODO: process and notify + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + /** + * Send a valid JSON string to the server. + * + * @param command + * Must be a valid JSON string. + */ + public void sendCommand(String command) { + String aLengthString = Integer.toString(command.length()); + byte[] aLengthBytes; + try { + aLengthBytes = aLengthString.getBytes(CHARSET); + + mOutputStream.write(aLengthBytes); + mOutputStream.write(0x0d); + mOutputStream.write(command.getBytes(CHARSET)); + } catch (UnsupportedEncodingException e) { + throw new Error("Specified network encoding [" + CHARSET + + " not available."); + } catch (IOException e) { + // TODO Notify that stream has closed. + } + } + +} diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java new file mode 100644 index 000000000000..7a9db40a2ed3 --- /dev/null +++ b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java @@ -0,0 +1,66 @@ +package org.libreoffice.impressremote.communication; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; + +public class CommunicationService extends Service { + + /** + * Return the service to clients. + */ + public class CBinder extends Binder { + public CommunicationService getService() { + return CommunicationService.this; + } + } + + private final IBinder mBinder = new CBinder(); + + public enum Protocol { + NETWORK, BLUETOOTH + }; + + private Transmitter mTransmitter; + + private Client mClient; + + @Override + public IBinder onBind(Intent intent) { + // TODO Auto-generated method stub + return mBinder; + } + + @Override + public void onCreate() { + // TODO Create a notification (if configured). + + } + + @Override + public void onDestroy() { + // TODO Destroy the notification (as necessary). + } + + public Transmitter getTransmitter() { + return mTransmitter; + + } + + public void connectTo(Protocol aProtocol, String address) { + switch (aProtocol) { + case NETWORK: + mClient = new NetworkClient(address); + mTransmitter = new Transmitter(mClient); + break; + + } + + } + + public void disconnect() { + + } + +} diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/NetworkClient.java b/android/sdremote/src/org/libreoffice/impressremote/communication/NetworkClient.java new file mode 100644 index 000000000000..1da19411c394 --- /dev/null +++ b/android/sdremote/src/org/libreoffice/impressremote/communication/NetworkClient.java @@ -0,0 +1,37 @@ +package org.libreoffice.impressremote.communication; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +import android.content.Context; +import android.content.ServiceConnection; + +/** + * Standard Network client. Connects to a server using Sockets. + * + * @author Andrzej J.R. Hunt + * + */ +public class NetworkClient extends Client { + + private static final int PORT = 1599; + + public NetworkClient(String ipAddress) { + + Socket aSocket; + try { + aSocket = new Socket(ipAddress, PORT); + mInputStream = aSocket.getInputStream(); + mOutputStream = aSocket.getOutputStream(); + } catch (UnknownHostException e) { + // TODO Tell the user we have a problem + e.printStackTrace(); + } catch (IOException e) { + // TODO As above + e.printStackTrace(); + } + + } + +} diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/Transmitter.java b/android/sdremote/src/org/libreoffice/impressremote/communication/Transmitter.java new file mode 100644 index 000000000000..0e2da45c72b2 --- /dev/null +++ b/android/sdremote/src/org/libreoffice/impressremote/communication/Transmitter.java @@ -0,0 +1,56 @@ +package org.libreoffice.impressremote.communication; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Interface to send commands to the server. + * + * @author Andrzej J.R. Hunt + * + */ +public class Transmitter { + + private Client mClient; + + public Transmitter(Client aClient) { + mClient = aClient; + } + + public void nextTransition() { + JSONObject aCommand = new JSONObject(); + try { + aCommand.put("command", "transition_next"); + } catch (JSONException e) { + e.printStackTrace(); + // TODO: clean + } + // Create JSON + mClient.sendCommand(aCommand.toString()); + } + + public void previousTransition() { + JSONObject aCommand = new JSONObject(); + try { + aCommand.put("command", "transition_previous"); + } catch (JSONException e) { + e.printStackTrace(); + // TODO: clean + } + // Create JSON + mClient.sendCommand(aCommand.toString()); + } + + public void gotoSlide(int slide) { + JSONObject aCommand = new JSONObject(); + try { + aCommand.put("command", "goto_slide"); + aCommand.put("slide_numer", slide); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + mClient.sendCommand(aCommand.toString()); + } + +} |