← Back to team overview

openlp-android team mailing list archive

[Merge] lp:~johanmynhardt/openlp/android into lp:openlp/android

 

Johan Mynhardt has proposed merging lp:~johanmynhardt/openlp/android into lp:openlp/android.

Requested reviews:
  Tim Bentley (trb143)

For more details, see:
https://code.launchpad.net/~johanmynhardt/openlp/android/+merge/60328

Took me a while to fix my conflicts, but now my workflow is at least in proper shape :)

-- 
https://code.launchpad.net/~johanmynhardt/openlp/android/+merge/60328
Your team OpenLP Android Developers is subscribed to branch lp:openlp/android.
=== modified file '.bzrignore'
--- .bzrignore	2011-05-03 22:11:35 +0000
+++ .bzrignore	2011-05-08 21:33:27 +0000
@@ -6,3 +6,4 @@
 Openlp-android.iml
 Openlp-android-working.iml
 .classpath
+.settings

=== added file 'OpenLP.apk'
Binary files OpenLP.apk	1970-01-01 00:00:00 +0000 and OpenLP.apk	2011-05-08 21:33:27 +0000 differ
=== removed file 'OpenLP.apk'
Binary files OpenLP.apk	2011-05-04 20:23:50 +0000 and OpenLP.apk	1970-01-01 00:00:00 +0000 differ
=== modified file 'res/layout/misc.xml'
--- res/layout/misc.xml	2011-05-03 20:40:54 +0000
+++ res/layout/misc.xml	2011-05-08 21:33:27 +0000
@@ -1,23 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android";
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android";
         android:orientation="vertical"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent">
-    <Button android:text="@string/blank"
-            android:id="@+id/blank"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"/>
-    <Button android:text="@string/unblank"
-            android:id="@+id/unblank"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"/>
-    <TextView android:text="@string/alert"
+    <ToggleButton
+            android:id="@+id/toggleDisplayButton"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:textOn="@string/toggleBlankOn"
+            android:textOff="@string/toggleBlankOff"/>
+    <TextView
+            android:text="@string/alert"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"/>
-    <EditText android:id="@+id/alert"
+    <EditText
+            android:id="@+id/alert"
             android:layout_height="wrap_content"
             android:text=""
-            android:layout_width="fill_parent"/>
+            android:inputType="textShortMessage"
+            android:layout_width="fill_parent"
+            android:hint="@string/alertHint"/>
     <Button android:text="@string/send"
             android:id="@+id/send"
             android:layout_width="fill_parent"

=== modified file 'res/layout/service.xml'
--- res/layout/service.xml	2011-04-27 18:33:17 +0000
+++ res/layout/service.xml	2011-05-08 21:33:27 +0000
@@ -1,22 +1,26 @@
 <?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"
-        >
-    <Button android:text="@string/prev"
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android";
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+    <Button
+            android:text="@string/prev"
             android:id="@+id/prev"
             android:layout_width="fill_parent"
-            android:layout_height="wrap_content"/>
-    <Button android:text="@string/next"
+            android:layout_height="wrap_content"
+            />
+    <Button
+            android:text="@string/next"
             android:id="@+id/next"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"/>
-    <TextView
+<!--    <TextView
             android:id="@+id/services"
             android:layout_width="fill_parent"
+            android:layout_height="wrap_content"/>-->
+    <ListView
+            android:id="@+id/list"
+            android:layout_width="fill_parent"
             android:layout_height="wrap_content"/>
-    <ListView android:id="@+id/list"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"/>
 </LinearLayout>

=== removed file 'res/layout/settings.xml'
--- res/layout/settings.xml	2011-05-03 20:52:22 +0000
+++ res/layout/settings.xml	1970-01-01 00:00:00 +0000
@@ -1,28 +0,0 @@
-<?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:text="@string/url"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"/>
-    <EditText android:id="@+id/url"
-              android:layout_height="wrap_content"
-              android:text="192.168.1.1"
-              android:inputType="textUri"
-              android:layout_width="fill_parent"/>
-    <TextView android:text="@string/port"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"/>
-    <EditText android:id="@+id/port"
-              android:layout_height="wrap_content"
-              android:text="@string/portDefaultValue"
-              android:layout_width="fill_parent"
-              android:inputType="number"/>
-    <Button android:text="@string/save"
-            android:id="@+id/save"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"/>
-</LinearLayout>
-

=== modified file 'res/layout/slide.xml'
--- res/layout/slide.xml	2011-04-27 18:33:17 +0000
+++ res/layout/slide.xml	2011-05-08 21:33:27 +0000
@@ -1,22 +1,21 @@
 <?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"
-        >
-    <Button android:text="@string/prev"
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android";
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+    <Button
+            android:text="@string/prev"
             android:id="@+id/prev" android:layout_width="fill_parent"
             android:layout_height="wrap_content"/>
-    <Button android:text="@string/next"
+    <Button
+            android:text="@string/next"
             android:id="@+id/next"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"/>
-    <TextView
-            android:id="@+id/slides"
-            android:layout_width="fill_parent"
+    <ListView
+            android:id="@+id/list"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"/>
-    <ListView android:id="@+id/list"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"/>
 
 </LinearLayout>

=== added file 'res/values-en/defaultValues.xml'
--- res/values-en/defaultValues.xml	1970-01-01 00:00:00 +0000
+++ res/values-en/defaultValues.xml	2011-05-08 21:33:27 +0000
@@ -0,0 +1,9 @@
+<resources>
+    <!-- STRING -->
+    <string name="hostDefaultValue">192.168.1.1</string>
+    <string name="portDefaultValue">4316</string>
+
+    <!-- INTEGER -->
+    <integer name="socketTimeoutDefaultValue">3000</integer>
+    <integer name="connectionTimeoutDefaultValue">3000</integer>
+</resources>
\ No newline at end of file

=== added file 'res/values-en/httpClientTimeoutValues.xml'
--- res/values-en/httpClientTimeoutValues.xml	1970-01-01 00:00:00 +0000
+++ res/values-en/httpClientTimeoutValues.xml	2011-05-08 21:33:27 +0000
@@ -0,0 +1,16 @@
+<resources>
+    <string-array name="socketValueEntries">
+		<item>3000</item>
+		<item>4000</item>
+		<item>5000</item>
+		<item>8000</item>
+		<item>10000</item>
+	</string-array>
+	<string-array name="socketValues">
+		<item>3000</item>
+		<item>4000</item>
+		<item>5000</item>
+		<item>8000</item>
+		<item>10000</item>
+	</string-array>
+</resources>
\ No newline at end of file

