zoukankan      html  css  js  c++  java
  • Customize "share picture via" menu on Android (Android Intent Filters) eggie5.com

    Customize "share picture via" menu on Android (Android Intent Filters) eggie5.com

    Customize "share picture via" menu on Android (Android Intent Filters)

    Alex Egg, 2010-11-13 2011-06-14

    You know in the android gallery when you view a picture there is the share menu that allows you to upload your picture to various services. It is the job of the app to handle the upload - for example on my phone (depending on the apps you have installed) facebook, picasa, blogger all have entries in that list. This article will describe the process to get your app in that list and post the picture over HTTP.

    Basically there are 3 steps to get this working:

    1. Register your app w/ the android platform to show your app in the platform share menu. (see Intents)
    2. Get the image from the Album app using android APIs (see ContentResolver)
    3. Do actual HTTP post request

    1. Add hook to AndroidManifest.xml

    If you intend to get your app in the share menu you must register that intent (pun intended) w/ the andoid system. This is done via and intent-filter in the AndroidManifest.xml file. 

    In order to use the internet to make and HTTP request we must also register that w/ Android via the use-permission directive in the manifest file. See below example:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       
    package="com.eggie5" android:versionCode="1" android:versionName="1.0">
       
    <application android:icon="@drawable/icon" android:label="@string/app_name">
           
    <activity android:name=".post_to_eggie5" android:label="@string/app_name">
               
    <intent-filter>
                   
    <action android:name="android.intent.action.MAIN" />
                   
    <category android:name="android.intent.category.LAUNCHER" />
               
    </intent-filter>
               
    <intent-filter>
                   
    <action android:name="android.intent.action.SEND" />
                   
    <category android:name="android.intent.category.DEFAULT" />
                   
    <data android:mimeType="image/*" />
               
    </intent-filter>
           
    </activity>
       
    </application>
       
    <uses-permission android:name="android.permission.INTERNET" />
    </manifest>

    2. Get image from Gallery

    Getting an image from the camera isn't as straight forward as it seems. It's not just open the file at this path - you must use the ContentResolver/ContentProvider API in android - which the gallery app exposes. See code example:

    public void onCreate(Bundle savedInstanceState)
    {
       
    super.onCreate(savedInstanceState);
        setContentView
    (R.layout.main);

       
    Intent intent = getIntent();
       
    Bundle extras = intent.getExtras();
       
    String action = intent.getAction();

       
    // if this is from the share menu
       
    if (Intent.ACTION_SEND.equals(action))
       
    {
           
    if (extras.containsKey(Intent.EXTRA_STREAM))
           
    {
               
    try
               
    {
                   
    // Get resource path from intent callee
                   
    Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);

                   
    // Query gallery for camera picture via
                   
    // Android ContentResolver interface
                   
    ContentResolver cr = getContentResolver();
                   
    InputStream is = cr.openInputStream(uri);
                   
    // Get binary bytes for encode
                   
    byte[] data = getBytesFromFile(is);

                   
    // base 64 encode for text transmission (HTTP)
                   
    byte[] encoded_data = Base64.encodeBase64(data);
                   
    String data_string = new String(encoded_data); // convert to string

                   
    SendRequest(data_string);

                   
    return;
               
    } catch (Exception e)
               
    {
                   
    Log.e(this.getClass().getName(), e.toString());
               
    }

           
    } else if (extras.containsKey(Intent.EXTRA_TEXT))
           
    {
               
    return;
           
    }
       
    }

    }

    First we get a path to the image (uri) from the share menu of the gallery when we clicked on share. It's not however just a path to the image - it's a content uri which is android platform specific way to refrence a resource. It looks somehting like this content://com.example.gallery/3. With a URI you can then query gallery for the resource. The key here is getContentResolver() method - it will get you a handle to android internal DRM system which the cameria/gallery exposes(uses). Then in order to sent the image over HTTP we must convert it to plaintext encoding (base64) from binary. We do this by gettings it's bits and converting to base64 string representation (details are beyond the scope of this article - see source for details).

    3. HTTP Post Request

    Rather than choose a high level library for the HTTP action I chose to implement it using sockets as an exercise (more fun - we can really see what's happening).

    First we build the xml post body string. We then create the request and send it. Note: most people would do this using multipart/mime but I choose just to encode the image into the xml photo node.

    private void SendRequest(String data_string)
    {

       
    try
       
    {
           
    String xmldata = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                   
    + "<photo><photo>" + data_string
                   
    + "</photo><caption>via android - " + new Date().toString()
                   
    + "</caption></photo>";

           
    // Create socket
           
    String hostname = "eggie5.com";
           
    String path = "/photos";
           
    int port = 80;
           
    InetAddress addr = InetAddress.getByName(hostname);
           
    Socket sock = new Socket(addr, port);

           
    // Send header
           
    BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(
                    sock
    .getOutputStream(), "UTF-8"));
            wr
    .write("POST " + path + " HTTP/1.1\r\n");
            wr
    .write("Host: eggie5.com\r\n");
            wr
    .write("Content-Length: " + xmldata.length() + "\r\n");
            wr
    .write("Content-Type: text/xml; charset=\"utf-8\"\r\n");
            wr
    .write("Accept: text/xml\r\n");
            wr
    .write("\r\n");

           
    // Send data
            wr
    .write(xmldata);
            wr
    .flush();

           
    // Response
           
    BufferedReader rd = new BufferedReader(new InputStreamReader(
                    sock
    .getInputStream()));
           
    String line;
           
    while ((line = rd.readLine()) != null)
           
    {
               
    Log.v(this.getClass().getName(), line);
           
    }

       
    } catch (Exception e)
       
    {
           
    Log.e(this.getClass().getName(), "Upload failed", e);
       
    }

    }

    Then on the server side - I must decode the base64 stream back into binary which I did in ruby:

    Base64.decode64(incoming_file)

    See full source on github: https://github.com/eggie5/android-share-menu

    Next Steps:

    When the image is uploading the UI kinda locks up - the next step would be to have some type of progress bar like the facebook or picasa app does.

    Also usually the images are way to big for the front page of this site (where they go) - should implement some type of resize on the phone. This would also make the upload faster.

    /g:plusone

  • 相关阅读:
    剑指offer_24:二叉树中和为某一值的路径
    剑指offer_23:二叉搜索树的后序遍历序列
    Java基础类型大小
    旋转数组
    剑指offer_22:从上往下打印二叉树
    剑指offer_21:栈的压入、弹出序列
    剑指offer_20:包含min函数的栈
    剑指offer_19:顺时针打印矩阵
    剑指offer_18:二叉树的镜像
    redis jedis源码
  • 原文地址:https://www.cnblogs.com/lexus/p/2787377.html
Copyright © 2011-2022 走看看