android-blogposter

Unnamed repository; edit this file 'description' to name the repository.
git clone http://git.code.weiherhei.de/android-blogposter.git
Log | Files | Refs

commit a5b8c8910d2c99b0d5946dcd0cd220fb276086dd
parent a4da5eb73301e685f53d94a9454cd57a60fa4dc0
Author: Jan Dankert <devnull@localhost>
Date:   Fri, 25 Nov 2011 00:05:54 +0100

Vervollständigung der Eingabe-Maske, incl. Kamera-Aufruf und Starten von IntentService. Vervollständiung der Einstellungen.

Diffstat:
res/layout/main.xml | 40+++++++++++++++++++++++++++-------------
res/values/strings.xml | 13+++++++++++--
res/xml/settings.xml | 41+++++++++++++++++++++++++++++++++++------
src/de/openrat/android/blog/Blog.java | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
src/de/openrat/android/blog/FileUtils.java | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/de/openrat/android/blog/HTTPRequest.java | 624+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/de/openrat/android/blog/MailIntentService.java | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/de/openrat/android/blog/MyStreamReader.java | 35+++++++++++++++++++++++++++++++++++
src/de/openrat/android/blog/UploadIntentService.java | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 1057 insertions(+), 27 deletions(-)

diff --git a/res/layout/main.xml b/res/layout/main.xml @@ -1,16 +1,30 @@ <?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"> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" android:layout_height="fill_parent"> + <LinearLayout 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="@string/hello" /> - + <TextView android:layout_width="fill_parent" + android:layout_height="wrap_content" android:text="@string/param_title" /> <EditText android:layout_width="fill_parent" - android:layout_height="wrap_content" android:id="@+id/text" /> - - <Button android:layout_width="fill_parent" - android:layout_height="wrap_content" android:text="@string/hello" - android:id="@+id/save" /> - -</LinearLayout> + android:layout_height="wrap_content" android:id="@+id/title" /> + + <TextView android:layout_width="fill_parent" + android:layout_height="wrap_content" android:text="@string/param_text" /> + <EditText android:layout_width="fill_parent" + android:layout_height="wrap_content" android:id="@+id/text" /> + + <TextView android:layout_width="fill_parent" + android:layout_height="wrap_content" android:text="@string/param_image" /> + <ImageButton android:layout_width="fill_parent" + android:layout_height="wrap_content" android:id="@+id/image" /> + + <CheckBox android:layout_width="fill_parent" + android:layout_height="wrap_content" android:id="@+id/ispublic" android:text="@string/param_privacy" /> + + <Button android:layout_width="fill_parent" + android:layout_height="wrap_content" android:text="@string/hello" + android:id="@+id/save" /> + + </LinearLayout> +</ScrollView> diff --git a/res/values/strings.xml b/res/values/strings.xml @@ -3,13 +3,22 @@ <string name="hello">Hello World, Blog!</string> <string name="app_name">Blog</string> <string name="save">Blog</string> - <string name="settings">Einstellunen</string> + <string name="settings">Einstellungen</string> <string name="mail">E-Mail</string> <string name="upload">Hochladen</string> + <string name="upload_long">Hochladen der Daten</string> + <string name="upload_ok">Hochladen beendet</string> + <string name="upload_ok_long">Hochladen erfolgreich beendet</string> + <string name="upload_fail">Hochladen nicht erfolgreich</string> + <string name="upload_fail_long">Hochladen fehlgeschlagen</string> <string name="url">URL</string> <string name="param_image">Parameter Bild</string> - <string name="param_text">Text</string> + <string name="param_title">Parameter Titel</string> + <string name="param_text">Parameter Text</string> + <string name="param_privacy">Parameter Privacy</string> <string name="user">Benutzer</string> <string name="password">Kennwort</string> <string name="take_photo">Kamera</string> + <string name="use_email">Per E-Mail versenden</string> + <string name="use_upload">Hochladen</string> </resources> diff --git a/res/xml/settings.xml b/res/xml/settings.xml @@ -1,11 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="@string/hello"> - <PreferenceCategory android:title="@string/settings"> - <EditTextPreference android:key="param_image" - android:title="@string/param_image"></EditTextPreference> - <EditTextPreference android:key="url" - android:title="@string/url"></EditTextPreference> - </PreferenceCategory> + <CheckBoxPreference android:key="use_email" android:title="@string/use_email" /> + + <PreferenceScreen android:dependency="use_email" android:title="@string/use_email"> + <PreferenceCategory android:title="@string/settings"> + <EditTextPreference android:key="url" + android:title="@string/url"></EditTextPreference> + <EditTextPreference android:key="http_user" + android:title="@string/user"></EditTextPreference> + <EditTextPreference android:key="http_password" + android:password="true" android:title="@string/password"></EditTextPreference> + <EditTextPreference android:key="param_title" + android:title="@string/param_title"></EditTextPreference> + <EditTextPreference android:key="param_text" + android:title="@string/param_text"></EditTextPreference> + <EditTextPreference android:key="param_image" + android:title="@string/param_image"></EditTextPreference> + <EditTextPreference android:key="param_privacy" + android:title="@string/param_privacy"></EditTextPreference> + </PreferenceCategory> + </PreferenceScreen> + + <CheckBoxPreference android:key="use_upload" android:title="@string/use_upload" /> + + <PreferenceScreen android:dependency="use_upload" android:title="@string/use_upload"> + <PreferenceCategory android:title="@string/settings"> + <EditTextPreference android:key="recipient_address" + android:title="@string/param_image"></EditTextPreference> + <EditTextPreference android:key="smtp_host" + android:title="@string/url"></EditTextPreference> + <EditTextPreference android:key="smtp_user" + android:title="@string/user"></EditTextPreference> + <EditTextPreference android:key="smtp_password" + android:password="true" android:title="@string/password"></EditTextPreference> + </PreferenceCategory> + </PreferenceScreen> </PreferenceScreen> diff --git a/src/de/openrat/android/blog/Blog.java b/src/de/openrat/android/blog/Blog.java @@ -7,19 +7,29 @@ import java.io.IOException; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.hardware.Camera; import android.net.Uri; import android.os.Bundle; import android.os.Environment; +import android.preference.PreferenceManager; import android.provider.MediaStore; -import android.provider.MediaStore.Audio.Media; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; public class Blog extends Activity { + private static final int TAKE_PHOTO_CODE = 1; + private String imageFilename; + private ImageView image; + private EditText title; + private EditText text; @Override public void onCreate(Bundle savedInstanceState) @@ -27,6 +37,59 @@ public class Blog extends Activity super.onCreate(savedInstanceState); setContentView(R.layout.main); + + title = (EditText) findViewById(R.id.title); + text = (EditText) findViewById(R.id.text); + image = (ImageView) findViewById(R.id.image); + image.setOnClickListener(new OnClickListener() + { + + @Override + public void onClick(View v) + { + takePhoto(); + } + }); + Button button = (Button) findViewById(R.id.save); + button.setOnClickListener(new OnClickListener() + { + + @Override + public void onClick(View v) + { + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(Blog.this); + + if (prefs.getBoolean("use_upload", false)) + { + final Intent uploadIntent = new Intent(Blog.this, + UploadIntentService.class); + + uploadIntent.putExtra(UploadIntentService.EXTRA_TITLE, + title.getText()); + uploadIntent.putExtra(UploadIntentService.EXTRA_TEXT, text + .getText()); + uploadIntent.putExtra(UploadIntentService.EXTRA_IMAGE, + imageFilename); + startService(uploadIntent); + + } + if (prefs.getBoolean("use_mail", false)) + { + final Intent mailIntent = new Intent(Blog.this, + MailIntentService.class); + mailIntent.putExtra(UploadIntentService.EXTRA_TITLE, title + .getText()); + mailIntent.putExtra(UploadIntentService.EXTRA_TEXT, text + .getText()); + mailIntent.putExtra(UploadIntentService.EXTRA_IMAGE, + imageFilename); + + startService(mailIntent); + } + + } + }); } @Override @@ -71,8 +134,6 @@ public class Blog extends Activity * } } }; */ - private static final int TAKE_PHOTO_CODE = 1; - private void takePhoto() { final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); @@ -102,13 +163,14 @@ public class Blog extends Activity { case TAKE_PHOTO_CODE: final File file = getTempFile(this); + this.imageFilename = file.getAbsoluteFile().getName(); try { Bitmap captureBmp = android.provider.MediaStore.Images.Media .getBitmap(getContentResolver(), Uri .fromFile(file)); - // do whatever you want with the bitmap (Resize, Rename, - // Add To Gallery, etc) + + image.setImageBitmap(captureBmp); } catch (FileNotFoundException e) { diff --git a/src/de/openrat/android/blog/FileUtils.java b/src/de/openrat/android/blog/FileUtils.java @@ -0,0 +1,55 @@ +/** + * + */ +package de.openrat.android.blog; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author dankert + * + */ +public class FileUtils +{ + + /** + * + * @param file + * @return + * @throws IOException + */ + public static byte[] getBytesFromFile(File file) throws IOException { + InputStream is = new FileInputStream(file); + + // Get the size of the file + long length = file.length(); + + if (length > Integer.MAX_VALUE) { + // File is too large + throw new IOException("File is too large"); + } + + // Create the byte array to hold the data + byte[] bytes = new byte[(int)length]; + + // Read in the bytes + int offset = 0; + int numRead = 0; + while (offset < bytes.length + && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { + offset += numRead; + } + + // Ensure all the bytes have been read in + if (offset < bytes.length) { + throw new IOException("Could not completely read file "+file.getName()); + } + + // Close the input stream and return bytes + is.close(); + return bytes; + } +} diff --git a/src/de/openrat/android/blog/HTTPRequest.java b/src/de/openrat/android/blog/HTTPRequest.java @@ -0,0 +1,624 @@ +/* +OpenRat Java-Client +Copyright (C) 2009 Jan Dankert + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +Boston, MA 02110-1301, USA. + + */ +package de.openrat.android.blog; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; + +/** + * API-Request to the OpenRat Content Management System. <br> + * <br> + * The call to the CMS server is done via a (non-SSL) HTTP connection.<br> + * <br> + * Before a call you are able to set some key/value-pairs as parameters. After + * calling the CMS a DOM-document is returned, which contains the server + * response.<br> + * Example <br> + * + * <pre> + * CMSRequest request = new CMSRequest(&quot;your.openrat.example.com&quot;); + * //prints tracing information to stdout. + * request.trace = true; + * try + * { + * request.parameter.put(&quot;action&quot;, &quot;index&quot;); + * request.parameter.put(&quot;subaction&quot;, &quot;showlogin&quot;); // login page + * request.parameter.put(&quot;...&quot;, &quot;...&quot;); + * Document response = request.call(); + * // now traverse through the dom tree and get your information. + * } catch (IOException e) + * { + * // your error handling. + * } + * </pre> + * + * @author Jan Dankert + */ +public class HTTPRequest implements Serializable +{ + + private static final String CRLF = "\r\n"; + + private Multipart multipart = new Multipart(); + + // some constants... + private static final String CHARSET_UTF8 = "UTF-8"; + private static final String HTTP_GET = "GET"; + private static final String HTTP_POST = "POST"; + + /** + * if <code>true</code>, Tracing-Output will be logged to stdout. Default: + * <code>false</code>. + */ + // this is public, for easier use. + public boolean trace = false; + + /** + * HTTP-method, must be "GET" or "POST", default: "GET". + */ + private String method = HTTP_GET; + + /** + * Parameter map. + */ + private Map<String, String> parameter = new HashMap<String, String>(); + private Map<String, String> requestHeader = new HashMap<String, String>(); + + private String serverPath; + private String serverHost; + private int serverPort; + + private String proxyHostname; + private int proxyPort; + private SocketAddress socketAddress; + + private String cookieName; + private String cookieValue; + private String language; + private int timeout = 30000; + + /** + * + */ + public HTTPRequest() + { + super(); + this.language = Locale.getDefault().getLanguage(); + } + + public String getAcceptLanguage() + { + return language; + } + + public void setAcceptLanguage(String language) + { + this.language = language; + } + + /** + * Setting a HTTP-Cookie. + * + * @param name + * name + * @param value + * value + */ + public void setCookie(String name, String value) + { + + this.cookieName = this.urlEncode(name); + this.cookieValue = this.urlEncode(value); + } + + /** + * URL-Encoder. + * + * @param value + * @return url-encoded value + */ + private String urlEncode(String value) + { + + try + { + return URLEncoder.encode(value, CHARSET_UTF8); + } catch (UnsupportedEncodingException e) + { + // maybe... this would be strange + throw new IllegalStateException(CHARSET_UTF8 + + " ist not supported by this VM"); + } + } + + /** + * Setting a HTTP-Proxy. + * + * @param host + * hostname + * @param port + * port + */ + public void setProxy(String host, int port) + { + + this.proxyHostname = host; + this.proxyPort = port; + } + + + /** + * Timeout for Socket. + * @param timeout Timeout in milliseconds. + * @return old timeout + */ + public int setTimeout(int timeout) + { + int oldTimeout = this.timeout; + this.timeout = timeout; + + return oldTimeout; + } + + /** + * Set the HTTP Method. Default is "GET". + * + * @param method + * HTTP-method + */ + public void setMethod(String method) + { + + if (!HTTP_GET.equalsIgnoreCase(method) + && !HTTP_POST.equalsIgnoreCase(method)) + throw new IllegalArgumentException("Method must be '" + HTTP_POST + + "' or '" + HTTP_GET + "'."); + + this.method = method.toUpperCase(); + } + + /** + * Clear parameter values. + */ + public void clearParameters() + { + + parameter.clear(); + requestHeader.clear(); + multipart.parts.clear(); + } + + /** + * Setting a parameter value. <strong>DO NOT url-encode your values</strong> + * as this is done automatically inside this method! + * + * @param paramName + * name + * @param paramValue + * value + */ + public void setParameter(String paramName, String paramValue) + { + + if (paramName == null || paramValue == null || "" == paramName) + throw new IllegalArgumentException( + "parameter name and value must have values"); + + parameter.put(paramName, paramValue); + } + + /** + * + * Setting a parameter value. <strong>DO NOT url-encode your values</strong> + * as this is done automatically inside this method! + * + * @param paramName + * name + * @param paramValue + * value + */ + public void setHeader(String paramName, String paramValue) + { + + if (paramName == null || paramValue == null || "" == paramName) + throw new IllegalArgumentException( + "parameter name and value must have values"); + + requestHeader.put(paramName, paramValue); + } + + /** + * Constructs a CMS-Request to the specified server.<br> + * Server-Path is "/", Server-Port is 80. + * + * @param host + * hostname + */ + public HTTPRequest(String host) + { + + super(); + this.serverHost = host; + this.serverPath = "/"; + this.serverPort = 80; + } + + /** + * Constructs a CMS-Request to the specified server/path.<br> + * Server-Port is 80. + * + * @param host + * hostname + * @param path + * path + */ + public HTTPRequest(String host, String path) + { + + super(); + this.serverHost = host; + this.serverPath = path; + this.serverPort = 80; + } + + /** + * Constructs a CMS-Request to the specified server/path/port. + * + * @param host + * hostname + * @param path + * path + * @param port + * port-number + */ + public HTTPRequest(String host, String path, int port) + { + + super(); + this.serverHost = host; + this.serverPath = path; + this.serverPort = port; + } + + /** + * Sends a request to the openrat-server and parses the response into a DOM + * tree document. + * + * @return server response as a DOM tree + * @throws IOException + * if server is unrechable or responds non-wellformed XML + */ + public byte[] performRequest() throws IOException + { + return performRequest(null); + } + + /** + * Sends a request to the openrat-server and parses the response into a DOM + * tree document. + * + * @return server response as a DOM tree + * @throws IOException + * if server is unrechable or responds non-wellformed XML + */ + public byte[] performRequest(String body) throws IOException + { + + final Socket socket = new Socket(); + + try + { + + final boolean useProxy = this.proxyHostname != null; + final boolean useCookie = this.cookieName != null; + + if (serverPath == null) + this.serverPath = "/"; + if (!serverPath.startsWith("/")) + this.serverPath = "/" + this.serverPath; + + // When a client uses a proxy, it typically sends all requests to + // that proxy, instead + // of to the servers in the URLs. Requests to a proxy differ from + // normal requests in one + // way: in the first line, they use the complete URL of the resource + // being requested, + // instead of just the path. + if (useProxy) + { + socketAddress = new InetSocketAddress(this.proxyHostname, + this.proxyPort); + } else + { + socketAddress = new InetSocketAddress(this.serverHost, + serverPort); + } + + socket.setKeepAlive(false); + socket.setReuseAddress(false); + socket.setSoTimeout(timeout); + socket.connect(socketAddress, timeout); + + final StringBuffer header = new StringBuffer(); + + final StringBuffer parameterList = new StringBuffer(); + + for (Entry<String, String> entry : this.parameter.entrySet()) + { + if (parameterList.length() > 0) + parameterList.append("&"); + parameterList.append(this.urlEncode(entry.getKey())); + parameterList.append("="); + parameterList.append(this.urlEncode(entry.getValue())); + } + + String httpUrl = this.serverPath; + + if (useProxy) + // See RFC 2616 Section 5.1.2 "Request-URI" + // "The absolute URI form is REQUIRED when the request is being made to a proxy" + httpUrl = "http://" + this.serverHost + httpUrl; + + if (HTTP_GET.equals(this.method) + || (body != null || multipart.parts.size() > 0)) + httpUrl = httpUrl + "?" + parameterList; + + // using HTTP/1.0 as this is supported by all HTTP-servers and + // proxys. + // We have no need for HTTP/1.1 at the moment. + header.append(this.method + " " + httpUrl + " HTTP/1.0" + CRLF); + + // Setting the HTTP Header + Map<String, String> headers = new HashMap<String, String>(); + headers.put("Host", this.serverHost); + headers.put("User-Agent", + "Mozilla/5.0; compatible (OpenRat android-client)"); + headers.put("Accept", "application/json"); + headers.put("Accept-Language", language); + headers.put("Accept-Charset", "utf-8"); + headers.put("Connection", "close"); + if (useCookie) + headers.put("Cookie", cookieName + "=" + cookieValue); + + if (HTTP_POST.equals(this.method)) + { + if (body == null && multipart.parts.size() == 0) + { + headers.put("Content-Type", + "application/x-www-form-urlencoded"); + headers.put("Content-Length", "" + parameterList.length()); + } else if (multipart.parts.size() > 0) + { + + headers.put("Content-Type", multipart.getContentType()); + headers.put("Content-Length", "" + + multipart.getPayload().length); + + } else + { + headers.put("Content-Type", "text/plain"); + + } + } + + headers.putAll(requestHeader); + for (String headerName : headers.keySet()) + { + header.append(headerName + ": " + headers.get(headerName) + + CRLF); + + } + + header.append(CRLF); + + final OutputStream outputStream = socket + .getOutputStream(); + outputStream.write(header.toString().getBytes()); + + if (HTTP_POST.equals(this.method)) + { + if (body == null && multipart.parts.size() == 0) + outputStream.write(parameterList.toString().getBytes()); + else if (multipart.parts.size() > 0) + outputStream.write(multipart.getPayload()); + else + outputStream.write(body.getBytes()); + } + + if (this.trace) + System.out.println("--- request ---"); + if (this.trace) + System.out.println(header.toString()); + + + outputStream.flush(); + + final InputStream inputStream = socket.getInputStream(); +// final int available = inputStream.available(); + + final BufferedReader bufferedReader = new BufferedReader( + new MyStreamReader(inputStream),1); + + final String httpResponse = bufferedReader.readLine().trim(); + final String httpRetCode = httpResponse.substring(9, 12); + + if (this.trace) + System.out.println("--- response ---"); + if (this.trace) + System.out.println(httpResponse); + + // Check if we got the status 200=OK. + if (!httpRetCode.equals("200")) + { + + // non-200-status seems to be an error. + throw new IOException("No HTTP 200: Status=" + httpRetCode + + " (" + httpResponse + ")"); + } + + while (true) + { + + String responseHeader = bufferedReader.readLine().trim(); + + if (responseHeader.equals("")) + break; + + if (this.trace) + System.out.println(responseHeader); + } + //inputStreamReader.reset(); + //inputStream.reset(); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + int nRead; + byte[] data = new byte[1024]; + + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + buffer.flush(); + + byte[] response = buffer.toByteArray(); + + if (this.trace) + System.out.println("--- response body ---"); + if (this.trace) + System.out.println(response + "\n\n\n"); + + return response; + } finally + { + try + { + socket.close(); // Clean up the socket. + } catch (IOException e) + { + // We have done our very best. + } + } + + } + + public void setFile(String name, byte[] value, String filename, + String type, String encoding) + { + + Part part = new Part(); + part.file = value; + part.filename = filename; + part.encoding = encoding; + part.name = name; + part.contentType = type; + this.multipart.parts.add(part); + } + + public void setText(String name, String value) + { + + Part part = new Part(); + part.name = name; + part.text = value; + part.contentType = "text/plain"; + this.multipart.parts.add(part); + } + + private class Multipart implements Serializable + { + + private static final String CRLF = "\r\n"; + private static final String BOUNDARY = "614BA262123F3B29656A745C5DD26"; + List<Part> parts = new ArrayList<Part>(); + + public byte[] getPayload() throws IOException + { + HttpOutputStream body = new HttpOutputStream(); + + for (Part part : parts) + { + body.append("--" + BOUNDARY + CRLF); + body.append("Content-Type: " + part.contentType + CRLF); + + if (part.encoding != null) + body.append("Content-Transfer-Encoding: " + part.encoding + + CRLF); + + body.append("Content-Disposition: form-data; name=\"" + + part.name + + "\"" + + (part.filename != null ? ("; filename=\"" + + part.filename + "\"") : "") + CRLF); + body.append(CRLF); + if (part.file.length > 0) + body.write(part.file); + else + body.append(part.text); + body.append(CRLF); + } + body.append("--" + BOUNDARY + "--"); + return body.toByteArray(); + } + + public String getContentType() + { + return "multipart/form-data; boundary=" + Multipart.BOUNDARY; + } + } + + private class Part implements Serializable + { + public byte[] file; + public String filename; + public String text; + public String name; + public String contentType; + public String encoding; + } + + private class HttpOutputStream extends ByteArrayOutputStream + { + + public void write(String s) throws IOException + { + super.write(s.getBytes()); + } + public void append(String s) throws IOException + { + super.write(s.getBytes()); + } + } +} diff --git a/src/de/openrat/android/blog/MailIntentService.java b/src/de/openrat/android/blog/MailIntentService.java @@ -0,0 +1,99 @@ +/** + * + */ +package de.openrat.android.blog; + +import java.io.File; +import java.io.IOException; + +import android.app.IntentService; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.util.Log; + +/** + * @author dankert + * + */ +public class MailIntentService extends IntentService +{ + + private static final int NOTIFICATION_UPLOAD = 1; + + public MailIntentService() + { + super("UploadIntentService"); + } + + /** + * + * {@inheritDoc} + * + * @see android.app.IntentService#onHandleIntent(android.content.Intent) + */ + @Override + protected void onHandleIntent(Intent intent) + { + final String filePath = intent.getStringExtra(UploadIntentService.EXTRA_IMAGE); + + final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + final Intent notificationIntent = new Intent(this, Blog.class); + final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, + notificationIntent, 0); + + final File file = new File(filePath); + final String tickerText = getResources() + .getString(R.string.upload_long); + final Notification notification = new Notification( + android.R.drawable.ic_menu_rotate, tickerText, System + .currentTimeMillis()); + notification.setLatestEventInfo(getApplicationContext(), getResources() + .getString(R.string.upload), file.getName(), contentIntent); + notification.flags = Notification.FLAG_ONGOING_EVENT + | Notification.FLAG_NO_CLEAR; + nm.notify(NOTIFICATION_UPLOAD, notification); + + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(this); + + try + { + HTTPRequest request = new HTTPRequest(); + request.setFile(prefs.getString("param_image", "image"), FileUtils + .getBytesFromFile(file), "image.png", "image/png", "binary"); + // Alles OK. + final String msgText = getResources().getString(R.string.upload_ok); + notification.tickerText = getResources().getString( + R.string.upload_ok_long); + notification.setLatestEventInfo(getApplicationContext(), msgText, + file.getName(), contentIntent); + notification.flags = Notification.FLAG_AUTO_CANCEL; + nm.notify(NOTIFICATION_UPLOAD, notification); + Log.d(this.getClass().getName(), msgText); + } + catch (IOException e) + { + // Fehler ist aufgetreten. + final String msgText = getResources().getString( + R.string.upload_fail); + notification.tickerText = getResources().getString( + R.string.upload_fail_long); + notification.setLatestEventInfo(getApplicationContext(), msgText, e + .getMessage() + + ": " + file.getName(), contentIntent); + notification.flags = Notification.FLAG_AUTO_CANCEL; + nm.notify(NOTIFICATION_UPLOAD, notification); + + Log.e(this.getClass().getName(), msgText, e); + } + finally + { + } + } +} diff --git a/src/de/openrat/android/blog/MyStreamReader.java b/src/de/openrat/android/blog/MyStreamReader.java @@ -0,0 +1,35 @@ +package de.openrat.android.blog; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +public class MyStreamReader extends Reader +{ + + private InputStream stream; + + public MyStreamReader(InputStream inputStream) + { + this.stream = inputStream; + } + + @Override + public void close() throws IOException + { + stream.close(); + } + + @Override + public int read(char[] buf, int offset, int count) throws IOException + { + if (count != 1 || buf.length != 1 || offset != 0) + throw new IOException("Buffer size must be 1"); + byte[] b = new byte[1]; + this.stream.read(b); + char c = (char) b[0]; + buf[0] = c; + return 1; + } + +} diff --git a/src/de/openrat/android/blog/UploadIntentService.java b/src/de/openrat/android/blog/UploadIntentService.java @@ -0,0 +1,103 @@ +/** + * + */ +package de.openrat.android.blog; + +import java.io.File; +import java.io.IOException; + +import android.app.IntentService; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.util.Log; + +/** + * @author dankert + * + */ +public class UploadIntentService extends IntentService +{ + + public static final String EXTRA_TITLE = "title"; + public static final String EXTRA_TEXT = "text"; + public static final String EXTRA_IMAGE = "image"; + + private static final int NOTIFICATION_UPLOAD = 1; + + public UploadIntentService() + { + super("UploadIntentService"); + } + + /** + * + * {@inheritDoc} + * + * @see android.app.IntentService#onHandleIntent(android.content.Intent) + */ + @Override + protected void onHandleIntent(Intent intent) + { + final String filePath = intent.getStringExtra(EXTRA_IMAGE); + + final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + final Intent notificationIntent = new Intent(this, Blog.class); + final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, + notificationIntent, 0); + + final File file = new File(filePath); + final String tickerText = getResources() + .getString(R.string.upload_long); + final Notification notification = new Notification( + android.R.drawable.ic_menu_rotate, tickerText, System + .currentTimeMillis()); + notification.setLatestEventInfo(getApplicationContext(), getResources() + .getString(R.string.upload), file.getName(), contentIntent); + notification.flags = Notification.FLAG_ONGOING_EVENT + | Notification.FLAG_NO_CLEAR; + nm.notify(NOTIFICATION_UPLOAD, notification); + + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(this); + + try + { + HTTPRequest request = new HTTPRequest(); + request.setFile(prefs.getString("param_image", "image"), FileUtils + .getBytesFromFile(file), "image.png", "image/png", "binary"); + // Alles OK. + final String msgText = getResources().getString(R.string.upload_ok); + notification.tickerText = getResources().getString( + R.string.upload_ok_long); + notification.setLatestEventInfo(getApplicationContext(), msgText, + file.getName(), contentIntent); + notification.flags = Notification.FLAG_AUTO_CANCEL; + nm.notify(NOTIFICATION_UPLOAD, notification); + Log.d(this.getClass().getName(), msgText); + } + catch (IOException e) + { + // Fehler ist aufgetreten. + final String msgText = getResources().getString( + R.string.upload_fail); + notification.tickerText = getResources().getString( + R.string.upload_fail_long); + notification.setLatestEventInfo(getApplicationContext(), msgText, e + .getMessage() + + ": " + file.getName(), contentIntent); + notification.flags = Notification.FLAG_AUTO_CANCEL; + nm.notify(NOTIFICATION_UPLOAD, notification); + + Log.e(this.getClass().getName(), msgText, e); + } + finally + { + } + } +}