=== added file 'res/values-en/keyStrings.xml'
--- res/values-en/keyStrings.xml	1970-01-01 00:00:00 +0000
+++ res/values-en/keyStrings.xml	2011-05-08 21:33:27 +0000
@@ -0,0 +1,8 @@
+<resources>
+    <string name="keyEnableCustomTimeout">enableCustomTimeout</string>
+    <string name="keyConnectionTimeout">connectionTimeout</string>
+    <string name="keySocketTimeout">socketTimeout</string>
+    <string name="keyHost">keyHost</string>
+    <string name="keyPort">keyPort</string>
+    <string name="keySharedPreferences">keySharedPreferences</string>
+</resources>
\ No newline at end of file

=== modified file 'res/values-en/strings.xml' (properties changed: +x to -x)
--- res/values-en/strings.xml	2011-05-03 22:35:46 +0000
+++ res/values-en/strings.xml	2011-05-08 21:33:27 +0000
@@ -6,26 +6,36 @@
     <string name="exit">Exit</string>
     <string name="prev">Previous</string>
     <string name="next">Next</string>
+    <string name="previousServiceItem">Previous Item</string>
+    <string name="nextServiceItem">Next Item</string>
+    <string name="previousSlide">Previous Slide</string>
+    <string name="nextSlide">Next Slide</string>
     <string name="blank">Blank</string>
     <string name="unblank">Unblank</string>
     <string name="alert">Alert:</string>
     <string name="send">Send</string>
     <string name="Slide">Slide</string>
+    <string name="slides">Slides</string>
     <string name="Service">Service</string>
     <string name="misc">Miscellaneous</string>
+    <string name="preferenceCategoryTitleServer">Server</string>
     <string name="url">Server</string>
-    <string name="urlDefaultValue">192.168.1.1</string>
     <string name="port">Port</string>
-    <string name="portDefaultValue">4316</string>
-    <string name="keyEnableCustomTimeout">enableCustomTimeout</string>
+    <string name="enableCustomTimeouts">Enable Custom Timeouts</string>
+    <string name="customTimeoutsSummary">Check to modify timeout settings</string>
     <string name="customTimeout">Custom Timeout</string>
     <string name="socketTimeout">Socket Timeout</string>
-    <string name="keySocketTimeout">socketTimeout</string>
-    <string name="connectionTimeout">Connection Timout</string>
-    <string name="keyConnectionTimeout">connectionTimeout</string>
+    <string name="socketTimeoutSummary">Select a value (milliseconds)</string>
+    <string name="connectionTimeout">Connection Timeout</string>
+    <string name="connectionTimeoutSummary">Select a value (milliseconds)</string>
     <string name="save">Save</string>
     <string name="unable">Unable to load page -</string>
     <string name="fail">Connection failed</string>
     <string name="jsonfail">JSON failed</string>
     <string name="loading">Connecting...</string>
+    <string name="toggleBlankOn">Display Blanked</string>
+    <string name="toggleBlankOff">Display Unblanked</string>
+    <string name="loadingServiceItems">Loading Service Items...</string>
+    <string name="loadingSlideItems">Loading Slide Items...</string>
+
 </resources>

=== added file 'res/values/defaultValues.xml'
--- res/values/defaultValues.xml	1970-01-01 00:00:00 +0000
+++ res/values/defaultValues.xml	2011-05-08 21:33:27 +0000
@@ -0,0 +1,9 @@
+<resources>
+    <!-- STRING -->
+    <string name="hostDefaultValue">192.168.1.1</string>
+    <string name="portDefaultValue">4316</string>
+
+    <!-- INTEGER -->
+    <integer name="socketTimeoutDefaultValue">3000</integer>
+    <integer name="connectionTimeoutDefaultValue">3000</integer>
+</resources>
\ No newline at end of file

=== removed file 'res/values/integers.xml'
--- res/values/integers.xml	2011-04-30 22:36:35 +0000
+++ res/values/integers.xml	1970-01-01 00:00:00 +0000
@@ -1,4 +0,0 @@
-<resources>
-    <integer name="socketTimeoutDefaultValue">3000</integer>
-    <integer name="connectionTimeoutDefaultValue">3000</integer>
-</resources>
\ No newline at end of file

=== added file 'res/values/keyStrings.xml'
--- res/values/keyStrings.xml	1970-01-01 00:00:00 +0000
+++ res/values/keyStrings.xml	2011-05-08 21:33:27 +0000
@@ -0,0 +1,8 @@
+<resources>
+    <string name="keyEnableCustomTimeout">enableCustomTimeout</string>
+    <string name="keyConnectionTimeout">connectionTimeout</string>
+    <string name="keySocketTimeout">socketTimeout</string>
+    <string name="keyHost">keyHost</string>
+    <string name="keyPort">keyPort</string>
+    <string name="keySharedPreferences">keySharedPreferences</string>
+</resources>
\ No newline at end of file

=== modified file 'res/values/strings.xml'
--- res/values/strings.xml	2011-05-03 22:35:46 +0000
+++ res/values/strings.xml	2011-05-08 21:33:27 +0000
@@ -6,26 +6,38 @@
     <string name="exit">Exit</string>
     <string name="prev">Previous</string>
     <string name="next">Next</string>
+    <string name="previousServiceItem">Previous Item</string>
+    <string name="nextServiceItem">Next Item</string>
+    <string name="previousSlide">Previous Slide</string>
+    <string name="nextSlide">Next Slide</string>
     <string name="blank">Blank</string>
     <string name="unblank">Unblank</string>
     <string name="alert">Alert:</string>
+    <string name="alertHint">Enter alert message</string>
     <string name="send">Send</string>
     <string name="Slide">Slide</string>
+    <string name="slides">Slides</string>
     <string name="Service">Service</string>
     <string name="misc">Miscellaneous</string>
+    <string name="preferenceCategoryTitleServer">Server</string>
     <string name="url">Server</string>
-    <string name="urlDefaultValue">192.168.1.1</string>
+    <string name="urlHint">Hostname or IP</string>
     <string name="port">Port</string>
-    <string name="portDefaultValue">4316</string>
-    <string name="keyEnableCustomTimeout">enableCustomTimeout</string>
+    <string name="enableCustomTimeouts">Enable Custom Timeouts</string>
+    <string name="customTimeoutsSummary">Check to modify timeout settings</string>
     <string name="customTimeout">Custom Timeout</string>
     <string name="socketTimeout">Socket Timeout</string>
