();
151 | postParams.add(new BasicNameValuePair("username", username));
152 | postParams.add(new BasicNameValuePair("password", password));
153 | postParams.add(new BasicNameValuePair("device_id", "0000"));
154 |
155 | try {
156 | httpPost.setEntity(new UrlEncodedFormEntity(postParams, HTTP.UTF_8));
157 | HttpResponse httpResponse = httpClient.execute(httpPost);
158 |
159 | // test result code
160 | if( httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
161 | Toast.makeText(LoginActivity.this, "Login failed", Toast.LENGTH_SHORT).show();
162 | Log.i(TAG, "Login HTTP status fail");
163 | return;
164 | }
165 |
166 | // test json response
167 | HttpEntity httpEntity = httpResponse.getEntity();
168 | if( httpEntity != null ) {
169 | BufferedReader reader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "UTF-8"));
170 | String json = reader.readLine();
171 | JSONTokener jsonTokener = new JSONTokener(json);
172 | JSONObject jsonObject = new JSONObject(jsonTokener);
173 | Log.i(TAG,"JSON: " + jsonObject.toString());
174 |
175 | String loginStatus = jsonObject.getString("status");
176 |
177 | if( !loginStatus.equals("ok") ) {
178 | Toast.makeText(LoginActivity.this, "Login failed", Toast.LENGTH_SHORT).show();
179 | Log.e(TAG, "JSON status not ok: " + jsonObject.getString("status"));
180 | return;
181 | }
182 | }
183 |
184 | // save login info so that we can reuse them later
185 | cookieStore = httpClient.getCookieStore();
186 |
187 | if( saveLoginInfo(cookieStore, username, password) == true ) {
188 | Toast.makeText(LoginActivity.this, "Logged in", Toast.LENGTH_SHORT).show();
189 | openMainActivity();
190 | } else {
191 | Toast.makeText(LoginActivity.this, "Login failed", Toast.LENGTH_SHORT).show();
192 | Log.e(TAG, "Cookie error");
193 | }
194 | } catch( IOException e ) {
195 | Log.e(TAG, "HttpPost error: " + e.toString());
196 | Toast.makeText(LoginActivity.this, "Login failed "
197 | + e.toString(), Toast.LENGTH_LONG).show();
198 | } catch( JSONException e ) {
199 | Log.e(TAG, "JSON parse error: " + e.toString());
200 | Toast.makeText(LoginActivity.this, "Result from instagr.am was unexpected: "
201 | + e.toString(), Toast.LENGTH_LONG).show();
202 | }
203 | }
204 | }
--------------------------------------------------------------------------------
/gen/org/acmelab/andgram/R.java:
--------------------------------------------------------------------------------
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY.
2 | *
3 | * This class was automatically generated by the
4 | * aapt tool from the resource data it found. It
5 | * should not be modified by hand.
6 | */
7 |
8 | package org.acmelab.andgram;
9 |
10 | public final class R {
11 | public static final class attr {
12 | /** Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
13 |
This may also be a reference to a resource (in the form
14 | "@[package:]type:name") or
15 | theme attribute (in the form
16 | "?[package:][type:]name")
17 | containing a value of this type.
18 | */
19 | public static final int title=0x7f010000;
20 | }
21 | public static final class color {
22 | public static final int actionbar_background_end=0x7f040003;
23 | public static final int actionbar_background_item_pressed_end=0x7f040005;
24 | public static final int actionbar_background_item_pressed_start=0x7f040004;
25 | public static final int actionbar_background_start=0x7f040002;
26 | public static final int actionbar_separator=0x7f040000;
27 | public static final int actionbar_title=0x7f040001;
28 | public static final int background1=0x7f04000b;
29 | public static final int background2=0x7f04000c;
30 | public static final int background3=0x7f04000d;
31 | public static final int foreground1=0x7f040009;
32 | public static final int foreground2=0x7f04000a;
33 | public static final int pinned_header_background=0x7f040010;
34 | public static final int session_foreground_past=0x7f04000f;
35 | public static final int title_background=0x7f040006;
36 | public static final int title_separator=0x7f04000e;
37 | public static final int title_text=0x7f040007;
38 | public static final int title_text_alt=0x7f040008;
39 | }
40 | public static final class dimen {
41 | public static final int actionbar_height=0x7f050000;
42 | public static final int actionbar_item_height=0x7f050001;
43 | public static final int actionbar_item_width=0x7f050002;
44 | public static final int colorstrip_height=0x7f050003;
45 | public static final int now_playing_height=0x7f050005;
46 | public static final int text_size_large=0x7f050008;
47 | public static final int text_size_medium=0x7f050007;
48 | public static final int text_size_small=0x7f050006;
49 | public static final int title_height=0x7f050004;
50 | }
51 | public static final class drawable {
52 | public static final int actionbar_back_indicator=0x7f020000;
53 | public static final int actionbar_background=0x7f020001;
54 | public static final int actionbar_btn=0x7f020002;
55 | public static final int actionbar_btn_normal=0x7f020003;
56 | public static final int actionbar_btn_pressed=0x7f020004;
57 | public static final int ic_menu_allfriends=0x7f020005;
58 | public static final int ic_menu_camera=0x7f020006;
59 | public static final int ic_menu_compose=0x7f020007;
60 | public static final int ic_menu_delete=0x7f020008;
61 | public static final int ic_menu_gallery=0x7f020009;
62 | public static final int ic_menu_home=0x7f02000a;
63 | public static final int ic_menu_login=0x7f02000b;
64 | public static final int ic_menu_preferences=0x7f02000c;
65 | public static final int ic_menu_refresh=0x7f02000d;
66 | public static final int ic_menu_slideshow=0x7f02000e;
67 | public static final int ic_menu_star=0x7f02000f;
68 | public static final int ic_title_camera=0x7f020010;
69 | public static final int ic_title_home=0x7f020011;
70 | public static final int ic_title_refresh=0x7f020012;
71 | public static final int icon=0x7f020013;
72 | public static final int stub=0x7f020014;
73 | }
74 | public static final class id {
75 | public static final int actionbar_actions=0x7f090006;
76 | public static final int actionbar_home=0x7f090001;
77 | public static final int actionbar_home_bg=0x7f090003;
78 | public static final int actionbar_home_btn=0x7f090004;
79 | public static final int actionbar_home_is_back=0x7f090005;
80 | public static final int actionbar_home_logo=0x7f090002;
81 | public static final int actionbar_item=0x7f090009;
82 | public static final int actionbar_progress=0x7f090007;
83 | public static final int actionbar_title=0x7f090008;
84 | public static final int activity_button=0x7f09000b;
85 | public static final int btnCamera=0x7f09001c;
86 | public static final int btnGallery=0x7f09001d;
87 | public static final int btnLogin=0x7f09001a;
88 | public static final int btnUpload=0x7f09001e;
89 | public static final int camera_button=0x7f09000e;
90 | public static final int caption=0x7f090016;
91 | public static final int captionRow=0x7f09001f;
92 | public static final int clear=0x7f090023;
93 | public static final int comments=0x7f090017;
94 | public static final int dashboardActionbar=0x7f09000a;
95 | public static final int gallery_button=0x7f09000f;
96 | public static final int gridview=0x7f090011;
97 | public static final int image=0x7f090015;
98 | public static final int imageListActionbar=0x7f090012;
99 | public static final int imageView=0x7f090022;
100 | public static final int lblCaption=0x7f090020;
101 | public static final int list=0x7f090013;
102 | public static final int login_button=0x7f090010;
103 | public static final int pictureActionbar=0x7f09001b;
104 | public static final int popular_button=0x7f09000c;
105 | public static final int screen=0x7f090000;
106 | public static final int txtCaption=0x7f090021;
107 | public static final int txtPassword=0x7f090019;
108 | public static final int txtUsername=0x7f090018;
109 | public static final int user_feed_button=0x7f09000d;
110 | public static final int username=0x7f090014;
111 | }
112 | public static final class layout {
113 | public static final int actionbar=0x7f030000;
114 | public static final int actionbar_item=0x7f030001;
115 | public static final int dashboard_home=0x7f030002;
116 | public static final int image_grid=0x7f030003;
117 | public static final int image_list=0x7f030004;
118 | public static final int image_list_item=0x7f030005;
119 | public static final int login=0x7f030006;
120 | public static final int take_picture=0x7f030007;
121 | }
122 | public static final class menu {
123 | public static final int take_picture_menu=0x7f080000;
124 | }
125 | public static final class string {
126 | public static final int actionbar_activity_not_found=0x7f060002;
127 | public static final int app_header=0x7f060003;
128 | public static final int app_name=0x7f060001;
129 | public static final int choose_gallery=0x7f060009;
130 | public static final int comment=0x7f06000b;
131 | public static final int dashboard=0x7f060012;
132 | public static final int default_comment=0x7f06000c;
133 | public static final int empty=0x7f060011;
134 | public static final int feed=0x7f06000d;
135 | public static final int gallery=0x7f060010;
136 | public static final int hello=0x7f060000;
137 | public static final int login=0x7f060013;
138 | public static final int main_menu_clear=0x7f060007;
139 | public static final int main_menu_credentials=0x7f060004;
140 | public static final int main_menu_preferences=0x7f060006;
141 | public static final int main_menu_refresh=0x7f060005;
142 | public static final int no_registration_disclaimer=0x7f060014;
143 | public static final int popular=0x7f06000e;
144 | public static final int take_picture=0x7f060008;
145 | public static final int upload=0x7f06000a;
146 | public static final int userfeed=0x7f06000f;
147 | }
148 | public static final class style {
149 | public static final int ActionBar=0x7f070000;
150 | public static final int ActionBarHomeItem=0x7f070002;
151 | public static final int ActionBarHomeLogo=0x7f070003;
152 | public static final int ActionBarItem=0x7f070001;
153 | public static final int ActionBarProgressBar=0x7f070004;
154 | public static final int DashboardButton=0x7f070005;
155 | }
156 | public static final class styleable {
157 | /** Attributes that can be used with a ActionBar.
158 |
Includes the following attributes:
159 |
160 |
161 |
162 | | Attribute | Description |
163 | {@link #ActionBar_title org.acmelab.andgram:title} | |
164 |
165 | @see #ActionBar_title
166 | */
167 | public static final int[] ActionBar = {
168 | 0x7f010000
169 | };
170 | /**
171 | This symbol is the offset where the {@link org.acmelab.andgram.R.attr#title}
172 | attribute's value can be found in the {@link #ActionBar} array.
173 |
174 |
175 |
Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
176 |
This may also be a reference to a resource (in the form
177 | "@[package:]type:name") or
178 | theme attribute (in the form
179 | "?[package:][type:]name")
180 | containing a value of this type.
181 | @attr name android:title
182 | */
183 | public static final int ActionBar_title = 0;
184 | };
185 | }
186 |
--------------------------------------------------------------------------------
/gen/com/markupartist/android/widget/actionbar/R.java:
--------------------------------------------------------------------------------
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY.
2 | *
3 | * This class was automatically generated by the
4 | * aapt tool from the resource data it found. It
5 | * should not be modified by hand.
6 | */
7 |
8 | package com.markupartist.android.widget.actionbar;
9 |
10 | public final class R {
11 | public static final class attr {
12 | /**
Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
13 |
This may also be a reference to a resource (in the form
14 | "@[package:]type:name") or
15 | theme attribute (in the form
16 | "?[package:][type:]name")
17 | containing a value of this type.
18 | */
19 | public static final int title=0x7f010000;
20 | }
21 | public static final class color {
22 | public static final int actionbar_background_end=0x7f040003;
23 | public static final int actionbar_background_item_pressed_end=0x7f040005;
24 | public static final int actionbar_background_item_pressed_start=0x7f040004;
25 | public static final int actionbar_background_start=0x7f040002;
26 | public static final int actionbar_separator=0x7f040000;
27 | public static final int actionbar_title=0x7f040001;
28 | public static final int background1=0x7f04000b;
29 | public static final int background2=0x7f04000c;
30 | public static final int background3=0x7f04000d;
31 | public static final int foreground1=0x7f040009;
32 | public static final int foreground2=0x7f04000a;
33 | public static final int pinned_header_background=0x7f040010;
34 | public static final int session_foreground_past=0x7f04000f;
35 | public static final int title_background=0x7f040006;
36 | public static final int title_separator=0x7f04000e;
37 | public static final int title_text=0x7f040007;
38 | public static final int title_text_alt=0x7f040008;
39 | }
40 | public static final class dimen {
41 | public static final int actionbar_height=0x7f050000;
42 | public static final int actionbar_item_height=0x7f050001;
43 | public static final int actionbar_item_width=0x7f050002;
44 | public static final int colorstrip_height=0x7f050003;
45 | public static final int now_playing_height=0x7f050005;
46 | public static final int text_size_large=0x7f050008;
47 | public static final int text_size_medium=0x7f050007;
48 | public static final int text_size_small=0x7f050006;
49 | public static final int title_height=0x7f050004;
50 | }
51 | public static final class drawable {
52 | public static final int actionbar_back_indicator=0x7f020000;
53 | public static final int actionbar_background=0x7f020001;
54 | public static final int actionbar_btn=0x7f020002;
55 | public static final int actionbar_btn_normal=0x7f020003;
56 | public static final int actionbar_btn_pressed=0x7f020004;
57 | public static final int ic_menu_allfriends=0x7f020005;
58 | public static final int ic_menu_camera=0x7f020006;
59 | public static final int ic_menu_compose=0x7f020007;
60 | public static final int ic_menu_delete=0x7f020008;
61 | public static final int ic_menu_gallery=0x7f020009;
62 | public static final int ic_menu_home=0x7f02000a;
63 | public static final int ic_menu_login=0x7f02000b;
64 | public static final int ic_menu_preferences=0x7f02000c;
65 | public static final int ic_menu_refresh=0x7f02000d;
66 | public static final int ic_menu_slideshow=0x7f02000e;
67 | public static final int ic_menu_star=0x7f02000f;
68 | public static final int ic_title_camera=0x7f020010;
69 | public static final int ic_title_home=0x7f020011;
70 | public static final int ic_title_refresh=0x7f020012;
71 | public static final int icon=0x7f020013;
72 | public static final int stub=0x7f020014;
73 | }
74 | public static final class id {
75 | public static final int actionbar_actions=0x7f090006;
76 | public static final int actionbar_home=0x7f090001;
77 | public static final int actionbar_home_bg=0x7f090003;
78 | public static final int actionbar_home_btn=0x7f090004;
79 | public static final int actionbar_home_is_back=0x7f090005;
80 | public static final int actionbar_home_logo=0x7f090002;
81 | public static final int actionbar_item=0x7f090009;
82 | public static final int actionbar_progress=0x7f090007;
83 | public static final int actionbar_title=0x7f090008;
84 | public static final int activity_button=0x7f09000b;
85 | public static final int btnCamera=0x7f09001c;
86 | public static final int btnGallery=0x7f09001d;
87 | public static final int btnLogin=0x7f09001a;
88 | public static final int btnUpload=0x7f09001e;
89 | public static final int camera_button=0x7f09000e;
90 | public static final int caption=0x7f090016;
91 | public static final int captionRow=0x7f09001f;
92 | public static final int clear=0x7f090023;
93 | public static final int comments=0x7f090017;
94 | public static final int dashboardActionbar=0x7f09000a;
95 | public static final int gallery_button=0x7f09000f;
96 | public static final int gridview=0x7f090011;
97 | public static final int image=0x7f090015;
98 | public static final int imageListActionbar=0x7f090012;
99 | public static final int imageView=0x7f090022;
100 | public static final int lblCaption=0x7f090020;
101 | public static final int list=0x7f090013;
102 | public static final int login_button=0x7f090010;
103 | public static final int pictureActionbar=0x7f09001b;
104 | public static final int popular_button=0x7f09000c;
105 | public static final int screen=0x7f090000;
106 | public static final int txtCaption=0x7f090021;
107 | public static final int txtPassword=0x7f090019;
108 | public static final int txtUsername=0x7f090018;
109 | public static final int user_feed_button=0x7f09000d;
110 | public static final int username=0x7f090014;
111 | }
112 | public static final class layout {
113 | public static final int actionbar=0x7f030000;
114 | public static final int actionbar_item=0x7f030001;
115 | public static final int dashboard_home=0x7f030002;
116 | public static final int image_grid=0x7f030003;
117 | public static final int image_list=0x7f030004;
118 | public static final int image_list_item=0x7f030005;
119 | public static final int login=0x7f030006;
120 | public static final int take_picture=0x7f030007;
121 | }
122 | public static final class menu {
123 | public static final int take_picture_menu=0x7f080000;
124 | }
125 | public static final class string {
126 | public static final int actionbar_activity_not_found=0x7f060002;
127 | public static final int app_header=0x7f060003;
128 | public static final int app_name=0x7f060001;
129 | public static final int choose_gallery=0x7f060009;
130 | public static final int comment=0x7f06000b;
131 | public static final int dashboard=0x7f060012;
132 | public static final int default_comment=0x7f06000c;
133 | public static final int empty=0x7f060011;
134 | public static final int feed=0x7f06000d;
135 | public static final int gallery=0x7f060010;
136 | public static final int hello=0x7f060000;
137 | public static final int login=0x7f060013;
138 | public static final int main_menu_clear=0x7f060007;
139 | public static final int main_menu_credentials=0x7f060004;
140 | public static final int main_menu_preferences=0x7f060006;
141 | public static final int main_menu_refresh=0x7f060005;
142 | public static final int no_registration_disclaimer=0x7f060014;
143 | public static final int popular=0x7f06000e;
144 | public static final int take_picture=0x7f060008;
145 | public static final int upload=0x7f06000a;
146 | public static final int userfeed=0x7f06000f;
147 | }
148 | public static final class style {
149 | public static final int ActionBar=0x7f070000;
150 | public static final int ActionBarHomeItem=0x7f070002;
151 | public static final int ActionBarHomeLogo=0x7f070003;
152 | public static final int ActionBarItem=0x7f070001;
153 | public static final int ActionBarProgressBar=0x7f070004;
154 | public static final int DashboardButton=0x7f070005;
155 | }
156 | public static final class styleable {
157 | /** Attributes that can be used with a ActionBar.
158 |
Includes the following attributes:
159 |
160 |
161 |
162 | | Attribute | Description |
163 | {@link #ActionBar_title org.acmelab.andgram:title} | |
164 |
165 | @see #ActionBar_title
166 | */
167 | public static final int[] ActionBar = {
168 | 0x7f010000
169 | };
170 | /**
171 | This symbol is the offset where the {@link org.acmelab.andgram.R.attr#title}
172 | attribute's value can be found in the {@link #ActionBar} array.
173 |
174 |
175 |
Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
176 |
This may also be a reference to a resource (in the form
177 | "@[package:]type:name") or
178 | theme attribute (in the form
179 | "?[package:][type:]name")
180 | containing a value of this type.
181 | @attr name android:title
182 | */
183 | public static final int ActionBar_title = 0;
184 | };
185 | }
186 |
--------------------------------------------------------------------------------
/src/org/acmelab/andgram/ImageLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011, Mark L. Chang . All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without modification, are
5 | * permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this list of
8 | * conditions and the following disclaimer.
9 | *
10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 | * of conditions and the following disclaimer in the documentation and/or other
12 | * materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY Mark L. Chang ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK L. CHANG OR
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * The views and conclusions contained in the software and documentation are those of the
25 | * authors and should not be interpreted as representing official policies, either expressed
26 | * or implied, of Mark L. Chang.
27 | *
28 | * -----------------------
29 | * Code here for image listview handling was based heavily upon work done by
30 | * Fedor Vlasov (http://www.fedorvlasov.com/), originally posted here:
31 | * http://stackoverflow.com/questions/541966/android-how-do-i-do-a-lazy-load-of-images-in-listview/3068012#3068012
32 | *
33 | * No copyright was associated with the LazyList.zip source, so it was used and modified.
34 | */
35 |
36 | package org.acmelab.andgram;
37 |
38 | import java.io.File;
39 | import java.io.FileInputStream;
40 | import java.io.FileNotFoundException;
41 | import java.io.FileOutputStream;
42 | import java.io.InputStream;
43 | import java.io.OutputStream;
44 | import java.lang.ref.SoftReference;
45 | import java.net.URL;
46 | import java.util.HashMap;
47 | import java.util.Stack;
48 | import android.app.Activity;
49 | import android.content.Context;
50 | import android.graphics.Bitmap;
51 | import android.graphics.BitmapFactory;
52 | import android.util.Log;
53 | import android.widget.ImageView;
54 |
55 | public class ImageLoader {
56 |
57 | // the simplest in-memory cache implementation.
58 | // This should be replaced with something like SoftReference or
59 | // BitmapOptions.inPurgeable(since 1.6)
60 | private HashMap> cache=new HashMap>();
61 |
62 | final int stub_id = R.drawable.stub;
63 | private File cacheDir;
64 |
65 | public ImageLoader(Context context){
66 | // Make the background thread low priority. This way it will not affect the UI performance
67 | photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
68 |
69 | //Find the dir to save cached images
70 | if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
71 | cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),Utils.OUTPUT_DIR);
72 | else
73 | cacheDir=context.getCacheDir();
74 | if(!cacheDir.exists())
75 | cacheDir.mkdirs();
76 | }
77 |
78 | public void DisplayImage(String url, Activity activity, ImageView imageView)
79 | {
80 | Log.i(Utils.TAG, "Displaying image: " + url);
81 | if(cache.containsKey(url)) {
82 | Log.i(Utils.TAG, "Found cached image " + url);
83 | SoftReference softRef = cache.get(url);
84 | Bitmap bitmap = softRef.get();
85 | if( bitmap == null ) {
86 | Log.i(Utils.TAG, "But re-queuing GC'ed image: " + url);
87 | // maybe? : cache.remove(softRef);
88 | queuePhoto(url, activity, imageView);
89 | imageView.setImageResource(stub_id);
90 | } else {
91 | Log.i(Utils.TAG, "Setting image bitmap");
92 | imageView.setImageBitmap(softRef.get());
93 | if( softRef.get() == null ) {
94 | Log.e(Utils.TAG, "Null bitmap: " + url);
95 | }
96 | }
97 | }
98 | else
99 | {
100 | Log.i(Utils.TAG, "Not in cache, queueing " + url);
101 | queuePhoto(url, activity, imageView);
102 | imageView.setImageResource(stub_id);
103 | }
104 | }
105 |
106 | private void queuePhoto(String url, Activity activity, ImageView imageView)
107 | {
108 | Log.i(Utils.TAG, "Queueing: " + url);
109 |
110 | // This ImageView may be used for other images before.
111 | // So there may be some old tasks in the queue. We need to discard them.
112 | photosQueue.Clean(imageView);
113 | PhotoToLoad p=new PhotoToLoad(url, imageView);
114 | synchronized( photosQueue.photosToLoad ){
115 | photosQueue.photosToLoad.push(p);
116 | photosQueue.photosToLoad.notifyAll();
117 | }
118 |
119 | //start thread if it's not started yet
120 | if(photoLoaderThread.getState()==Thread.State.NEW)
121 | photoLoaderThread.start();
122 | }
123 |
124 | private Bitmap getBitmap(String url)
125 | {
126 | // I identify images by hashcode. Not a perfect solution, good for the demo.
127 | Log.i(Utils.TAG, "Getting image in thread: " + url);
128 | String filename=String.valueOf(url.hashCode());
129 | File f=new File(cacheDir, filename);
130 |
131 | //from SD cache
132 | Bitmap b = decodeFile(f);
133 | if(b != null) {
134 | Log.i(Utils.TAG, "Found in cache." );
135 | return b;
136 | }
137 |
138 |
139 | //from web
140 | try {
141 | Log.i(Utils.TAG, "Downloading from web");
142 | Bitmap bitmap = null;
143 | InputStream is = new URL(url).openStream();
144 | OutputStream os = new FileOutputStream(f);
145 | Utils.CopyStream(is, os);
146 | os.close();
147 | is.close();
148 | bitmap = decodeFile(f);
149 | return bitmap;
150 | } catch (Exception ex){
151 | ex.printStackTrace();
152 | return null;
153 | }
154 | }
155 |
156 | //decodes image and scales it to reduce memory consumption
157 | private Bitmap decodeFile(File f){
158 | try {
159 | Log.i(Utils.TAG, "Decoding image: " + f.toString());
160 | Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
161 | Log.i(Utils.TAG, "decoded a real bitmap!");
162 | return(b);
163 | } catch (FileNotFoundException e) {
164 | Log.i(Utils.TAG, "File not found");
165 | return null;
166 | } catch (Exception ex) {
167 | Log.e(Utils.TAG, "Some other shit failed in decodeFile");
168 | ex.printStackTrace();
169 | return null;
170 | }
171 | }
172 |
173 | // Task for the queue
174 | private class PhotoToLoad
175 | {
176 | public String url;
177 | public ImageView imageView;
178 | public PhotoToLoad(String u, ImageView i){
179 | url = u;
180 | imageView = i;
181 | }
182 | }
183 |
184 | PhotosQueue photosQueue = new PhotosQueue();
185 |
186 | public void stopThread()
187 | {
188 | photoLoaderThread.interrupt();
189 | }
190 |
191 | // stores list of photos to download
192 | class PhotosQueue
193 | {
194 | private Stack photosToLoad=new Stack();
195 |
196 | //removes all instances of this ImageView
197 | public void Clean(ImageView image)
198 | {
199 | for(int j=0 ;j(bmp));
230 | Object tag = photoToLoad.imageView.getTag();
231 | if(tag != null && ((String)tag).equals(photoToLoad.url)){
232 | BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad.imageView);
233 | Activity a = (Activity)photoToLoad.imageView.getContext();
234 | a.runOnUiThread(bd);
235 | } else {
236 | Log.i(Utils.TAG, "Got image w/o tag!");
237 | }
238 | }
239 | }
240 | if(Thread.interrupted())
241 | break;
242 | }
243 | } catch (InterruptedException e) {
244 | //allow thread to exit
245 | }
246 | }
247 | }
248 |
249 | PhotosLoader photoLoaderThread = new PhotosLoader();
250 |
251 | // Used to display bitmap in the UI thread
252 | class BitmapDisplayer implements Runnable
253 | {
254 | Bitmap bitmap;
255 | ImageView imageView;
256 |
257 | public BitmapDisplayer(Bitmap b, ImageView i) {
258 | bitmap = b;
259 | imageView = i;
260 | }
261 |
262 | public void run()
263 | {
264 | if(bitmap != null)
265 | imageView.setImageBitmap(bitmap);
266 | else
267 | imageView.setImageResource(stub_id);
268 | }
269 | }
270 |
271 | public void clearCache() {
272 | // clear memory cache
273 | cache.clear();
274 |
275 | //clear SD cache
276 | File[] files=cacheDir.listFiles();
277 | for(File f:files)
278 | f.delete();
279 | }
280 |
281 | }
282 |
--------------------------------------------------------------------------------
/src/org/acmelab/andgram/ImageGridActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011, Mark L. Chang . All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without modification, are
5 | * permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this list of
8 | * conditions and the following disclaimer.
9 | *
10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 | * of conditions and the following disclaimer in the documentation and/or other
12 | * materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY Mark L. Chang ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK L. CHANG OR
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * The views and conclusions contained in the software and documentation are those of the
25 | * authors and should not be interpreted as representing official policies, either expressed
26 | * or implied, of Mark L. Chang.
27 | */
28 |
29 | package org.acmelab.andgram;
30 |
31 | import android.app.Activity;
32 | import android.app.AlertDialog;
33 | import android.content.DialogInterface;
34 | import android.content.Intent;
35 | import android.os.AsyncTask;
36 | import android.os.Bundle;
37 | import android.util.Log;
38 | import android.view.View;
39 | import android.widget.*;
40 | import com.markupartist.android.widget.ActionBar;
41 | import org.apache.http.HttpEntity;
42 | import org.apache.http.HttpResponse;
43 | import org.apache.http.HttpStatus;
44 | import org.apache.http.NameValuePair;
45 | import org.apache.http.client.methods.HttpGet;
46 | import org.apache.http.impl.client.DefaultHttpClient;
47 | import org.apache.http.message.BasicNameValuePair;
48 | import org.json.JSONArray;
49 | import org.json.JSONException;
50 | import org.json.JSONObject;
51 | import org.json.JSONTokener;
52 |
53 | import java.io.BufferedReader;
54 | import java.io.InputStreamReader;
55 | import java.text.SimpleDateFormat;
56 | import java.util.ArrayList;
57 | import java.util.Date;
58 | import java.util.List;
59 |
60 | public class ImageGridActivity extends Activity {
61 |
62 | private String sourceUrl;
63 |
64 | GridView grid;
65 | LazyGridAdapter adapter;
66 | ArrayList instagramImageList;
67 | DefaultHttpClient httpClient = null;
68 |
69 | @Override
70 | public void onCreate(Bundle savedInstanceState) {
71 | super.onCreate(savedInstanceState);
72 | setContentView(R.layout.image_grid);
73 |
74 | Bundle extras = getIntent().getExtras();
75 | sourceUrl = extras.getString("url");
76 | grid = (GridView)findViewById(R.id.gridview);
77 |
78 | httpClient = new DefaultHttpClient();
79 | httpClient.getParams().setParameter("http.useragent", "Instagram");
80 |
81 | init();
82 | }
83 |
84 | private void init() {
85 | // set that list to background downloader
86 | instagramImageList = new ArrayList();
87 | adapter = new LazyGridAdapter(this, instagramImageList);
88 | grid.setAdapter(adapter);
89 | new FetchActivity().execute();
90 | }
91 |
92 | private void refresh() {
93 | instagramImageList.clear();
94 | adapter.notifyDataSetChanged();
95 | new FetchActivity().execute();
96 | }
97 |
98 |
99 | @Override
100 | public void onDestroy()
101 | {
102 | adapter.imageLoader.stopThread();
103 | grid.setAdapter(null);
104 | super.onDestroy();
105 | }
106 |
107 | public void clearCache(View view) {
108 | adapter.imageLoader.clearCache();
109 | adapter.notifyDataSetChanged();
110 | }
111 |
112 | private class FetchActivity extends AsyncTask {
113 | protected void onPreExecute() {
114 | }
115 |
116 | protected void onPostExecute(Boolean result) {
117 | if(result) {
118 | adapter.notifyDataSetChanged();
119 | }
120 | }
121 |
122 | protected void onProgressUpdate(String toastText) {
123 | Toast.makeText(ImageGridActivity.this, toastText, Toast.LENGTH_SHORT).show();
124 | }
125 |
126 | protected Boolean doInBackground(Void... voids) {
127 | Log.i(Utils.TAG, "Image fetch");
128 |
129 | if( Utils.isOnline(getApplicationContext()) == false ) {
130 | publishProgress("No connection to Internet.\nTry again later");
131 | Log.i(Utils.TAG, "No internet, didn't load Activity Feed");
132 | return false;
133 | }
134 |
135 | if( !Utils.doLogin(getApplicationContext(), httpClient) ) {
136 | publishProgress("Login failed");
137 | return false;
138 | } else {
139 | try {
140 | HttpGet httpGet = new HttpGet(sourceUrl);
141 | HttpResponse httpResponse = httpClient.execute(httpGet);
142 |
143 | // test result code
144 | if( httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
145 | publishProgress("Login failed.");
146 | Log.e(Utils.TAG, "Login status code bad.");
147 | return false;
148 | }
149 |
150 | // test json response
151 | HttpEntity httpEntity = httpResponse.getEntity();
152 | if( httpEntity != null ) {
153 | BufferedReader reader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "UTF-8"));
154 | String json = reader.readLine();
155 | JSONTokener jsonTokener = new JSONTokener(json);
156 | JSONObject jsonObject = new JSONObject(jsonTokener);
157 | Log.i(Utils.TAG,"JSON: " + jsonObject.toString());
158 |
159 | String loginStatus = jsonObject.getString("status");
160 |
161 | if( !loginStatus.equals("ok") ) {
162 | publishProgress("Activity feed did not return status ok");
163 | Log.e(Utils.TAG, "JSON status not ok: " + jsonObject.getString("status"));
164 | return false;
165 | } else {
166 | // parse the activity feed
167 | Log.i(Utils.TAG, "Getting images from activity feed");
168 | JSONArray items = jsonObject.getJSONArray("items");
169 |
170 | // get image URLs and commentary
171 | for( int i=0; i< items.length(); i++ ) {
172 | // create a new instance
173 | InstagramImage instagramImage = new InstagramImage();
174 |
175 | // image
176 | JSONObject entry = (JSONObject)items.get(i);
177 | JSONArray imageVersions = entry.getJSONArray("image_versions");
178 | JSONObject bigImage = (JSONObject)imageVersions.get(2);
179 | instagramImage.url = bigImage.getString("url");
180 | instagramImage.pk = ((Long)entry.getLong("pk")).toString();
181 |
182 | // user
183 | JSONObject user = entry.getJSONObject("user");
184 | instagramImage.username = user.getString("username");
185 |
186 | // date taken_at
187 | Long dateLong = entry.getLong("taken_at");
188 | SimpleDateFormat formatter = new SimpleDateFormat("MMMM d, yyyy HH:mm");
189 | instagramImage.taken_at = formatter.format(new Date(dateLong * 1000L));
190 |
191 | // comments (and caption)
192 | JSONArray comments = entry.getJSONArray("comments");
193 | if( comments != null ) {
194 | ArrayList commentList = new ArrayList();
195 | for( int c=0; c < comments.length(); c++ ) {
196 | JSONObject comment = comments.getJSONObject(c);
197 | user = comment.getJSONObject("user");
198 | if(c==0) {
199 | instagramImage.caption = comment.getString("text");
200 | } else {
201 | commentList.add(new Comment(user.getString("username"),
202 | comment.getString("text")));
203 | }
204 | }
205 | instagramImage.comment_list = commentList;
206 | }
207 |
208 | // likers
209 | try {
210 | JSONArray liker_ids = entry.getJSONArray("liker_ids");
211 | if( liker_ids != null) {
212 | if( liker_ids.length() > 0 ) {
213 | ArrayList likerList = new ArrayList();
214 | likerList.add(Integer.toString(liker_ids.length()));
215 | instagramImage.liker_list = likerList;
216 | instagramImage.liker_list_is_count = true;
217 | }
218 | }
219 | } catch( JSONException j ) {}
220 |
221 | try {
222 | JSONArray likers = entry.getJSONArray("likers");
223 | if( likers != null ) {
224 | ArrayList likerList = new ArrayList();
225 | StringBuilder likerString = new StringBuilder();
226 | if( likers.length() > 0 ) {
227 | likerString.append("Liked by: ");
228 | for( int l=0; l < likers.length(); l++ ) {
229 | JSONObject like = likers.getJSONObject(l);
230 | likerString.append(like.getString("username") + " ");
231 | likerList.add(like.getString("username"));
232 | }
233 | likerString.append("");
234 | instagramImage.liker_list = likerList;
235 | instagramImage.liker_list_is_count = false;
236 | }
237 | }
238 | } catch( JSONException j ) {}
239 |
240 | instagramImageList.add(instagramImage);
241 | }
242 |
243 | return true;
244 | }
245 | } else {
246 | publishProgress("Improper data returned from Instagram");
247 | Log.e(Utils.TAG, "instagram returned bad data");
248 | return false;
249 | }
250 | } catch (Exception e) {
251 | e.printStackTrace();
252 | return false;
253 | }
254 | }
255 | }
256 | }
257 |
258 | private class RefreshAction implements ActionBar.Action {
259 |
260 | public int getDrawable() {
261 | return R.drawable.ic_title_refresh;
262 | }
263 |
264 | public void performAction(View view) {
265 | refresh();
266 | }
267 | }
268 | }
--------------------------------------------------------------------------------
/src/org/acmelab/andgram/Utils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011, Mark L. Chang . All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without modification, are
5 | * permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this list of
8 | * conditions and the following disclaimer.
9 | *
10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 | * of conditions and the following disclaimer in the documentation and/or other
12 | * materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY Mark L. Chang ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK L. CHANG OR
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * The views and conclusions contained in the software and documentation are those of the
25 | * authors and should not be interpreted as representing official policies, either expressed
26 | * or implied, of Mark L. Chang.
27 | */
28 |
29 | package org.acmelab.andgram;
30 |
31 | import android.app.Activity;
32 | import android.content.Context;
33 | import android.content.Intent;
34 | import android.content.SharedPreferences;
35 | import android.net.ConnectivityManager;
36 | import android.util.Log;
37 | import android.widget.Toast;
38 | import org.apache.http.HttpEntity;
39 | import org.apache.http.HttpResponse;
40 | import org.apache.http.HttpStatus;
41 | import org.apache.http.NameValuePair;
42 | import org.apache.http.client.entity.UrlEncodedFormEntity;
43 | import org.apache.http.client.methods.HttpGet;
44 | import org.apache.http.client.methods.HttpPost;
45 | import org.apache.http.impl.client.DefaultHttpClient;
46 | import org.apache.http.message.BasicNameValuePair;
47 | import org.apache.http.protocol.HTTP;
48 | import org.json.JSONArray;
49 | import org.json.JSONException;
50 | import org.json.JSONObject;
51 | import org.json.JSONTokener;
52 |
53 | import java.io.*;
54 | import java.text.SimpleDateFormat;
55 | import java.util.ArrayList;
56 | import java.util.Date;
57 | import java.util.List;
58 |
59 | public class Utils {
60 | // strings
61 | public static final String TAG = "ANDGRAM";
62 | public static final String PREFS_NAME = "andgram_prefs";
63 |
64 | // intent identifiers
65 | public static final int CAMERA_PIC_REQUEST = 1;
66 | public static final int UPLOAD_FROM_GALLERY = 2;
67 | public static final int UPLOAD_FROM_CAMERA = 3;
68 | public static final int SELECT_FROM_GALLERY = 4;
69 |
70 | // image constants
71 | public static final String OUTPUT_DIR = "andgram";
72 | public static final String OUTPUT_FILE = "andgram.jpg";
73 | public static final String OUTPUT_FILE_PROCESSED = "andgram_processed.jpg";
74 | public static final int IMAGE_WIDTH = 612;
75 | public static final int IMAGE_HEIGHT = 612;
76 | public static final int IMAGE_BORDER = 24;
77 | public static final int IMAGE_CORNER_RADIUS = 35;
78 | public static final int IMAGE_JPEG_COMPRESSION_QUALITY = 75;
79 |
80 | // url constants
81 | public static final String LOGIN_URL = "https://instagr.am/api/v1/accounts/login/";
82 | public static final String LOGOUT_URL = "http://instagr.am/api/v1/accounts/logout/";
83 | public static final String UPLOAD_URL = "http://instagr.am/api/v1/media/upload/";
84 | public static final String CONFIGURE_URL = "https://instagr.am/api/v1/media/configure/";
85 | public static final String TIMELINE_URL = "http://instagr.am/api/v1/feed/timeline/";
86 | public static final String POPULAR_URL = "http://instagr.am/api/v1/feed/popular/";
87 |
88 | public static final String USERTIMELINE_PREFIX = "http://instagr.am/api/v1/feed/user/";
89 | public static final String MEDIA_PREFIX = "http://instagr.am/api/v1/media/";
90 | public static final String LIKE_POSTFIX = "/like/";
91 | public static final String UNLIKE_POSTFIX = "/unlike/";
92 | public static final String COMMENT_POSTFIX = "/comment/";
93 | public static final String DELETE_POSTFIX = "/delete/";
94 | public static final String PERMALINK_POSTFIX = "/permalink/";
95 |
96 |
97 | public static boolean isOnline(Context ctx) {
98 | ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
99 | if( cm.getActiveNetworkInfo() == null ) return false;
100 | return cm.getActiveNetworkInfo().isConnectedOrConnecting();
101 | }
102 |
103 | public static String createUserTimelineUrl(String pk) {
104 | return USERTIMELINE_PREFIX + pk + "/";
105 | }
106 |
107 | public static String getUserPk(Context ctx) {
108 | SharedPreferences sharedPreferences = ctx.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
109 | Boolean loginValid = sharedPreferences.getBoolean("loginValid",false);
110 |
111 | if( loginValid ) {
112 | return sharedPreferences.getString("pk",null);
113 | } else {
114 | return null;
115 | }
116 | }
117 |
118 | public static String createDeleteUrl(String id) {
119 | return MEDIA_PREFIX + id + DELETE_POSTFIX;
120 | }
121 |
122 |
123 | public static String createLikeUrl(String id) {
124 | return MEDIA_PREFIX + id + LIKE_POSTFIX;
125 | }
126 |
127 | public static String createUnlikeUrl(String id) {
128 | return MEDIA_PREFIX + id + UNLIKE_POSTFIX;
129 | }
130 |
131 | public static String createCommentUrl(String id) {
132 | return MEDIA_PREFIX + id + COMMENT_POSTFIX;
133 | }
134 |
135 | public static String createPermalinkUrl(String id) {
136 | return MEDIA_PREFIX + id + PERMALINK_POSTFIX;
137 | }
138 |
139 | public static void CopyStream(InputStream is, OutputStream os)
140 | {
141 | final int buffer_size=1024;
142 | try
143 | {
144 | byte[] bytes=new byte[buffer_size];
145 | for(;;)
146 | {
147 | int count=is.read(bytes, 0, buffer_size);
148 | if(count==-1)
149 | break;
150 | os.write(bytes, 0, count);
151 | }
152 | }
153 | catch(Exception ex){}
154 | }
155 |
156 | public static void launchCredentials(Context ctx) {
157 | SharedPreferences sharedPreferences = ctx.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
158 | SharedPreferences.Editor editor = sharedPreferences.edit();
159 | editor.clear();
160 | editor.putBoolean("loginValid", false);
161 | editor.commit();
162 |
163 | Intent loginIntent = new Intent(ctx, LoginActivity.class);
164 | loginIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
165 | ctx.startActivity(loginIntent);
166 | }
167 |
168 | public static String getUsername(Context ctx) {
169 | SharedPreferences sharedPreferences = ctx.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
170 | Boolean loginValid = sharedPreferences.getBoolean("loginValid",false);
171 |
172 | if( loginValid ) {
173 | return sharedPreferences.getString("username",null);
174 | } else {
175 | return null;
176 | }
177 | }
178 |
179 | public static String getPk(Context ctx) {
180 | SharedPreferences sharedPreferences = ctx.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
181 | Boolean loginValid = sharedPreferences.getBoolean("loginValid",false);
182 |
183 | if( loginValid ) {
184 | return sharedPreferences.getString("pk",null);
185 | } else {
186 | return null;
187 | }
188 | }
189 |
190 | public static boolean doLogin(Context ctx, DefaultHttpClient httpClient) {
191 | Log.i(TAG, "Doing login");
192 |
193 | // gather login info
194 | SharedPreferences sharedPreferences = ctx.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
195 | Boolean loginValid = sharedPreferences.getBoolean("loginValid",false);
196 |
197 | if( !loginValid ) {
198 | launchCredentials(ctx);
199 | return false;
200 | }
201 |
202 | String username = sharedPreferences.getString("username","");
203 | String password = sharedPreferences.getString("password","");
204 |
205 | // create POST
206 | HttpPost httpPost = new HttpPost(LOGIN_URL);
207 | List postParams = new ArrayList();
208 | postParams.add(new BasicNameValuePair("username", username));
209 | postParams.add(new BasicNameValuePair("password", password));
210 | postParams.add(new BasicNameValuePair("device_id", "0000"));
211 |
212 | try {
213 | httpPost.setEntity(new UrlEncodedFormEntity(postParams, HTTP.UTF_8));
214 | HttpResponse httpResponse = httpClient.execute(httpPost);
215 |
216 | // test result code
217 | if( httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
218 | Log.i(TAG, "Login HTTP status fail");
219 | return false;
220 | }
221 |
222 | // test json response
223 | HttpEntity httpEntity = httpResponse.getEntity();
224 | if( httpEntity != null ) {
225 | BufferedReader reader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "UTF-8"));
226 | String json = reader.readLine();
227 | JSONTokener jsonTokener = new JSONTokener(json);
228 | JSONObject jsonObject = new JSONObject(jsonTokener);
229 | Log.i(TAG,"JSON: " + jsonObject.toString());
230 |
231 | String loginStatus = jsonObject.getString("status");
232 |
233 | if( !loginStatus.equals("ok") ) {
234 | Log.e(TAG, "JSON status not ok: " + jsonObject.getString("status"));
235 | return false;
236 | }
237 | }
238 |
239 | } catch( IOException e ) {
240 | Log.e(TAG, "HttpPost error: " + e.toString());
241 | return false;
242 | } catch( JSONException e ) {
243 | Log.e(TAG, "JSON parse error: " + e.toString());
244 | return false;
245 | }
246 |
247 | return true;
248 | }
249 |
250 | public static String doRestulPut(DefaultHttpClient httpClient, String url,
251 | List postParams, Context ctx) {
252 | // create POST
253 | HttpPost httpPost = new HttpPost(url);
254 |
255 | try {
256 | httpPost.setEntity(new UrlEncodedFormEntity(postParams, HTTP.UTF_8));
257 | HttpResponse httpResponse = httpClient.execute(httpPost);
258 |
259 | // test result code
260 | if( httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
261 | Log.i(TAG, "Login HTTP status fail");
262 | return null;
263 | }
264 |
265 | // test json response
266 | HttpEntity httpEntity = httpResponse.getEntity();
267 | if( httpEntity != null ) {
268 | BufferedReader reader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "UTF-8"));
269 | String json = reader.readLine();
270 | JSONTokener jsonTokener = new JSONTokener(json);
271 | JSONObject jsonObject = new JSONObject(jsonTokener);
272 | Log.i(TAG,"JSON: " + jsonObject.toString());
273 |
274 | String loginStatus = jsonObject.getString("status");
275 |
276 | if( !loginStatus.equals("ok") ) {
277 | Log.e(TAG, "JSON status not ok: " + jsonObject.getString("status"));
278 | return null;
279 | } else {
280 | return json;
281 | }
282 | } else {
283 | return null;
284 | }
285 | } catch( IOException e ) {
286 | Log.e(TAG, "HttpPost error: " + e.toString());
287 | return null;
288 | } catch( JSONException e ) {
289 | Log.e(TAG, "JSON parse error: " + e.toString());
290 | return null;
291 | }
292 | }
293 |
294 | public static String doRestfulGet(DefaultHttpClient httpClient, String url, Context ctx) {
295 | Log.i(Utils.TAG, "Image fetch");
296 |
297 | if( Utils.isOnline(ctx) == false ) {
298 | Toast.makeText(ctx,"No connection to Internet.\nTry again later",Toast.LENGTH_SHORT).show();
299 | Log.i(Utils.TAG, "No internet!");
300 | return null;
301 | }
302 |
303 |
304 | try {
305 | HttpGet httpGet = new HttpGet(url);
306 | HttpResponse httpResponse = httpClient.execute(httpGet);
307 |
308 | // test result code
309 | if( httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
310 | Toast.makeText(ctx, "Action failed.", Toast.LENGTH_SHORT).show();
311 | Log.e(TAG, "Return status code bad.");
312 | return null;
313 | }
314 |
315 | // test json response
316 | HttpEntity httpEntity = httpResponse.getEntity();
317 | if( httpEntity != null ) {
318 | BufferedReader reader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "UTF-8"));
319 | String json = reader.readLine();
320 | JSONTokener jsonTokener = new JSONTokener(json);
321 | JSONObject jsonObject = new JSONObject(jsonTokener);
322 | Log.i(TAG,"JSON: " + jsonObject.toString());
323 |
324 | String loginStatus = jsonObject.getString("status");
325 |
326 | if( !loginStatus.equals("ok") ) {
327 | Toast.makeText(ctx,"Network activity did not return ok",Toast.LENGTH_SHORT).show();
328 | Log.e(TAG, "JSON status not ok: " + jsonObject.getString("status"));
329 | return null;
330 | } else {
331 | return json;
332 | }
333 | } else {
334 | Toast.makeText(ctx,"Improper data returned from Instagram",Toast.LENGTH_SHORT).show();
335 | Log.e(TAG, "instagram returned bad data");
336 | return null;
337 | }
338 | } catch (Exception e) {
339 | e.printStackTrace();
340 | return null;
341 | }
342 | }
343 |
344 | }
--------------------------------------------------------------------------------
/src/org/acmelab/andgram/ImageListActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011, Mark L. Chang . All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without modification, are
5 | * permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this list of
8 | * conditions and the following disclaimer.
9 | *
10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 | * of conditions and the following disclaimer in the documentation and/or other
12 | * materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY Mark L. Chang ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK L. CHANG OR
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * The views and conclusions contained in the software and documentation are those of the
25 | * authors and should not be interpreted as representing official policies, either expressed
26 | * or implied, of Mark L. Chang.
27 | *
28 | * -----------------------
29 | * Code here for image listview handling was based heavily upon work done by
30 | * Fedor Vlasov (http://www.fedorvlasov.com/), originally posted here:
31 | * http://stackoverflow.com/questions/541966/android-how-do-i-do-a-lazy-load-of-images-in-listview/3068012#3068012
32 | *
33 | * No copyright was associated with the LazyList.zip source, so it was used and modified.
34 | */
35 |
36 | package org.acmelab.andgram;
37 |
38 | import android.app.Activity;
39 | import android.app.AlertDialog;
40 | import android.content.DialogInterface;
41 | import android.content.Intent;
42 | import android.os.AsyncTask;
43 | import android.os.Bundle;
44 | import android.util.Log;
45 | import android.view.View;
46 | import android.widget.*;
47 | import com.markupartist.android.widget.ActionBar;
48 | import org.apache.http.HttpEntity;
49 | import org.apache.http.HttpResponse;
50 | import org.apache.http.HttpStatus;
51 | import org.apache.http.NameValuePair;
52 | import org.apache.http.client.methods.HttpGet;
53 | import org.apache.http.impl.client.DefaultHttpClient;
54 | import org.apache.http.message.BasicNameValuePair;
55 | import org.json.JSONArray;
56 | import org.json.JSONException;
57 | import org.json.JSONObject;
58 | import org.json.JSONTokener;
59 |
60 | import java.io.BufferedReader;
61 | import java.io.InputStreamReader;
62 | import java.text.SimpleDateFormat;
63 | import java.util.ArrayList;
64 | import java.util.Date;
65 | import java.util.List;
66 |
67 | public class ImageListActivity extends Activity {
68 |
69 | private static final String TAG = "ANDGRAM";
70 | private String sourceUrl;
71 |
72 | ActionBar actionBar;
73 | ListView list;
74 | LazyAdapter adapter;
75 | ArrayList instagramImageList;
76 | DefaultHttpClient httpClient = null;
77 |
78 | @Override
79 | public void onCreate(Bundle savedInstanceState) {
80 | super.onCreate(savedInstanceState);
81 | setContentView(R.layout.image_list);
82 |
83 | Bundle extras = getIntent().getExtras();
84 | sourceUrl = extras.getString("url");
85 | int titleId = extras.getInt("title");
86 | String title = getResources().getString(titleId);
87 |
88 | Intent dashboardIntent = new Intent(getApplicationContext(), DashboardActivity.class);
89 | dashboardIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
90 |
91 | actionBar = (ActionBar) findViewById(R.id.imageListActionbar);
92 | actionBar.setTitle(title);
93 | actionBar.addAction(new RefreshAction());
94 | final ActionBar.Action goHomeAction = new ActionBar.IntentAction(this,
95 | dashboardIntent, R.drawable.ic_title_home);
96 | actionBar.addAction(goHomeAction);
97 |
98 | list=(ListView)findViewById(R.id.list);
99 | list.setOnItemClickListener(itemClickListener);
100 |
101 | httpClient = new DefaultHttpClient();
102 | httpClient.getParams().setParameter("http.useragent", "Instagram");
103 |
104 | init();
105 | }
106 |
107 | private void init() {
108 | // set that list to background downloader
109 | instagramImageList = new ArrayList();
110 | adapter = new LazyAdapter(this, instagramImageList);
111 | list.setAdapter(adapter);
112 | new FetchActivity().execute();
113 | }
114 |
115 | private void refresh() {
116 | instagramImageList.clear();
117 | adapter.notifyDataSetChanged();
118 | new FetchActivity().execute();
119 | }
120 |
121 |
122 | public AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
123 | public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
124 | Log.i(Utils.TAG, "Clicked: " + String.valueOf(i));
125 |
126 | final InstagramImage instagramImage = (InstagramImage)adapter.getItem(i);
127 | final String username = Utils.getUsername(getApplicationContext());
128 |
129 | // build dialog
130 | List dialogItems = new ArrayList();
131 |
132 | // 0: like/unlike
133 | if( instagramImage.liker_list != null ) {
134 | if( instagramImage.liker_list.contains(username) ) {
135 | dialogItems.add("Unlike");
136 | } else {
137 | dialogItems.add("Like");
138 | }
139 | } else {
140 | dialogItems.add("Like");
141 | }
142 |
143 | // 1: comment
144 | dialogItems.add("Comment");
145 |
146 | // 2: share + 3: delete
147 | if( instagramImage.username.equals(username) ) {
148 | dialogItems.add("Share");
149 | dialogItems.add("Delete");
150 | }
151 |
152 | final CharSequence[] items = dialogItems.toArray(new String[dialogItems.size()]);
153 |
154 | AlertDialog.Builder builder = new AlertDialog.Builder(ImageListActivity.this);
155 | builder.setTitle("Choose your action");
156 | builder.setItems(items, new DialogInterface.OnClickListener() {
157 | public void onClick(DialogInterface dialog, int item) {
158 | switch(item) {
159 | case 0:
160 | likeUnlike(instagramImage, username);
161 | break;
162 | case 1:
163 | showCommentDialog(instagramImage, username);
164 | break;
165 | case 2:
166 | showShareDialog(instagramImage);
167 | break;
168 | case 3:
169 | showDeleteDialog(instagramImage);
170 | break;
171 | default:
172 | break;
173 | }
174 | }
175 | });
176 | AlertDialog alert = builder.create();
177 | alert.show();
178 |
179 | }
180 | };
181 |
182 | public void showShareDialog(InstagramImage image) {
183 | final InstagramImage finalImage = image;
184 |
185 | // get the permalink
186 | String url = Utils.createPermalinkUrl(finalImage.pk);
187 | String jsonResponse = Utils.doRestfulGet(httpClient, url, getApplicationContext());
188 | if( jsonResponse != null ) {
189 | try {
190 | JSONTokener jsonTokener = new JSONTokener(jsonResponse);
191 | JSONObject jsonObject = new JSONObject(jsonTokener);
192 | String permalink = jsonObject.getString("permalink");
193 | if( permalink != null ) {
194 | // shoot the intent
195 | // will default to "messaging / sms" if nothing else is installed
196 | Intent sharingIntent = new Intent(Intent.ACTION_SEND);
197 | //Text seems to be necessary for Facebook and Twitter
198 | sharingIntent.setType("text/plain");
199 | sharingIntent.putExtra(Intent.EXTRA_TEXT, image.caption + " " + permalink);
200 | startActivity(Intent.createChooser(sharingIntent,"Share using"));
201 | }
202 | } catch (JSONException j) {
203 | Log.e(TAG, "JSON parse error: " + j.toString());
204 | Toast.makeText(getApplicationContext(),
205 | "There was an error communicating with Instagram",
206 | Toast.LENGTH_SHORT).show();
207 | }
208 | } else {
209 | Toast.makeText(getApplicationContext(),
210 | "Failed to get permalink for the image", Toast.LENGTH_SHORT).show();
211 | }
212 |
213 | }
214 |
215 |
216 |
217 | public void showDeleteDialog(InstagramImage image) {
218 | final InstagramImage finalImage = image;
219 |
220 | AlertDialog.Builder builder = new AlertDialog.Builder(this);
221 | builder.setMessage("Are you sure you want to delete this image?")
222 | .setCancelable(false)
223 | .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
224 | public void onClick(DialogInterface dialog, int id) {
225 | String url = Utils.createDeleteUrl(finalImage.pk);
226 | String jsonResponse = Utils.doRestfulGet(httpClient, url, getApplicationContext());
227 | if( jsonResponse != null ) {
228 | instagramImageList.remove(finalImage);
229 | adapter.notifyDataSetChanged();
230 | } else {
231 | Toast.makeText(getApplicationContext(),
232 | "Delete failed", Toast.LENGTH_SHORT).show();
233 | }
234 | }
235 | })
236 | .setNegativeButton("No", new DialogInterface.OnClickListener() {
237 | public void onClick(DialogInterface dialog, int id) {
238 | dialog.cancel();
239 | }
240 | });
241 | AlertDialog alert = builder.create();
242 | alert.show();
243 | }
244 |
245 | public void showCommentDialog(InstagramImage image, String username) {
246 | final InstagramImage finalImage = image;
247 | final String finalUsername = username;
248 |
249 | AlertDialog.Builder alert = new AlertDialog.Builder(this);
250 |
251 | alert.setTitle("Comment");
252 |
253 | // Set an EditText view to get user input
254 | final EditText input = new EditText(this);
255 | alert.setView(input);
256 |
257 | alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
258 | public void onClick(DialogInterface dialog, int whichButton) {
259 | String comment = input.getText().toString();
260 | postComment(comment, finalImage, finalUsername);
261 | }
262 | });
263 |
264 | alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
265 | public void onClick(DialogInterface dialog, int whichButton) {
266 | // Canceled.
267 | }
268 | });
269 |
270 | alert.show();
271 | }
272 |
273 | public void postComment(String comment, InstagramImage image, String username) {
274 | List postParams = new ArrayList();
275 | postParams.add(new BasicNameValuePair("comment_text", comment));
276 | String jsonResponse = Utils.doRestulPut(httpClient,
277 | Utils.createCommentUrl(image.pk),
278 | postParams,
279 | this);
280 | if( jsonResponse != null ) {
281 | image.comment_list.add(new Comment(username,comment));
282 | Toast.makeText(this,
283 | "Comment successful", Toast.LENGTH_SHORT).show();
284 | adapter.notifyDataSetChanged();
285 | } else {
286 | Toast.makeText(this,
287 | "Comment failed", Toast.LENGTH_SHORT).show();
288 | }
289 | }
290 |
291 | public void likeUnlike(InstagramImage image, String username) {
292 | String url;
293 |
294 | if( image.liker_list != null ) {
295 | if( image.liker_list.contains(Utils.getUsername(getApplicationContext()))) {
296 | unlike(image,username);
297 | } else {
298 | like(image, username);
299 | }
300 | } else {
301 | like(image, username);
302 | }
303 |
304 | }
305 |
306 | public void like(InstagramImage image, String username) {
307 | String url = Utils.createLikeUrl(image.pk);
308 | String jsonResponse = Utils.doRestfulGet(httpClient, url, ImageListActivity.this);
309 | if( jsonResponse != null ) {
310 | if( image.liker_list == null ) image.liker_list = new ArrayList();
311 | image.liker_list.add(username);
312 | adapter.notifyDataSetChanged();
313 | }
314 | }
315 |
316 | public void unlike(InstagramImage image, String username) {
317 | String url = Utils.createUnlikeUrl(image.pk);
318 | String jsonResponse = Utils.doRestfulGet(httpClient, url, ImageListActivity.this);
319 | if( jsonResponse != null ) {
320 | if( image.liker_list == null ) image.liker_list = new ArrayList();
321 | image.liker_list.remove(username);
322 | adapter.notifyDataSetChanged();
323 | }
324 | }
325 |
326 | @Override
327 | public void onDestroy()
328 | {
329 | adapter.imageLoader.stopThread();
330 | list.setAdapter(null);
331 | super.onDestroy();
332 | }
333 |
334 | public void clearCache(View view) {
335 | adapter.imageLoader.clearCache();
336 | adapter.notifyDataSetChanged();
337 | }
338 |
339 | private class FetchActivity extends AsyncTask {
340 | protected void onPreExecute() {
341 | actionBar.setProgressBarVisibility(View.VISIBLE);
342 | }
343 |
344 | protected void onPostExecute(Boolean result) {
345 | actionBar.setProgressBarVisibility(View.GONE);
346 | if(result) {
347 | adapter.notifyDataSetChanged();
348 | }
349 | }
350 |
351 | protected void onProgressUpdate(String toastText) {
352 | Toast.makeText(ImageListActivity.this, toastText, Toast.LENGTH_SHORT).show();
353 | }
354 |
355 | protected Boolean doInBackground(Void... voids) {
356 | Log.i(Utils.TAG, "Image fetch");
357 |
358 | if( Utils.isOnline(getApplicationContext()) == false ) {
359 | publishProgress("No connection to Internet.\nTry again later");
360 | Log.i(Utils.TAG, "No internet, didn't load Activity Feed");
361 | return false;
362 | }
363 |
364 | if( !Utils.doLogin(getApplicationContext(), httpClient) ) {
365 | publishProgress("Login failed");
366 | return false;
367 | } else {
368 | try {
369 | HttpGet httpGet = new HttpGet(sourceUrl);
370 | HttpResponse httpResponse = httpClient.execute(httpGet);
371 |
372 | // test result code
373 | if( httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
374 | publishProgress("Login failed.");
375 | Log.e(TAG, "Login status code bad.");
376 | return false;
377 | }
378 |
379 | // test json response
380 | HttpEntity httpEntity = httpResponse.getEntity();
381 | if( httpEntity != null ) {
382 | BufferedReader reader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "UTF-8"));
383 | String json = reader.readLine();
384 | JSONTokener jsonTokener = new JSONTokener(json);
385 | JSONObject jsonObject = new JSONObject(jsonTokener);
386 | Log.i(TAG,"JSON: " + jsonObject.toString());
387 |
388 | String loginStatus = jsonObject.getString("status");
389 |
390 | if( !loginStatus.equals("ok") ) {
391 | publishProgress("Activity feed did not return status ok");
392 | Log.e(TAG, "JSON status not ok: " + jsonObject.getString("status"));
393 | return false;
394 | } else {
395 | // parse the activity feed
396 | Log.i(Utils.TAG, "Getting images from activity feed");
397 | JSONArray items = jsonObject.getJSONArray("items");
398 |
399 | // get image URLs and commentary
400 | for( int i=0; i< items.length(); i++ ) {
401 | // create a new instance
402 | InstagramImage instagramImage = new InstagramImage();
403 |
404 | // image
405 | JSONObject entry = (JSONObject)items.get(i);
406 | JSONArray imageVersions = entry.getJSONArray("image_versions");
407 | JSONObject bigImage = (JSONObject)imageVersions.get(0);
408 | instagramImage.url = bigImage.getString("url");
409 | instagramImage.pk = ((Long)entry.getLong("pk")).toString();
410 |
411 | // user
412 | JSONObject user = entry.getJSONObject("user");
413 | instagramImage.username = user.getString("username");
414 |
415 | // date taken_at
416 | Long dateLong = entry.getLong("taken_at");
417 | SimpleDateFormat formatter = new SimpleDateFormat("MMMM d, yyyy HH:mm");
418 | instagramImage.taken_at = formatter.format(new Date(dateLong * 1000L));
419 |
420 | // comments (and caption)
421 | JSONArray comments = entry.getJSONArray("comments");
422 | if( comments != null ) {
423 | ArrayList commentList = new ArrayList();
424 | for( int c=0; c < comments.length(); c++ ) {
425 | JSONObject comment = comments.getJSONObject(c);
426 | user = comment.getJSONObject("user");
427 | if(c==0) {
428 | instagramImage.caption = comment.getString("text");
429 | } else {
430 | commentList.add(new Comment(user.getString("username"),
431 | comment.getString("text")));
432 | }
433 | }
434 | instagramImage.comment_list = commentList;
435 | }
436 |
437 | // likers
438 | try {
439 | JSONArray liker_ids = entry.getJSONArray("liker_ids");
440 | if( liker_ids != null) {
441 | if( liker_ids.length() > 0 ) {
442 | ArrayList likerList = new ArrayList();
443 | likerList.add(Integer.toString(liker_ids.length()));
444 | instagramImage.liker_list = likerList;
445 | instagramImage.liker_list_is_count = true;
446 | }
447 | }
448 | } catch( JSONException j ) {}
449 |
450 | try {
451 | JSONArray likers = entry.getJSONArray("likers");
452 | if( likers != null ) {
453 | ArrayList likerList = new ArrayList();
454 | StringBuilder likerString = new StringBuilder();
455 | if( likers.length() > 0 ) {
456 | likerString.append("Liked by: ");
457 | for( int l=0; l < likers.length(); l++ ) {
458 | JSONObject like = likers.getJSONObject(l);
459 | likerString.append(like.getString("username") + " ");
460 | likerList.add(like.getString("username"));
461 | }
462 | likerString.append("");
463 | instagramImage.liker_list = likerList;
464 | instagramImage.liker_list_is_count = false;
465 | }
466 | }
467 | } catch( JSONException j ) {}
468 |
469 | instagramImageList.add(instagramImage);
470 | }
471 |
472 | return true;
473 | }
474 | } else {
475 | publishProgress("Improper data returned from Instagram");
476 | Log.e(TAG, "instagram returned bad data");
477 | return false;
478 | }
479 | } catch (Exception e) {
480 | e.printStackTrace();
481 | return false;
482 | }
483 | }
484 | }
485 | }
486 |
487 | private class RefreshAction implements ActionBar.Action {
488 |
489 | public int getDrawable() {
490 | return R.drawable.ic_title_refresh;
491 | }
492 |
493 | public void performAction(View view) {
494 | refresh();
495 | }
496 | }
497 | }
--------------------------------------------------------------------------------
/src/org/acmelab/andgram/TakePictureActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011, Mark L. Chang . All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without modification, are
5 | * permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this list of
8 | * conditions and the following disclaimer.
9 | *
10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 | * of conditions and the following disclaimer in the documentation and/or other
12 | * materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY Mark L. Chang ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK L. CHANG OR
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * The views and conclusions contained in the software and documentation are those of the
25 | * authors and should not be interpreted as representing official policies, either expressed
26 | * or implied, of Mark L. Chang.
27 | */
28 |
29 | package org.acmelab.andgram;
30 |
31 | import android.app.Activity;
32 | import android.content.ContentResolver;
33 | import android.content.Intent;
34 | import android.database.Cursor;
35 | import android.graphics.*;
36 | import android.graphics.drawable.BitmapDrawable;
37 | import android.graphics.drawable.Drawable;
38 | import android.net.Uri;
39 | import android.os.AsyncTask;
40 | import android.os.Bundle;
41 | import android.os.Environment;
42 | import android.provider.MediaStore;
43 | import android.util.Log;
44 | import android.view.Menu;
45 | import android.view.MenuInflater;
46 | import android.view.MenuItem;
47 | import android.view.View;
48 | import android.widget.*;
49 | import com.markupartist.android.widget.ActionBar;
50 | import org.apache.http.HttpEntity;
51 | import org.apache.http.HttpResponse;
52 | import org.apache.http.HttpStatus;
53 | import org.apache.http.NameValuePair;
54 | import org.apache.http.client.entity.UrlEncodedFormEntity;
55 | import org.apache.http.client.methods.HttpPost;
56 | import org.apache.http.entity.mime.HttpMultipartMode;
57 | import org.apache.http.entity.mime.MultipartEntity;
58 | import org.apache.http.entity.mime.content.FileBody;
59 | import org.apache.http.entity.mime.content.StringBody;
60 | import org.apache.http.impl.client.DefaultHttpClient;
61 | import org.apache.http.message.BasicNameValuePair;
62 | import org.apache.http.protocol.HTTP;
63 | import org.json.JSONObject;
64 | import org.json.JSONTokener;
65 |
66 | import java.io.*;
67 | import java.util.ArrayList;
68 | import java.util.HashMap;
69 | import java.util.List;
70 | import java.util.Map;
71 |
72 | public class TakePictureActivity extends Activity
73 | {
74 | private static final String TAG = Utils.TAG;
75 |
76 | EditText txtCaption = null;
77 | ImageView imageView = null;
78 | Button uploadButton = null;
79 | Button cameraButton = null;
80 | Button galleryButton = null;
81 |
82 | private DefaultHttpClient httpClient = null;
83 | private Uri srcImageUri = null;
84 | private Uri processedImageUri = null;
85 | private boolean imageReady = false;
86 | private ActionBar actionBar;
87 |
88 | /** Called when the activity is first created. */
89 | @Override
90 | public void onCreate(Bundle savedInstanceState)
91 | {
92 | super.onCreate(savedInstanceState);
93 | setContentView(R.layout.take_picture);
94 |
95 | httpClient = new DefaultHttpClient();
96 | httpClient.getParams().setParameter("http.useragent", "Instagram");
97 |
98 | txtCaption = (EditText)findViewById(R.id.txtCaption);
99 | imageView = (ImageView)findViewById(R.id.imageView);
100 | uploadButton = (Button)findViewById(R.id.btnUpload);
101 | cameraButton = (Button)findViewById(R.id.btnCamera);
102 | galleryButton = (Button)findViewById(R.id.btnGallery);
103 |
104 | // create the output dir for us
105 | File outputDirectory = new File(Environment.getExternalStorageDirectory(), Utils.OUTPUT_DIR);
106 | outputDirectory.mkdirs();
107 |
108 | Intent dashboardIntent = new Intent(getApplicationContext(), DashboardActivity.class);
109 | dashboardIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
110 |
111 | actionBar = (ActionBar) findViewById(R.id.pictureActionbar);
112 | actionBar.setTitle(R.string.upload);
113 | final ActionBar.Action goHomeAction = new ActionBar.IntentAction(this,
114 | dashboardIntent, R.drawable.ic_title_home);
115 | actionBar.addAction(goHomeAction);
116 |
117 | // figure out what action we are supposed to take
118 | Bundle extras = getIntent().getExtras();
119 | int action = extras.getInt("action");
120 | switch(action) {
121 | case Utils.UPLOAD_FROM_CAMERA:
122 | galleryButton.setVisibility(View.GONE);
123 | cameraButton.setVisibility(View.VISIBLE);
124 | takePicture(null);
125 | break;
126 | case Utils.UPLOAD_FROM_GALLERY:
127 | cameraButton.setVisibility(View.GONE);
128 | galleryButton.setVisibility(View.VISIBLE);
129 | uploadFromGallery(null);
130 | break;
131 | default:
132 | break;
133 | }
134 | }
135 |
136 | @Override
137 | public boolean onCreateOptionsMenu(Menu menu) {
138 | MenuInflater inflater = getMenuInflater();
139 | inflater.inflate(R.menu.take_picture_menu, menu);
140 | return true;
141 | }
142 |
143 | @Override
144 | public boolean onOptionsItemSelected(MenuItem item) {
145 | switch( item.getItemId() ) {
146 | case R.id.clear:
147 | doClear();
148 | return true;
149 | default:
150 | return super.onOptionsItemSelected(item);
151 | }
152 | }
153 |
154 | public void uploadFromGallery(View view) {
155 | Intent intent = new Intent();
156 | intent.setType("image/*");
157 | intent.setAction(Intent.ACTION_GET_CONTENT);
158 | startActivityForResult(Intent.createChooser(intent,
159 | "Select Picture"), Utils.SELECT_FROM_GALLERY);
160 | }
161 |
162 | public void takePicture(View view) {
163 | Log.i(TAG, "Taking picture");
164 | File outputFile = new File(Environment.getExternalStorageDirectory(), Utils.OUTPUT_DIR + "/" + Utils.OUTPUT_FILE);
165 | srcImageUri = Uri.fromFile(outputFile);
166 | Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
167 | cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, srcImageUri);
168 | startActivityForResult(cameraIntent, Utils.CAMERA_PIC_REQUEST);
169 | }
170 |
171 | public void doClear() {
172 | Log.i(TAG, "Clear image");
173 | if( imageReady ) {
174 | imageReady = false;
175 | srcImageUri = null;
176 | processedImageUri = null;
177 |
178 | findViewById(R.id.captionRow).setVisibility(View.INVISIBLE);
179 | findViewById(R.id.btnUpload).setEnabled(false);
180 | ((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();
181 | imageView.setImageBitmap(null);
182 | }
183 | }
184 |
185 | public void startUpload(View view) {
186 | if( Utils.isOnline(getApplicationContext()) == false ) {
187 | Toast.makeText(TakePictureActivity.this,
188 | "No connection to Internet.\nTry again later.",
189 | Toast.LENGTH_SHORT);
190 | Log.i(Utils.TAG, "No internet, didn't start upload.");
191 | return;
192 | }
193 |
194 | Log.i(TAG, "Starting async upload");
195 | if( !Utils.doLogin(getApplicationContext(), httpClient) ) {
196 | Toast.makeText(TakePictureActivity.this, "Login failed", Toast.LENGTH_SHORT).show();
197 | } else {
198 | new UploadPhotoTask().execute();
199 | }
200 | }
201 |
202 | // fixme: this doesn't need to be a Map return
203 | public Map doUpload() {
204 | Log.i(TAG, "Upload");
205 | Long timeInMilliseconds = System.currentTimeMillis()/1000;
206 | String timeInSeconds = timeInMilliseconds.toString();
207 | MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
208 | Map returnMap = new HashMap();
209 |
210 | // check for cookies
211 | if( httpClient.getCookieStore() == null ) {
212 | returnMap.put("result", "Not logged in");
213 | return returnMap;
214 | }
215 |
216 | try {
217 | // create multipart data
218 | File imageFile = new File(processedImageUri.getPath());
219 | FileBody partFile = new FileBody(imageFile);
220 | StringBody partTime = new StringBody(timeInSeconds);
221 | multipartEntity.addPart("photo", partFile );
222 | multipartEntity.addPart("device_timestamp", partTime);
223 | } catch ( Exception e ) {
224 | Log.e(TAG,"Error creating mulitpart form: " + e.toString());
225 | returnMap.put("result", "Error creating mulitpart form: " + e.toString());
226 | return returnMap;
227 | }
228 |
229 | // upload
230 | try {
231 | HttpPost httpPost = new HttpPost(Utils.UPLOAD_URL);
232 | httpPost.setEntity(multipartEntity);
233 | HttpResponse httpResponse = httpClient.execute(httpPost);
234 | HttpEntity httpEntity = httpResponse.getEntity();
235 | Log.i(TAG, "Upload status: " + httpResponse.getStatusLine());
236 |
237 | // test result code
238 | if( httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
239 | Log.e(TAG, "Login HTTP status fail: " + httpResponse.getStatusLine().getStatusCode());
240 | returnMap.put("result", "HTTP status error: " + httpResponse.getStatusLine().getStatusCode() );
241 | return returnMap;
242 | }
243 |
244 | // test json response
245 | // should look like
246 | /*
247 | {"status": "ok"}
248 | */
249 | if( httpEntity != null ) {
250 | BufferedReader reader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "UTF-8"));
251 | String json = reader.readLine();
252 | JSONTokener jsonTokener = new JSONTokener(json);
253 | JSONObject jsonObject = new JSONObject(jsonTokener);
254 | Log.i(TAG,"JSON: " + jsonObject.toString());
255 |
256 | String loginStatus = jsonObject.getString("status");
257 |
258 | if( !loginStatus.equals("ok") ) {
259 | Log.e(TAG, "JSON status not ok: " + jsonObject.getString("status"));
260 | returnMap.put("result", "JSON status not ok: " + jsonObject.getString("status") );
261 | return returnMap;
262 | }
263 | }
264 | } catch( Exception e ) {
265 | Log.e(TAG, "HttpPost exception: " + e.toString());
266 | returnMap.put("result", "HttpPost exception: " + e.toString());
267 | return returnMap;
268 | }
269 |
270 | // configure / comment
271 | try {
272 | HttpPost httpPost = new HttpPost(Utils.CONFIGURE_URL);
273 | String partComment = txtCaption.getText().toString();
274 | List postParams = new ArrayList();
275 | postParams.add(new BasicNameValuePair("device_timestamp", timeInSeconds));
276 | postParams.add(new BasicNameValuePair("caption", partComment));
277 | httpPost.setEntity(new UrlEncodedFormEntity(postParams, HTTP.UTF_8));
278 | HttpResponse httpResponse = httpClient.execute(httpPost);
279 | HttpEntity httpEntity = httpResponse.getEntity();
280 |
281 | // test result code
282 | if( httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
283 | Log.e(TAG, "Upload comment fail: " + httpResponse.getStatusLine().getStatusCode());
284 | returnMap.put("result", "Upload comment fail: " + httpResponse.getStatusLine().getStatusCode() );
285 | return returnMap;
286 | }
287 |
288 | returnMap.put("result", "ok");
289 | return returnMap;
290 | } catch( Exception e ) {
291 | Log.e(TAG, "HttpPost comment error: " + e.toString());
292 | returnMap.put("result", "HttpPost comment error: " + e.toString());
293 | return returnMap;
294 | }
295 | }
296 |
297 | // fixme: this is terrible, but gets it done
298 | private void processImage(String filePath) {
299 | Bitmap resizedBitmap;
300 | Bitmap croppedBitmap;
301 | Bitmap roundedBitmap;
302 | Bitmap srcBitmap;
303 |
304 | StringBuilder srcImageFilename = new StringBuilder();
305 | StringBuilder processedImageFilename = new StringBuilder();
306 |
307 | // such a fucking hack. sorry.
308 | if( filePath != null ) {
309 | srcImageFilename.append(filePath);
310 | } else {
311 | srcImageFilename.append(Environment.getExternalStorageDirectory() +
312 | "/" + Utils.OUTPUT_DIR + "/" + Utils.OUTPUT_FILE);
313 | }
314 | processedImageFilename.append(Environment.getExternalStorageDirectory() +
315 | "/" + Utils.OUTPUT_DIR + "/" + Utils.OUTPUT_FILE_PROCESSED);
316 |
317 | // Get the source image's dimensions
318 | srcBitmap = BitmapFactory.decodeFile(srcImageFilename.toString());
319 |
320 | int srcWidth = srcBitmap.getWidth();
321 | int srcHeight = srcBitmap.getHeight();
322 | int desiredWidth = Utils.IMAGE_WIDTH;
323 | int desiredHeight = Utils.IMAGE_HEIGHT;
324 |
325 | // scale image short length to desiredWidth
326 | // crop long dimension
327 | if( srcWidth > desiredWidth && srcHeight > desiredWidth ) {
328 | if( srcWidth < srcHeight ) {
329 | float scaleRatio = (float)srcWidth/(float)desiredWidth;
330 | float newHeight = (float)srcHeight / scaleRatio;
331 | resizedBitmap = Bitmap.createScaledBitmap(srcBitmap, desiredWidth, (int)newHeight, true);
332 | srcBitmap.recycle();
333 |
334 | int offsetY = resizedBitmap.getHeight()/2 - desiredWidth / 2;
335 | croppedBitmap = Bitmap.createBitmap(resizedBitmap, 0, offsetY, desiredWidth, desiredHeight);
336 | resizedBitmap.recycle();
337 | roundedBitmap = getRoundedCornerBitmap(croppedBitmap);
338 | croppedBitmap.recycle();
339 | } else {
340 | float scaleRatio = (float)srcHeight/(float)desiredWidth;
341 | float newWidth = (float)srcWidth/scaleRatio;
342 | resizedBitmap = Bitmap.createScaledBitmap(srcBitmap, (int)newWidth, desiredHeight, true);
343 | srcBitmap.recycle();
344 |
345 | int offsetX = resizedBitmap.getWidth()/2 - desiredWidth / 2;
346 | croppedBitmap = Bitmap.createBitmap(resizedBitmap, offsetX, 0, desiredWidth, desiredHeight);
347 | resizedBitmap.recycle();
348 | roundedBitmap = getRoundedCornerBitmap(croppedBitmap);
349 | croppedBitmap.recycle();
350 | }
351 |
352 | // Save
353 | try {
354 | File outputFile = new File(Environment.getExternalStorageDirectory(), Utils.OUTPUT_DIR + "/" + Utils.OUTPUT_FILE_PROCESSED);
355 | processedImageUri = Uri.fromFile(outputFile);
356 |
357 | FileOutputStream out = new FileOutputStream(processedImageFilename.toString());
358 | roundedBitmap.compress(Bitmap.CompressFormat.JPEG,
359 | Utils.IMAGE_JPEG_COMPRESSION_QUALITY, out);
360 | roundedBitmap.recycle();
361 | Log.i(TAG,"Processed image, now returning");
362 | } catch( Exception e ) {
363 |
364 | }
365 | } else if( srcWidth <= desiredWidth && srcHeight <= desiredWidth ) {
366 | Log.i(Utils.TAG, "Small image, leaving alone");
367 | processedImageUri = srcImageUri;
368 | } else {
369 | // one dimension is smaller than desired, one is larger
370 | // resize the larger dimension down then round it into 612x612
371 | if( srcWidth > desiredWidth ) {
372 | float scaleRatio = (float)srcWidth/(float)desiredWidth;
373 | float newHeight = (float)srcHeight/scaleRatio;
374 | resizedBitmap = Bitmap.createScaledBitmap(srcBitmap, desiredWidth, (int)newHeight, true);
375 | srcBitmap.recycle();
376 | roundedBitmap = getScaledRoundedCornerBitmap(resizedBitmap);
377 | resizedBitmap.recycle();
378 | } else {
379 | float scaleRatio = (float)srcHeight/(float)desiredWidth;
380 | float newWidth = (float)srcWidth/scaleRatio;
381 | resizedBitmap = Bitmap.createScaledBitmap(srcBitmap, (int)newWidth, desiredHeight, true);
382 | srcBitmap.recycle();
383 | roundedBitmap = getScaledRoundedCornerBitmap(resizedBitmap);
384 | resizedBitmap.recycle();
385 | }
386 |
387 | // Save
388 | try {
389 | File outputFile = new File(Environment.getExternalStorageDirectory(), Utils.OUTPUT_DIR + "/" + Utils.OUTPUT_FILE_PROCESSED);
390 | processedImageUri = Uri.fromFile(outputFile);
391 |
392 | FileOutputStream out = new FileOutputStream(processedImageFilename.toString());
393 | roundedBitmap.compress(Bitmap.CompressFormat.JPEG,
394 | Utils.IMAGE_JPEG_COMPRESSION_QUALITY, out);
395 | roundedBitmap.recycle();
396 | Log.i(TAG,"Processed image, now returning");
397 | } catch( Exception e ) {
398 |
399 | }
400 | }
401 | }
402 |
403 | private Bitmap getScaledRoundedCornerBitmap(Bitmap bitmap) {
404 | // paint bitmap into black bitmap
405 | Bitmap roundedBitmap = Bitmap.createBitmap(Utils.IMAGE_WIDTH, Utils.IMAGE_HEIGHT, Bitmap.Config.ARGB_8888);
406 | Canvas canvas = new Canvas(roundedBitmap);
407 |
408 | final int color = 0xff424242;
409 | final Paint paint = new Paint();
410 | final Rect destRect = new Rect((Utils.IMAGE_WIDTH-bitmap.getWidth())/2,
411 | Utils.IMAGE_BORDER,
412 | (Utils.IMAGE_WIDTH)-(Utils.IMAGE_WIDTH-bitmap.getWidth())/2,
413 | Utils.IMAGE_HEIGHT-Utils.IMAGE_BORDER);
414 | final RectF rectF = new RectF(destRect);
415 | final Rect srcRect = new Rect(0,0,bitmap.getWidth(), Utils.IMAGE_HEIGHT);
416 | final float roundPx = Utils.IMAGE_CORNER_RADIUS;
417 |
418 | paint.setAntiAlias(true);
419 | canvas.drawARGB(0, 0, 0, 0);
420 | paint.setColor(color);
421 | canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
422 |
423 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
424 | canvas.drawBitmap(bitmap, srcRect, destRect, paint);
425 |
426 | return roundedBitmap;
427 | }
428 |
429 | private Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
430 | Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
431 | bitmap.getHeight(), Bitmap.Config.ARGB_8888);
432 | Canvas canvas = new Canvas(output);
433 |
434 | final int color = 0xff424242;
435 | final Paint paint = new Paint();
436 | final Rect rect = new Rect(Utils.IMAGE_BORDER, Utils.IMAGE_BORDER, Utils.IMAGE_WIDTH-Utils.IMAGE_BORDER,
437 | Utils.IMAGE_HEIGHT-Utils.IMAGE_BORDER);
438 | final RectF rectF = new RectF(rect);
439 | final float roundPx = Utils.IMAGE_CORNER_RADIUS;
440 |
441 | paint.setAntiAlias(true);
442 | canvas.drawARGB(0, 0, 0, 0);
443 | paint.setColor(color);
444 | canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
445 |
446 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
447 | canvas.drawBitmap(bitmap, rect, rect, paint);
448 |
449 | return output;
450 |
451 | }
452 |
453 | private void showProcessedImage() {
454 | getContentResolver().notifyChange(processedImageUri, null);
455 | ContentResolver contentResolver = getContentResolver();
456 | Bitmap imageBitmap;
457 | LinearLayout captionRow = (LinearLayout)findViewById(R.id.captionRow);
458 | try {
459 | captionRow.setVisibility(View.VISIBLE);
460 |
461 | Drawable toRecycle = imageView.getDrawable();
462 | if( toRecycle != null ) {
463 | Bitmap bitmapToRecycle = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
464 | if( bitmapToRecycle != null ) {
465 | ((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();
466 | }
467 | }
468 | imageBitmap = android.provider.MediaStore.Images.Media.getBitmap(contentResolver, processedImageUri);
469 | imageView.setImageBitmap(imageBitmap);
470 | Log.i(TAG, "Image: " + processedImageUri.toString());
471 | imageReady = true;
472 |
473 | // turn on upload button
474 | uploadButton.setEnabled(true);
475 |
476 | } catch ( Exception e ) {
477 | Toast.makeText(TakePictureActivity.this, "Image file read error", Toast.LENGTH_SHORT).show();
478 | Log.e(TAG, "File read error: " + e.toString() );
479 | doClear();
480 | }
481 | }
482 |
483 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
484 | super.onActivityResult(requestCode, resultCode, data);
485 |
486 | if( resultCode == Activity.RESULT_OK ) {
487 | switch( requestCode ) {
488 | case Utils.CAMERA_PIC_REQUEST:
489 | Log.i(TAG, "Camera returned");
490 | getContentResolver().notifyChange(srcImageUri, null);
491 | processImage(null);
492 | showProcessedImage();
493 | break;
494 | case Utils.SELECT_FROM_GALLERY:
495 | Log.i(Utils.TAG, "Gallery returned");
496 | srcImageUri = data.getData();
497 | String[] filePathColumn = {MediaStore.Images.Media.DATA};
498 |
499 | Cursor cursor = getContentResolver().query(srcImageUri, filePathColumn, null, null, null);
500 | cursor.moveToFirst();
501 |
502 | int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
503 | String filePath = cursor.getString(columnIndex);
504 | cursor.close();
505 |
506 | processImage(filePath);
507 | showProcessedImage();
508 | break;
509 | default:
510 |
511 | }
512 | }
513 | }
514 |
515 | private class UploadPhotoTask extends AsyncTask> {
516 |
517 | protected void onPreExecute() {
518 | Toast.makeText(TakePictureActivity.this, "Uploading", Toast.LENGTH_SHORT).show();
519 | }
520 |
521 | protected Map doInBackground(Void... voids) {
522 | return doUpload();
523 | }
524 |
525 | protected void onPostExecute(Map resultMap) {
526 | Toast.makeText(TakePictureActivity.this, resultMap.get("result"), Toast.LENGTH_SHORT).show();
527 | }
528 | }
529 |
530 | public void onDestroy() {
531 | doClear();
532 | super.onDestroy();
533 | }
534 | }
535 |
--------------------------------------------------------------------------------