// -*- mode: java; c-basic-offset: 2; -*- // Copyright 2009-2011 Google, All Rights reserved // Copyright 2011-2012 MIT, All rights reserved // Released under the MIT License https://raw.github.com/mit-cml/app-inventor/master/mitlicense.txt package com.google.appinventor.components.runtime; import android.os.Handler; import com.google.appinventor.components.annotations.DesignerComponent; import com.google.appinventor.components.annotations.DesignerProperty; import com.google.appinventor.components.annotations.PropertyCategory; import com.google.appinventor.components.annotations.SimpleEvent; import com.google.appinventor.components.annotations.SimpleFunction; import com.google.appinventor.components.annotations.SimpleObject; import com.google.appinventor.components.annotations.SimpleProperty; import com.google.appinventor.components.annotations.UsesLibraries; import com.google.appinventor.components.annotations.UsesPermissions; import com.google.appinventor.components.common.ComponentCategory; import com.google.appinventor.components.common.PropertyTypeConstants; import com.google.appinventor.components.common.YaVersion; import com.google.appinventor.components.runtime.util.AsyncCallbackPair; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; // When the component is installed in App Inventor, the Javadoc // comments will become included in the automatically-generated system // documentation, except for lines starting with tags (such as @author). /** * The MediaStore component communicates with a web service to store media objects. This component * has a single method that stores a media object in the services blob store, and returns a pointer * to the object via a url. The accompanying Web service is at (http://ai-mediaservice.appspot.com). * * This component is currently in development, and more functionality will be added. * * @author andrew.f.mckinney@gmail.com (Andrew F. McKinney) */ // The annotations here provide information to the compiler about // integrating the component into App Inventor system. The following // three annotations stipulate that MediaStore will appear in the // designer, that it will be an object in the App Inventor language, // and say what Android system permissions it requires. // @DesignerComponent(version = YaVersion.MEDIASTORE_COMPONENT_VERSION, description = "Non-visible component that communicates with a Web service and stores media " + "files.", category = ComponentCategory.INTERNAL, nonVisible = true, iconName = "images/mediastore.png") @SimpleObject @UsesPermissions(permissionNames = "android.permission.INTERNET") @UsesLibraries(libraries = "httpcore-4.3.2.jar," + "httpmime-4.3.4.jar") public final class MediaStore extends AndroidNonvisibleComponent implements Component { protected final ComponentContainer componentContainer; private static final String LOG_TAG_COMPONENT = "MediaStore: "; private String serviceURL; private Handler androidUIHandler; /** * Creates a new MediaStore component. * * @param container the Form that this component is contained in. */ public MediaStore(ComponentContainer container) { super(container.$form()); componentContainer = container; androidUIHandler = new Handler(); serviceURL = "http://ai-mediaservice.appspot.com"; } /** * Returns the URL of the MediaStore web service. */ @SimpleProperty(category = PropertyCategory.BEHAVIOR) public String ServiceURL() { return serviceURL; } /** * Specifies the URL of the Web service. * The default value is the App Inventor MediaStore service running on App Engine. */ @DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING, defaultValue = "http://ai-mediaservice.appspot.com") @SimpleProperty public void ServiceURL(String url) { serviceURL = url; } /** * Asks the Web service to store the given media file. * * @param mediafile The value to store. */ @SimpleFunction public void PostMedia(String mediafile) throws FileNotFoundException{ AsyncCallbackPair<String> myCallback = new AsyncCallbackPair<String>() { public void onSuccess(final String response) { androidUIHandler.post(new Runnable() { public void run() { MediaStored(response); } }); } public void onFailure(final String message) { androidUIHandler.post(new Runnable() { public void run() { WebServiceError(message); } }); } }; try { HttpClient client = new DefaultHttpClient(); MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); String[] pathtokens = mediafile.split("/"); String newMediaPath; if (pathtokens[0].equals("file:")) { newMediaPath = new java.io.File(new URL(mediafile).toURI()).getAbsolutePath(); } else { newMediaPath = mediafile; } File media = new File(newMediaPath); entityBuilder.addPart("file", new FileBody(media)); HttpEntity entity = entityBuilder.build(); String uploadURL = getUploadUrl(); HttpPost post = new HttpPost(uploadURL); post.setEntity(entity); HttpResponse response = client.execute(post); HttpEntity httpEntity = response.getEntity(); String result = EntityUtils.toString(httpEntity); myCallback.onSuccess(result); } catch (Exception e) { e.printStackTrace(); myCallback.onFailure(e.getMessage()); } } private String getUploadUrl() { try { String url = serviceURL; URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); // optional default is GET con.setRequestMethod("GET"); // add request header String USER_AGENT = "AppInventor"; con.setRequestProperty("User-Agent", USER_AGENT); con.setRequestProperty("Content-Type", "text/plain; charset=utf-8"); // get and build upload URL from response BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); StringBuilder response = new StringBuilder(); String inputLine; while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); // return upload URL return response.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } /** * Indicates that a MediaStored server request has succeeded. * * @param url the value that was returned. */ @SimpleEvent public void MediaStored(String url) { EventDispatcher.dispatchEvent(this, "MediaStored", url); } /** * Indicates that the communication with the Web service signaled an error * * @param message the error message */ @SimpleEvent public void WebServiceError(String message) { EventDispatcher.dispatchEvent(this, "WebServiceError", message); } }