-    <string name="keySocketTimeout">socketTimeout</string>
-    <string name="connectionTimeout">Connection Timout</string>
-    <string name="keyConnectionTimeout">connectionTimeout</string>
+    <string name="socketTimeoutSummary">Select a value (milliseconds)</string>
+    <string name="connectionTimeout">Connection Timeout</string>
+    <string name="connectionTimeoutSummary">Select a value (milliseconds)</string>
     <string name="save">Save</string>
     <string name="unable">Unable to load page -</string>
     <string name="fail">Connection failed</string>
     <string name="jsonfail">JSON failed</string>
     <string name="loading">Connecting...</string>
+    <string name="toggleBlankOn">Display Blanked</string>
+    <string name="toggleBlankOff">Display Unblanked</string>
+    <string name="loadingServiceItems">Loading Service Items...</string>
+    <string name="loadingSlideItems">Loading Slide Items...</string>
+
 </resources>

=== modified file 'res/xml/preferences.xml'
--- res/xml/preferences.xml	2011-05-03 20:52:22 +0000
+++ res/xml/preferences.xml	2011-05-08 21:33:27 +0000
@@ -2,30 +2,30 @@
 <PreferenceScreen
         xmlns:android="http://schemas.android.com/apk/res/android";>
     <PreferenceCategory
-            android:title="Server">
+            android:title="@string/preferenceCategoryTitleServer">
         <EditTextPreference
                 android:title="@string/url"
-                android:key="url"
-                android:defaultValue="192.168.1.1"
-                android:inputType="phone"
+                android:key="@string/keyHost"
+                android:hint="@string/urlHint"
+                android:inputType="textUri"
                 android:name="@string/url"/>
         <EditTextPreference
                 android:defaultValue="@string/portDefaultValue"
                 android:title="@string/port"
-                android:key="port"
+                android:key="@string/keyPort"
                 android:name="@string/url"
                 android:inputType="number"/>
     </PreferenceCategory>
     <PreferenceCategory
             android:title="@string/customTimeout">
         <CheckBoxPreference
-                android:title="Enable Custom Timeouts"
+                android:title="@string/enableCustomTimeouts"
                 android:key="@string/keyEnableCustomTimeout"
-                android:summary="Check to modify timeout settings"/>
+                android:summary="@string/customTimeoutsSummary"/>
         <ListPreference
                 android:title="@string/connectionTimeout"
                 android:key="@string/keyConnectionTimeout"
-                android:summary="Select a value (milliseconds)"
+                android:summary="@string/connectionTimeoutSummary"
                 android:dependency="@string/keyEnableCustomTimeout"
                 android:entries="@array/socketValueEntries"
                 android:entryValues="@array/socketValues"
@@ -33,7 +33,7 @@
         <ListPreference
                 android:title="@string/socketTimeout"
                 android:key="@string/keySocketTimeout"
-                android:summary="Select a value (milliseconds)"
+                android:summary="@string/socketTimeoutSummary"
                 android:dependency="@string/keyEnableCustomTimeout"
                 android:entries="@array/socketValueEntries"
                 android:entryValues="@array/socketValues"

=== modified file 'src/org/openlp/android/Misc.java'
--- src/org/openlp/android/Misc.java	2011-05-03 20:52:22 +0000
+++ src/org/openlp/android/Misc.java	2011-05-08 21:33:27 +0000
@@ -22,6 +22,8 @@
  *******************************************************************************/
 package org.openlp.android;
 
+import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
@@ -32,38 +34,17 @@
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.Toast;
+import android.widget.ToggleButton;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.json.JSONStringer;
+import org.openlp.android.api.Api;
+import org.openlp.android.utility.WebCallAsyncTask;
 
 import java.io.UnsupportedEncodingException;
 
-public class Misc extends OpenLPActivity implements OpenLP.ApiActions {
-    public Button.OnClickListener mBlank = new Button.OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            String urlAll = String.format("%s:%s%s", getURL(), getPort(), DISPLAY_HIDE);
-            try {
-                webCall(urlAll);
-            }
-            catch (Exception e) {
-                Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
-            }
-        }
-    };
-
-    public Button.OnClickListener mUnblank = new Button.OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            String urlAll = String.format("%s:%s%s", getURL(), getPort(), DISPLAY_SHOW);
-            try {
-                webCall(urlAll);
-            }
-            catch (Exception e) {
-                Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
-            }
-        }
-    };
+public class Misc extends Activity implements Api {
+    private final Context context = this;
 
     public Button.OnClickListener mSend = new Button.OnClickListener() {
         @Override
@@ -77,14 +58,14 @@
                 alert = java.net.URLEncoder.encode(alert, "UTF-8");
             }
             catch (JSONException e) {
-                alert = e.toString();
+                alert = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
             }
             catch (UnsupportedEncodingException e) {
-                alert = e.toString();
+                alert = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
             }
-            String urlAll = String.format("%s:%s%s%s", getURL(), getPort(), ALERT, alert);
+
             try {
-                webCall(urlAll);
+                new WebCallAsyncTask(context).execute(String.format("%s%s", ALERT, alert));
             }
             catch (Exception e) {
                 Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
@@ -97,12 +78,37 @@
         super.onCreate(savedInstanceState);
         Log.i(LOG_TAG, "onCreate");
         setContentView(R.layout.misc);
-        findViewById(R.id.blank).setOnClickListener(mBlank);
-        findViewById(R.id.unblank).setOnClickListener(mUnblank);
+
+        final ToggleButton toggleButton = (ToggleButton) findViewById(R.id.toggleDisplayButton);
+
+        toggleButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                try {
+                    if (!toggleButton.isChecked()) {
+                        new WebCallAsyncTask(context).execute(DISPLAY_SHOW);
+                    }
+                    else {
+                        new WebCallAsyncTask(context).execute(DISPLAY_HIDE);
+                    }
+                }
+                catch (Exception e) {
+                    Toast.makeText(context, String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage()),
+                            Toast.LENGTH_SHORT).show();
+                }
+            }
+        });
+
         findViewById(R.id.send).setOnClickListener(mSend);
     }
 
     @Override
+    protected void onResume() {
+        super.onResume();
+        Log.d(LOG_TAG, "Resume");
+    }
+
+    @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.menu, menu);

=== modified file 'src/org/openlp/android/OpenLP.java'
--- src/org/openlp/android/OpenLP.java	2011-05-03 21:01:12 +0000
+++ src/org/openlp/android/OpenLP.java	2011-05-08 21:33:27 +0000
@@ -39,59 +39,33 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
-        Log.i(LOG_TAG, "onCreate");
         setContentView(R.layout.main);
 
-        TabHost tabHost = getTabHost(); // The activity TabHost
-        TabHost.TabSpec spec; // Reusable TabSpec for each tab
-        Intent intent; // Reusable Intent for each tab
-
-        // Create an Intent to launch an Activity for the tab (to be reused)
-        intent = new Intent().setClass(this, Slide.class);
-
-        // Initialise a TabSpec for each tab and add it to the TabHost
-        Log.i(LOG_TAG, "Initialise Slide TabSpec");
-        spec = tabHost.newTabSpec("artists").setIndicator("Slide")
-                .setContent(intent);
-        tabHost.addTab(spec);
-        tabHost.setCurrentTab(1);
-
-        // Do the same for the other tabs
-        intent = new Intent().setClass(this, Service.class);
-        Log.i(LOG_TAG, "Initialise Service TabSpec");
-        spec = tabHost.newTabSpec("albums").setIndicator("Service")
-                .setContent(intent);
-        tabHost.addTab(spec);
-
-        // Do the same for the other tabs
-        intent = new Intent().setClass(this, Misc.class);
-        Log.i(LOG_TAG, "Initialise Misc TabSpec");
-        spec = tabHost.newTabSpec("albums").setIndicator("Misc")
-                .setContent(intent);
-        tabHost.addTab(spec);
-
-        if (getSharedPreferences("prefs", Context.MODE_PRIVATE).getString("url", "NONE").equals("NONE")) {
+        if (getSharedPreferences(getString(R.string.keySharedPreferences), Context.MODE_PRIVATE)
+                .getString(getString(R.string.keyHost), "NONE").equals("NONE")
+                || getSharedPreferences(getString(R.string.keySharedPreferences), Context.MODE_PRIVATE).getString(getString(R.string.keyHost), null).equals(null)
+                ) {
             Log.d(LOG_TAG, "URL preference not set. Starting preference activity...");
             Intent preferenceIntent = new Intent(this, Preferences.class);
             startActivity(preferenceIntent);
         }
+        TabHost tabHost = getTabHost();
+
+        tabHost.addTab(tabHost.newTabSpec("albums")
+                .setIndicator("Service")
+                .setContent(new Intent(this, Service.class)));
+
+        tabHost.addTab(tabHost.newTabSpec("artists")
+                .setIndicator("Slide")
+                .setContent(new Intent(this, Slide.class)));
+
+        tabHost.addTab(tabHost.newTabSpec("albums")
+                .setIndicator("Misc")
+                .setContent(new Intent(this, Misc.class)));
+
     }
 
     private final String LOG_TAG = OpenLP.class.getName();
 
-    public interface ApiActions {
-        public final String LIVE_NEXT = "/api/controller/live/next";
-        public final String LIVE_PREVIOUS = "/api/controller/live/previous";
-        public final String LIVE_TEXT = "/api/controller/live/text";
-
-        public final String SERVICE_NEXT = "/api/service/next";
-        public final String SERVICE_PREVIOUS = "/api/service/previous";
-        public final String SERVICE_LIST = "/api/service/list";
-
-        public final String DISPLAY_HIDE = "/api/display/hide";
-        public final String DISPLAY_SHOW = "/api/display/show";
-
-        public final String ALERT = "/api/alert?data=";
-    }
+
 }
\ No newline at end of file

=== removed file 'src/org/openlp/android/OpenLPActivity.java'
--- src/org/openlp/android/OpenLPActivity.java	2011-05-04 10:29:58 +0000
+++ src/org/openlp/android/OpenLPActivity.java	1970-01-01 00:00:00 +0000
@@ -1,55 +0,0 @@
-/******************************************************************************
- * OpenLP - Open Source Lyrics Projection                                      *
- * --------------------------------------------------------------------------- *
- * Copyright (c) 2008-2011 Raoul Snyman                                        *
- * Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      *
- * Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,        *
- * Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      *
- * Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund             *
- * --------------------------------------------------------------------------- *
- * This program is free software; you can redistribute it and/or modify it     *
- * under the terms of the GNU General Public License as published by the Free  *
- * Software Foundation; version 2 of the License.                              *
- *                                                                             *
- * This program is distributed in the hope that it will be useful, but WITHOUT *
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
- * more details.                                                               *
- *                                                                             *
- * You should have received a copy of the GNU General Public License along     *
- * with this program; if not, write to the Free Software Foundation, Inc., 59  *
- * Temple Place, Suite 330, Boston, MA 02111-1307 USA                          *
- *******************************************************************************/
-package org.openlp.android;
-
-import android.app.Activity;
-import android.content.SharedPreferences;
-import android.util.Log;
-import org.openlp.android.utility.OpenLPHttpClient;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-public class OpenLPActivity extends Activity {
-    public String getURL() {
-        SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
-        return "http://"; + prefs.getString("url", getString(R.string.urlDefaultValue));
-    }
-
-    public String getPort() {
-        SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
-        return prefs.getString("port", getString(R.string.portDefaultValue));
-    }
-
-    public void webCall(String url) throws IOException, URISyntaxException {
-        OpenLPHttpClient httpclient = new OpenLPHttpClient(getApplicationContext());
-        httpclient.setUrl(new URL(url));
-
-        Log.d(LOG_TAG, "Executing request: " + httpclient.getUrl().toString());
-        httpclient.execute();
-
-    }
-
-    private String LOG_TAG = OpenLPActivity.class.getName();
-}

=== modified file 'src/org/openlp/android/Preferences.java'
--- src/org/openlp/android/Preferences.java	2011-05-02 21:10:36 +0000
+++ src/org/openlp/android/Preferences.java	2011-05-08 21:33:27 +0000
@@ -28,15 +28,15 @@
 
 /**
  * Credits:
- *  http://www.kaloer.com/android-preferences
- *  http://androidpartaker.wordpress.com/2010/07/11/android-preferences/
+ * http://www.kaloer.com/android-preferences
+ * http://androidpartaker.wordpress.com/2010/07/11/android-preferences/
  */
 public class Preferences extends PreferenceActivity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         Log.d(LOG_TAG, "Launching preferences");
-        getPreferenceManager().setSharedPreferencesName("prefs");
+        getPreferenceManager().setSharedPreferencesName(getString(R.string.keySharedPreferences));
         addPreferencesFromResource(R.xml.preferences);
     }
 

=== modified file 'src/org/openlp/android/Service.java'
--- src/org/openlp/android/Service.java	2011-05-04 10:29:58 +0000
+++ src/org/openlp/android/Service.java	2011-05-08 21:33:27 +0000
@@ -22,7 +22,9 @@
  *******************************************************************************/
 package org.openlp.android;
 
+import android.app.Activity;
 import android.app.ProgressDialog;
+import android.content.Context;
 import android.content.Intent;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -34,20 +36,20 @@
 import android.widget.ArrayAdapter;
 import android.widget.Button;
 import android.widget.ListView;
-import android.widget.TextView;
 import android.widget.Toast;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.openlp.android.api.Api;
 import org.openlp.android.utility.OpenLPHttpClient;
 import org.openlp.android.utility.StringHelper;
+import org.openlp.android.utility.WebCallAsyncTask;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URISyntaxException;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -55,10 +57,11 @@
 /**
  * Activity for managing service objects.
  */
-public class Service extends OpenLPActivity implements OpenLP.ApiActions {
+public class Service extends Activity implements Api {
     private final String LOG_TAG = Service.class.getName();
+    private final Context context = this;
 
-    private TextView txt;
+    private ListView listView;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -66,29 +69,29 @@
         Log.i(LOG_TAG, "onCreate");
 
         setContentView(R.layout.service);
+        listView = (ListView) findViewById(R.id.list);
         findViewById(R.id.prev).setOnClickListener(mPrev);
         findViewById(R.id.next).setOnClickListener(mNext);
-        txt = (TextView) findViewById(R.id.services);
-        txt.setText(R.string.loading);
-
-        String urlAll = String.format("%s:%s%s", getURL(), getPort(), SERVICE_LIST);
-
-        new FetchServiceItemsTask(this).execute(urlAll);
     }
 
-    private void setTextViewText(String text) {
-        txt.setText(text);
+    @Override
+    protected void onResume() {
+        super.onResume();
+        Log.d(LOG_TAG, "Resume");
+
+        new FetchServiceItemsTask(this).execute(SERVICE_LIST);
     }
 
     public Button.OnClickListener mPrev = new Button.OnClickListener() {
         @Override
         public void onClick(View v) {
-            String urlAll = String.format("%s:%s%s", getURL(), getPort(), SERVICE_PREVIOUS);
             try {
-                webCall(urlAll);
+                new WebCallAsyncTask(context).execute(SERVICE_PREVIOUS);
             }
             catch (Exception e) {
-                Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
+                Toast.makeText(getApplicationContext(),
+                        String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage()),
+                        Toast.LENGTH_SHORT).show();
             }
         }
     };
@@ -96,12 +99,13 @@
     public Button.OnClickListener mNext = new Button.OnClickListener() {
         @Override
         public void onClick(View v) {
-            String urlAll = String.format("%s:%s%s", getURL(), getPort(), SERVICE_NEXT);
             try {
-                webCall(urlAll);
+                new WebCallAsyncTask(context).execute(SERVICE_NEXT);
             }
             catch (Exception e) {
-                Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
+                Toast.makeText(getApplicationContext(),
+                        String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage()),
+                        Toast.LENGTH_SHORT).show();
             }
         }
     };
@@ -115,7 +119,6 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        // Handle item selection
         switch (item.getItemId()) {
             case R.id.preferences:
                 startActivity(new Intent(this, Preferences.class));
@@ -128,9 +131,10 @@
     /**
      * Asynchronous task to fetch the service items.
      */
-    class FetchServiceItemsTask extends AsyncTask<String, String[], String> {
+    class FetchServiceItemsTask extends AsyncTask<String, String[], Void> {
         Service serviceActivity;
         ProgressDialog progressDialog;
+        String error;
 
         FetchServiceItemsTask(Service serviceActivity) {
             this.serviceActivity = serviceActivity;
@@ -139,22 +143,27 @@
         @Override
         protected void onPreExecute() {
             super.onPreExecute();
-            progressDialog = ProgressDialog.show(Service.this, getString(R.string.loading), "Loading service items...");
+            progressDialog = ProgressDialog.show(Service.this, getString(R.string.loading),
+                    getString(R.string.loadingServiceItems));
         }
 
         @Override
-        protected String doInBackground(String... strings) {
+        protected Void doInBackground(String... strings) {
             OpenLPHttpClient httpClient = new OpenLPHttpClient(getApplicationContext());
-            HttpResponse response;
-            String returnString = null;
+            HttpResponse response = null;
+            String returnString = "";
 
             Log.d(LOG_TAG, "Processing:" + Arrays.asList(strings));
-
             try {
-                httpClient.setUrl(new URL(strings[0]));
-                response = httpClient.execute();
+                httpClient.setUrl(strings[0]);
+                if (httpClient.getUrl().getHost().trim().length() <= 0) {
+                    startActivity(new Intent(serviceActivity, Preferences.class));
+                }
+                else {
+                    response = httpClient.execute();
+                }
 
-                if (response.getStatusLine().getStatusCode() == 200) {
+                if (response != null && response.getStatusLine().getStatusCode() == 200) {
                     HttpEntity entity = response.getEntity();
                     // If the response does not enclose an entity, there is no need
                     // to worry about connection release
@@ -168,45 +177,53 @@
                         JSONObject jObject = new JSONObject(result);
                         JSONObject results = jObject.getJSONObject("results");
                         JSONArray items = results.getJSONArray("items");
-                        List<String> result1 = new ArrayList<String>();
+                        List<String> serviceItemList = new ArrayList<String>();
                         returnString = "";
 
                         for (int i = 0; i < items.length(); i++) {
-                            result1.add(items.getJSONObject(i).getString("title"));
+                            serviceItemList.add(items.getJSONObject(i).getString("title"));
                         }
 
                         instream.close();
-                        publishProgress(result1.toArray(new String[]{}));
+
+                        Log.i(LOG_TAG, String.format("Service Items: %s", serviceItemList));
+                        publishProgress(serviceItemList.toArray(new String[]{}));
                     }
                 }
                 else {
-                    returnString = String.format("Unable to load page - %s", response.getStatusLine());
+                    returnString = String.format("%s %s", getString(R.string.unable), response);
                 }
             }
             catch (JSONException ex) {
-                returnString = "JSON failed; " + ex.getMessage();
+                returnString = String.format("%s: %s", ex.getClass().getSimpleName(), ex.getMessage());
             }
             catch (IOException e) {
-                returnString = "IOException: " + e.getMessage();
+                returnString = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
             }
             catch (URISyntaxException e) {
-                returnString = "URISyntaxException: " + e.getMessage();
-            }
-            return returnString;
+                returnString = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
+            }
+
+            if (returnString.trim().length() > 0) {
+                error = returnString;
+                Log.e(LOG_TAG, returnString);
+            }
+            return null;
         }
 
         @Override
         protected void onProgressUpdate(String[]... values) {
             super.onProgressUpdate(values);
-            ListView lv1 = (ListView) findViewById(R.id.list);
-            lv1.setAdapter(new ArrayAdapter<String>(serviceActivity, android.R.layout.simple_list_item_1, values[0]));
+            listView.setAdapter(new ArrayAdapter<String>(serviceActivity, android.R.layout.simple_list_item_1, values[0]));
         }
 
         @Override
-        protected void onPostExecute(String s) {
-            super.onPostExecute(s);
-            serviceActivity.setTextViewText(s);
+        protected void onPostExecute(Void v) {
+            super.onPostExecute(v);
             progressDialog.dismiss();
+            if (error != null && error.trim().length() > 0) {
+                Toast.makeText(context, error, Toast.LENGTH_LONG).show();
+            }
         }
     }
 }
\ No newline at end of file

=== modified file 'src/org/openlp/android/Slide.java'
--- src/org/openlp/android/Slide.java	2011-05-04 05:21:09 +0000
+++ src/org/openlp/android/Slide.java	2011-05-08 21:33:27 +0000
@@ -22,7 +22,9 @@
  *******************************************************************************/
 package org.openlp.android;
 
+import android.app.Activity;
 import android.app.ProgressDialog;
+import android.content.Context;
 import android.content.Intent;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -34,50 +36,58 @@
 import android.widget.ArrayAdapter;
 import android.widget.Button;
 import android.widget.ListView;
-import android.widget.TextView;
 import android.widget.Toast;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.openlp.android.api.Api;
 import org.openlp.android.utility.OpenLPHttpClient;
 import org.openlp.android.utility.StringHelper;
+import org.openlp.android.utility.WebCallAsyncTask;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-public class Slide extends OpenLPActivity implements OpenLP.ApiActions {
+public class Slide extends Activity implements Api {
+    private final Context context = this;
     private final String LOG_TAG = Slide.class.getName();
-    private TextView txt;
+    private ListView slideList;
 
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        Log.i(LOG_TAG, "Creating view");
+        Log.d(LOG_TAG, "onCreate");
         setContentView(R.layout.slide);
+
+        slideList = (ListView) findViewById(R.id.list);
         findViewById(R.id.prev).setOnClickListener(mPrev);
         findViewById(R.id.next).setOnClickListener(mNext);
-        txt = (TextView) findViewById(R.id.slides);
-        txt.setText(R.string.loading);
-
-        final String urlAll = String.format("%s:%s%s", getURL(), getPort(), LIVE_TEXT);
-        new FetchSlideItemsTask(this).execute(urlAll);
+
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        Log.d(LOG_TAG, "Resume");
+
+        new FetchSlideItemsTask(this).execute(LIVE_TEXT);
     }
 
     public Button.OnClickListener mPrev = new Button.OnClickListener() {
         public void onClick(View v) {
-            String urlAll = String.format("%s:%s%s", getURL(), getPort(), LIVE_PREVIOUS);
             try {
-                webCall(urlAll);
+                new WebCallAsyncTask(context).execute(LIVE_PREVIOUS);
             }
             catch (Exception e) {
-                Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
+                Toast.makeText(getApplicationContext(),
+                        String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage()),
+                        Toast.LENGTH_SHORT).show();
                 Log.e(LOG_TAG, e.toString(), e);
             }
         }
@@ -85,12 +95,13 @@
 
     public Button.OnClickListener mNext = new Button.OnClickListener() {
         public void onClick(View v) {
-            String urlAll = getURL() + ":" + getPort() + LIVE_NEXT;
             try {
-                webCall(urlAll);
+                new WebCallAsyncTask(context).execute(LIVE_NEXT);
             }
             catch (Exception e) {
-                Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
+                Toast.makeText(getApplicationContext(),
+                        String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage()),
+                        Toast.LENGTH_SHORT).show();
                 Log.e(LOG_TAG, e.toString(), e);
             }
         }
@@ -115,13 +126,10 @@
         }
     }
 
-    void setTextViewText(String text) {
-        txt.setText(text);
-    }
-
-    class FetchSlideItemsTask extends AsyncTask<String, String[], String> {
+    class FetchSlideItemsTask extends AsyncTask<String, String[], Void> {
         Slide slideActivity;
         ProgressDialog progressDialog;
+        String error;
 
         FetchSlideItemsTask(Slide slideActivity) {
             this.slideActivity = slideActivity;
@@ -130,22 +138,26 @@
         @Override
         protected void onPreExecute() {
             super.onPreExecute();
-            progressDialog = ProgressDialog.show(Slide.this, getString(R.string.loading), "Loading slide items...");
+            progressDialog = ProgressDialog.show(Slide.this, getString(R.string.loading), getString(R.string.loadingSlideItems));
         }
 
         @Override
-        protected String doInBackground(String... strings) {
+        protected Void doInBackground(String... strings) {
             OpenLPHttpClient httpClient = new OpenLPHttpClient(getApplicationContext());
-            HttpResponse response;
-            String returnString = null;
+            HttpResponse response = null;
+            String returnString = "";
 
             Log.d(LOG_TAG, "Processing:" + Arrays.asList(strings));
             try {
-                httpClient.setUrl(new URL(strings[0]));
-                response = httpClient.execute();
+                httpClient.setUrl(strings[0]);
+                if (httpClient.getUrl().getHost().trim().length() <= 0) {
+                    startActivity(new Intent(slideActivity, Preferences.class));
+                }
+                else {
+                    response = httpClient.execute();
+                }
 
-                if (response.getStatusLine().getStatusCode() == 200) {
-                    Log.d(LOG_TAG, "Connection Established. Getting content.");
+                if (response != null && response.getStatusLine().getStatusCode() == 200) {
                     HttpEntity entity = response.getEntity();
                     // If the response does not enclose an entity, there is no need
                     // to worry about connection release
@@ -168,46 +180,54 @@
 
                         for (int i = 0; i < slides.length(); i++) {
                             result1.add(slides.getJSONObject(i).getString("text"));
-						}
+                        }
 
-						instream.close();
-						publishProgress(result1.toArray(new String[]{}));
-					}
+                        instream.close();
+                        Log.d(LOG_TAG, String.format("slides: %s", result1));
+                        publishProgress(result1.toArray(new String[]{}));
+                    }
                 }
                 else {
-                    returnString = "Unable to load page - " + response.getStatusLine();
+                    returnString = String.format("%s %s", getString(R.string.unable), response);
                 }
             }
             catch (JSONException ex) {
-                returnString = "JSON failed: " + ex.getMessage();
+                returnString = String.format("%s: %s", ex.getClass().getSimpleName(), ex.getMessage());
             }
             catch (MalformedURLException e) {
-                returnString = "MalformedURLException: " + e.getMessage();
+                returnString = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
             }
             catch (IOException e) {
-                returnString = "IOException: " + e.getMessage();
+                returnString = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
             }
             catch (URISyntaxException e) {
-                returnString = "URISyntaxException: " + e.getMessage();
+                returnString = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
             }
             catch (IllegalArgumentException e) {
-                returnString = "IllegalArgumentException: " + e.getMessage();
-            }
-            return returnString;
+                returnString = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
+            }
+
+            if (returnString.trim().length() > 0) {
+                error = returnString;
+                Log.e(LOG_TAG, returnString);
+            }
+            return null;
         }
 
         @Override
-        protected void onPostExecute(String s) {
-            super.onPostExecute(s);
+        protected void onPostExecute(Void aVoid) {
+            super.onPostExecute(aVoid);
             progressDialog.dismiss();
-            slideActivity.setTextViewText(s);
+
+            if (error != null && error.trim().length() > 0) {
+                Toast.makeText(context, error, Toast.LENGTH_LONG).show();
+            }
         }
 
         @Override
         protected void onProgressUpdate(String[]... values) {
             super.onProgressUpdate(values);
-            ListView lv1 = (ListView) findViewById(R.id.list);
-            lv1.setAdapter(new ArrayAdapter<String>(slideActivity, android.R.layout.simple_list_item_1, values[0]));
+            slideList.setAdapter(new ArrayAdapter<String>(slideActivity, android.R.layout.simple_list_item_1, values[0]));
         }
     }
 }

=== added directory 'src/org/openlp/android/api'
=== added file 'src/org/openlp/android/api/Api.java'
--- src/org/openlp/android/api/Api.java	1970-01-01 00:00:00 +0000
+++ src/org/openlp/android/api/Api.java	2011-05-08 21:33:27 +0000
@@ -0,0 +1,108 @@
+/******************************************************************************
+ * OpenLP - Open Source Lyrics Projection                                      *
+ * --------------------------------------------------------------------------- *
+ * Copyright (c) 2008-2011 Raoul Snyman                                        *
+ * Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      *
+ * Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,        *
+ * Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      *
+ * Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund             *
+ * --------------------------------------------------------------------------- *
+ * This program is free software; you can redistribute it and/or modify it     *
+ * under the terms of the GNU General Public License as published by the Free  *
+ * Software Foundation; version 2 of the License.                              *
+ *                                                                             *
+ * This program is distributed in the hope that it will be useful, but WITHOUT *
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
+ * more details.                                                               *
+ *                                                                             *
+ * You should have received a copy of the GNU General Public License along     *
+ * with this program; if not, write to the Free Software Foundation, Inc., 59  *
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA                          *
+ *******************************************************************************/
+package org.openlp.android.api;
+
+/**
+ * <h1>Routes:</h1>
+ * <p/>
+ * <pre>
+ * ``/``
+ * Go to the web interface.
+ *
+ * ``/files/{filename}``
+ *
+ * ``/api/poll``
+ * {"results": {"type": "controller"}}
+ * Or, if there were no results, False::
+ * {"results": False}
+ *
+ * ``/api/display/{hide|show}``
+ * Blank or unblank the screen.
+ *
+ * ``/api/alert``
+ * {"request": {"text": "<your alert text>"}}
+ * ``/api/controller/{live|preview}/{action}``
+ * ``next``
+ * Load the next slide.
+ *
+ * ``previous``
+ * Load the previous slide.
+ *
+ * ``set``
+ * Set a specific slide. Requires an id return in a JSON-encoded dict like
+ * this::
+ *
+ * {"request": {"id": 1}}
+ *
+ * ``first``
+ * Load the first slide.
+ *
+ * ``last``
+ * Load the last slide.
+ *
+ * ``text``
+ * Fetches the text of the current song. The output is a JSON-encoded
+ * dict which looks like this::
+ *
+ * {"result": {"slides": ["...", "..."]}}
+ *
+ * ``/api/service/{action}``
+ * Perform ``{action}`` on the service manager (e.g. go live). Data is
+ * passed as a json-encoded ``data`` parameter. Valid actions are:
+ *
+ * ``next``
+ * Load the next item in the service.
+ *
+ * ``previous``
+ *
+ * ``set``
+ * Set a specific item in the service. Requires an id returned in a
+ * JSON-encoded dict like this::
+ *
+ * {"request": {"id": 1}}
+ *
+ * ``list``
+ * Request a list of items in the service. Returns a list of items in the
+ * current service in a JSON-encoded dict like this::
+ *
+ * {"results": {"items": [{...}, {...}]}}
+ * """
+ * </pre>
+ */
+
+public interface Api {
+
+    public final String LIVE_NEXT = "/api/controller/live/next";
+    public final String LIVE_PREVIOUS = "/api/controller/live/previous";
+    public final String LIVE_TEXT = "/api/controller/live/text";
+
+    public final String SERVICE_NEXT = "/api/service/next";
+    public final String SERVICE_PREVIOUS = "/api/service/previous";
+    public final String SERVICE_LIST = "/api/service/list";
+
+    public final String DISPLAY_HIDE = "/api/display/hide";
+    public final String DISPLAY_SHOW = "/api/display/show";
+
+    public final String ALERT = "/api/alert?data=";
+
+}

=== modified file 'src/org/openlp/android/utility/OpenLPHttpClient.java'
--- src/org/openlp/android/utility/OpenLPHttpClient.java	2011-05-04 10:29:58 +0000
+++ src/org/openlp/android/utility/OpenLPHttpClient.java	2011-05-08 21:33:27 +0000
@@ -34,6 +34,7 @@
 import org.openlp.android.R;
 
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.net.URISyntaxException;
 import java.net.URL;
 
@@ -44,19 +45,30 @@
 
     private HttpGet httpGet;
     private URL url;
+    private final String urlBase;
     private final String LOG_TAG = OpenLPHttpClient.class.getName();
 
     public OpenLPHttpClient(Context context) {
-        SharedPreferences preferences = context.getSharedPreferences("prefs", Context.MODE_PRIVATE);
+        SharedPreferences preferences = context.getSharedPreferences(context
+                .getString(R.string.keySharedPreferences), Context.MODE_PRIVATE);
+
+        Log.d(LOG_TAG, preferences.getAll().toString());
         HttpParams httpParams = new BasicHttpParams();
 
+        urlBase = String.format("http://%s:%s";,
+                preferences.getString(context.getString(R.string.keyHost), context.getString(R.string.hostDefaultValue)),
+                preferences.getString(context.getString(R.string.keyPort), context.getString(R.string.portDefaultValue)));
+
         int connectionTimeout = context.getResources().getInteger(R.integer.connectionTimeoutDefaultValue);
         int socketTimeout = context.getResources().getInteger(R.integer.socketTimeoutDefaultValue);
 
         if (preferences.getBoolean(context.getString(R.string.keyEnableCustomTimeout), false)) {
-            Log.d(LOG_TAG, String.format("Retrieving values for %s and %s...", context.getString(R.string.keyConnectionTimeout), context.getString(R.string.keySocketTimeout)));
-            connectionTimeout = Integer.parseInt(preferences.getString(context.getString(R.string.keyConnectionTimeout), String.valueOf(context.getResources().getInteger(R.integer.connectionTimeoutDefaultValue))));
-            socketTimeout = Integer.parseInt(preferences.getString(context.getString(R.string.keySocketTimeout), String.valueOf(context.getResources().getInteger(R.integer.socketTimeoutDefaultValue))));
+            Log.d(LOG_TAG, String.format("Retrieving values for %s and %s...", context
+                    .getString(R.string.keyConnectionTimeout), context.getString(R.string.keySocketTimeout)));
+            connectionTimeout = Integer.parseInt(preferences.getString(context.getString(R.string.keyConnectionTimeout),
+                    String.valueOf(context.getResources().getInteger(R.integer.connectionTimeoutDefaultValue))));
+            socketTimeout = Integer.parseInt(preferences.getString(context.getString(R.string.keySocketTimeout),
+                    String.valueOf(context.getResources().getInteger(R.integer.socketTimeoutDefaultValue))));
         }
         HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeout);
         HttpConnectionParams.setSoTimeout(httpParams, socketTimeout);
@@ -70,12 +82,14 @@
         return url;
     }
 
-    public void setUrl(URL url) throws URISyntaxException {
-        this.url = url;
+    public void setUrl(String apiPart) throws URISyntaxException, MalformedURLException {
+        url = new URL(urlBase.concat(apiPart));
+        Log.d(LOG_TAG, "URL set to: " + url);
         httpGet.setURI(getUrl().toURI());
     }
 
     public HttpResponse execute() throws IOException {
         return super.execute(httpGet);
     }
+
 }

=== modified file 'src/org/openlp/android/utility/StringHelper.java'
--- src/org/openlp/android/utility/StringHelper.java	2011-05-04 10:29:58 +0000
+++ src/org/openlp/android/utility/StringHelper.java	2011-05-08 21:33:27 +0000
@@ -33,11 +33,12 @@
 public class StringHelper {
     public synchronized static String convertStreamToString(InputStream is) {
         /*
-                     * To convert the InputStream to String we use the
-                     * BufferedReader.readLine() method. We iterate until the BufferedReader
-                     * return null which means there's no more data to read. Each line will
-                     * appended to a StringBuilder and returned as String.
-                     */
+            To convert the InputStream to String we use the
+            BufferedReader.readLine() method. We iterate until the BufferedReader
+            return null which means there's no more data to read. Each line will
+            appended to a StringBuilder and returned as String.
+        */
+
         BufferedReader reader = new BufferedReader(new InputStreamReader(is));
         StringBuilder sb = new StringBuilder();
 

=== added file 'src/org/openlp/android/utility/WebCallAsyncTask.java'
--- src/org/openlp/android/utility/WebCallAsyncTask.java	1970-01-01 00:00:00 +0000
+++ src/org/openlp/android/utility/WebCallAsyncTask.java	2011-05-08 21:33:27 +0000
@@ -0,0 +1,84 @@
+/******************************************************************************
+ * OpenLP - Open Source Lyrics Projection                                      *
+ * --------------------------------------------------------------------------- *
+ * Copyright (c) 2008-2011 Raoul Snyman                                        *
+ * Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      *
+ * Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler,        *
+ * Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      *
+ * Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund             *
+ * --------------------------------------------------------------------------- *
+ * This program is free software; you can redistribute it and/or modify it     *
+ * under the terms of the GNU General Public License as published by the Free  *
+ * Software Foundation; version 2 of the License.                              *
+ *                                                                             *
+ * This program is distributed in the hope that it will be useful, but WITHOUT *
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
+ * more details.                                                               *
+ *                                                                             *
+ * You should have received a copy of the GNU General Public License along     *
+ * with this program; if not, write to the Free Software Foundation, Inc., 59  *
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA                          *
+ *******************************************************************************/
+package org.openlp.android.utility;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.util.Log;
+import android.widget.Toast;
+import org.openlp.android.R;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+/**
+ * Call URL's using this task, which provides visual feedback.
+ */
+public class WebCallAsyncTask extends AsyncTask<String, Void, Void> {
+    private final String LOG_TAG = WebCallAsyncTask.class.getName();
+    private Context context;
+    private ProgressDialog progressDialog;
+    private String error;
+
+    public WebCallAsyncTask(Context context) {
+        this.context = context;
+    }
+
+    @Override
+    protected void onPreExecute() {
+        super.onPreExecute();
+        progressDialog = ProgressDialog.show(context, "", context.getString(R.string.loading));
+    }
+
+    @Override
+    protected Void doInBackground(String... apiCall) {
+        OpenLPHttpClient httpClient = new OpenLPHttpClient(context);
+        try {
+            httpClient.setUrl(apiCall[0]);
+
+            Log.d(LOG_TAG, "Executing request: " + httpClient.getUrl().toString());
+            if (httpClient.getUrl().getHost() != null) {
+                httpClient.execute();
+            }
+        }
+        catch (URISyntaxException e) {
+            Log.e(LOG_TAG, e.toString());
+            error = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
+        }
+        catch (IOException e) {
+            Log.e(LOG_TAG, e.toString());
+            error = String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
+        }
+        return null;
+    }
+
+    @Override
+    protected void onPostExecute(Void aVoid) {
+        super.onPostExecute(aVoid);
+        progressDialog.dismiss();
+        if (error != null && error.trim().length() > 0) {
+            Toast.makeText(context, error, Toast.LENGTH_LONG).show();
+        }
+    }
+}


Follow ups