├── .gitignore
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── me
│ │ └── kaede
│ │ └── howoldrobot
│ │ ├── RobotApplication.java
│ │ ├── analyse
│ │ ├── activity
│ │ │ └── MainActivity.java
│ │ ├── model
│ │ │ ├── Attributes.java
│ │ │ ├── Face.java
│ │ │ └── FaceRectangle.java
│ │ ├── presenter
│ │ │ ├── AnalysePresenterCompl.java
│ │ │ ├── AnimationPresenterCompl.java
│ │ │ ├── DrawPresenterCompl.java
│ │ │ ├── IAnalysePresenter.java
│ │ │ ├── IAnimationPresenter.java
│ │ │ ├── IDrawPresenter.java
│ │ │ ├── IOptionsPresenter.java
│ │ │ ├── ISharePresenter.java
│ │ │ ├── OptionsPresenterCompl.java
│ │ │ └── SharePresenterCompl.java
│ │ └── view
│ │ │ └── IPhotoView.java
│ │ ├── util
│ │ ├── AppUtil.java
│ │ ├── BitmapUtil.java
│ │ ├── FileUtil.java
│ │ └── NavigationUtil.java
│ │ └── widget
│ │ ├── AgeIndicatorLayout.java
│ │ └── FaceImageView.java
│ └── res
│ ├── drawable-xhdpi
│ ├── bg_button_round.9.png
│ └── icon_how_old_02.png
│ ├── drawable-xxhdpi
│ ├── bg_indicator.9.png
│ ├── cardui_round_bg.9.png
│ ├── icon_camera.png
│ ├── icon_gallery.png
│ ├── icon_gende_male.png
│ ├── icon_gender_female.png
│ ├── icon_launcher.png
│ ├── icon_search.png
│ └── icon_share.png
│ ├── drawable
│ └── selector_bg_button_round.xml
│ ├── layout
│ ├── activity_browser.xml
│ ├── activity_main.xml
│ ├── fragment_browser.xml
│ └── item_age_indicator.xml
│ ├── menu
│ ├── menu_browser.xml
│ └── menu_main.xml
│ ├── values-v11
│ └── styles.xml
│ ├── values-w820dp
│ └── dimens.xml
│ ├── values-zh
│ └── strings.xml
│ └── values
│ ├── color.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── readme.md
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | .idea
3 | build
4 | /local.properties
5 | /.idea/workspace.xml
6 | /.idea/libraries
7 | .DS_Store
8 | /build
9 | /*.iml
10 | /app/*.iml
11 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "21.1.2"
6 |
7 | defaultConfig {
8 | applicationId "me.kaede.howoldrobot"
9 | minSdkVersion 10
10 | targetSdkVersion 22
11 | versionCode 30
12 | versionName "0.3.0"
13 | }
14 | buildTypes {
15 | release {
16 | multiDexEnabled false
17 | minifyEnabled true
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 |
22 | packagingOptions {
23 | exclude 'META-INF/DEPENDENCIES'
24 | exclude 'META-INF/NOTICE'
25 | exclude 'META-INF/LICENSE'
26 | exclude 'META-INF/LICENSE.txt'
27 | exclude 'META-INF/NOTICE.txt'
28 | }
29 | }
30 |
31 | dependencies {
32 | //compile fileTree(dir: 'libs', include: ['*.jar'])
33 | compile 'com.android.support:appcompat-v7:22.2.1'
34 | compile 'com.android.support:support-v4:22.2.1'
35 | compile 'com.loopj.android:android-async-http:1.4.7'
36 | }
37 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\ADT\android-sdk-as/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/RobotApplication.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot;
2 |
3 | import android.app.Application;
4 |
5 | /**
6 | * Created by kaede on 2015/5/25.
7 | */
8 | public class RobotApplication extends Application {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.activity;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Intent;
5 | import android.graphics.Bitmap;
6 | import android.os.Bundle;
7 | import android.support.v7.app.ActionBarActivity;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.view.View;
11 | import android.view.animation.AlphaAnimation;
12 | import android.view.animation.AnimationSet;
13 | import android.view.animation.TranslateAnimation;
14 | import android.widget.Toast;
15 |
16 | import java.util.List;
17 |
18 | import me.kaede.howoldrobot.R;
19 | import me.kaede.howoldrobot.analyse.model.Face;
20 | import me.kaede.howoldrobot.analyse.presenter.AnalysePresenterCompl;
21 | import me.kaede.howoldrobot.analyse.presenter.AnimationPresenterCompl;
22 | import me.kaede.howoldrobot.analyse.presenter.DrawPresenterCompl;
23 | import me.kaede.howoldrobot.analyse.presenter.IAnalysePresenter;
24 | import me.kaede.howoldrobot.analyse.presenter.IAnimationPresenter;
25 | import me.kaede.howoldrobot.analyse.presenter.IDrawPresenter;
26 | import me.kaede.howoldrobot.analyse.presenter.IOptionsPresenter;
27 | import me.kaede.howoldrobot.analyse.presenter.ISharePresenter;
28 | import me.kaede.howoldrobot.analyse.presenter.OptionsPresenterCompl;
29 | import me.kaede.howoldrobot.analyse.presenter.SharePresenterCompl;
30 | import me.kaede.howoldrobot.analyse.view.IPhotoView;
31 | import me.kaede.howoldrobot.widget.AgeIndicatorLayout;
32 | import me.kaede.howoldrobot.widget.FaceImageView;
33 |
34 |
35 | public class MainActivity extends ActionBarActivity implements IPhotoView, View.OnClickListener {
36 |
37 | public static final int ACTIVITY_REQUEST_CAMERA = 0;
38 | public static final int ACTIVITY_REQUEST_GALLERY = 1;
39 | private IAnalysePresenter analysePresenter;
40 | private IDrawPresenter drawPresenter;
41 | private FaceImageView faceImageView;
42 | private ProgressDialog progressDialog;
43 | private AgeIndicatorLayout ageIndicatorLayout;
44 | private View photoContainer;
45 |
46 |
47 | @Override
48 | protected void onCreate(Bundle savedInstanceState) {
49 | super.onCreate(savedInstanceState);
50 | setContentView(R.layout.activity_main);
51 | injectView();
52 | setListener();
53 | init();
54 | }
55 |
56 | private void injectView(){
57 | faceImageView = (FaceImageView) this.findViewById(R.id.iv_main_face);
58 | ageIndicatorLayout = (AgeIndicatorLayout) this.findViewById(R.id.layout_main_age);
59 | photoContainer = this.findViewById(R.id.layout_main_photo);
60 | }
61 |
62 | private void setListener() {
63 | this.findViewById(R.id.btn_main_camera).setOnClickListener(this);
64 | this.findViewById(R.id.btn_main_gallery).setOnClickListener(this);
65 | this.findViewById(R.id.btn_main_share).setOnClickListener(this);
66 | }
67 |
68 | private void init() {
69 | analysePresenter = new AnalysePresenterCompl(this);
70 | drawPresenter = new DrawPresenterCompl(this, this);
71 | try {
72 | getSupportActionBar().setElevation(0);//取消Actionbar阴影(5.0后生效)
73 | getSupportActionBar().setTitle(getResources().getString(R.string.app_name));
74 | } catch (Exception e) {
75 | e.printStackTrace();
76 | }
77 | IAnimationPresenter animationPresenter = new AnimationPresenterCompl();
78 | animationPresenter.doLogoAnimation(findViewById(R.id.iv_main_introduce_logo));
79 | animationPresenter.doIntroduceAnimation(findViewById(R.id.layout_main_introduce_text));
80 | }
81 |
82 | @Override
83 | public void onGetFaces(List faces) {
84 | showProgressDialog(false);
85 | if (faces==null){
86 | toast(getResources().getString(R.string.main_analyze_fail));
87 | }else if (faces.size()<=0){
88 | toast(getResources().getString(R.string.main_analyze_no_face));
89 | }else {
90 | drawPresenter.drawFaces(ageIndicatorLayout, faceImageView, faces);
91 | }
92 | }
93 |
94 | @Override
95 | public void onGetImage(Bitmap bitmap, String imgPath) {
96 | faceImageView.clearFaces();
97 | ageIndicatorLayout.clearAges();
98 | faceImageView.setImageBitmap(bitmap);
99 | this.findViewById(R.id.layout_main_introduce).setVisibility(View.GONE);
100 | this.findViewById(R.id.layout_main_border).setBackgroundResource(R.color.orange_500);
101 | analysePresenter.doAnalyse(imgPath);
102 | }
103 |
104 | @Override
105 | public void showProgressDialog(Boolean isShow) {
106 | if (progressDialog == null){
107 | progressDialog = new ProgressDialog(this);
108 | progressDialog.setIndeterminate(true);
109 | progressDialog.setCancelable(false);
110 | progressDialog.setCanceledOnTouchOutside(false);
111 | progressDialog.setMessage(getResources().getString(R.string.main_loading));
112 | }
113 | if (isShow){
114 | if (!progressDialog.isShowing())
115 | progressDialog.show();
116 | }else {
117 | if (progressDialog.isShowing())
118 | progressDialog.dismiss();
119 | }
120 |
121 |
122 | }
123 |
124 | @Override
125 | public void toast(String msg) {
126 | Toast.makeText(this,msg,Toast.LENGTH_LONG).show();
127 | }
128 |
129 | @Override
130 | public View getPhotoContainer() {
131 | return photoContainer;
132 | }
133 |
134 | @Override
135 | public boolean onCreateOptionsMenu(Menu menu) {
136 | getMenuInflater().inflate(R.menu.menu_main, menu);
137 | return super.onCreateOptionsMenu(menu);
138 | }
139 |
140 | @Override
141 | public boolean onOptionsItemSelected(MenuItem item) {
142 | IOptionsPresenter optionsPresenter = new OptionsPresenterCompl();
143 | optionsPresenter.onOptionsItemClick(this,item.getItemId());
144 | return super.onOptionsItemSelected(item);
145 | }
146 |
147 | @Override
148 | public void onClick(View v) {
149 |
150 | switch(v.getId()) {
151 | case R.id.btn_main_camera:
152 | analysePresenter.pickPhoto(this,AnalysePresenterCompl.TYPE_PICK_CAMERA);
153 | break;
154 | case R.id.btn_main_gallery:
155 | analysePresenter.pickPhoto(this,AnalysePresenterCompl.TYPE_PICK_GALLERY);
156 | break;
157 | case R.id.btn_main_share:
158 | ISharePresenter sharePresenter = new SharePresenterCompl(this);
159 | sharePresenter.doShare(this, this.findViewById(android.R.id.content));
160 | break;
161 | default:
162 | break;
163 | }
164 | }
165 |
166 | @Override
167 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
168 | super.onActivityResult(requestCode, resultCode, data);
169 | switch(requestCode){
170 | case ACTIVITY_REQUEST_CAMERA:
171 | case ACTIVITY_REQUEST_GALLERY:
172 | if(resultCode==RESULT_OK){
173 | analysePresenter.getImage(this,data);
174 | }
175 | break;
176 | default:
177 | break;
178 | }
179 | }
180 |
181 |
182 | }
183 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/model/Attributes.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.model;
2 |
3 | public class Attributes{
4 | @Override
5 | public String toString() {
6 | return "Attributes{" +
7 | "gender='" + gender + '\'' +
8 | ", age=" + age +
9 | '}';
10 | }
11 |
12 | public String gender;
13 | public int age;
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/model/Face.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.model;
2 |
3 | /**
4 | * Created by kaede on 2015/5/23.
5 | */
6 | public class Face {
7 | public int faceId;
8 | public FaceRectangle faceRectangle;
9 | public Attributes attributes;
10 | public Face(){
11 | faceRectangle = new FaceRectangle();
12 | attributes = new Attributes();
13 | }
14 |
15 | @Override
16 | public String toString() {
17 | return "Face{" +
18 | "faceId=" + faceId +
19 | ", faceRectangle=" + faceRectangle +
20 | ", attributes=" + attributes +
21 | '}';
22 | }
23 | }
24 |
25 |
26 |
27 | /*
28 | [
29 | {
30 | "faceId": null,
31 | "faceRectangle": {
32 | "top": 181,
33 | "left": 568,
34 | "width": 37,
35 | "height": 37
36 | },
37 | "attributes": {
38 | "gender": "Female",
39 | "age": 25
40 | }
41 | },
42 | {
43 | "faceId": null,
44 | "faceRectangle": {
45 | "top": 184,
46 | "left": 490,
47 | "width": 35,
48 | "height": 35
49 | },
50 | "attributes": {
51 | "gender": "Male",
52 | "age": 26
53 | }
54 | },
55 | {
56 | "faceId": null,
57 | "faceRectangle": {
58 | "top": 159,
59 | "left": 326,
60 | "width": 35,
61 | "height": 35
62 | },
63 | "attributes": {
64 | "gender": "Male",
65 | "age": 44.5
66 | }
67 | },
68 | {
69 | "faceId": null,
70 | "faceRectangle": {
71 | "top": 184,
72 | "left": 635,
73 | "width": 33,
74 | "height": 33
75 | },
76 | "attributes": {
77 | "gender": "Male",
78 | "age": 20.5
79 | }
80 | },
81 | {
82 | "faceId": null,
83 | "faceRectangle": {
84 | "top": 184,
85 | "left": 254,
86 | "width": 33,
87 | "height": 33
88 | },
89 | "attributes": {
90 | "gender": "Female",
91 | "age": 24
92 | }
93 | },
94 | {
95 | "faceId": null,
96 | "faceRectangle": {
97 | "top": 187,
98 | "left": 158,
99 | "width": 32,
100 | "height": 32
101 | },
102 | "attributes": {
103 | "gender": "Female",
104 | "age": 25
105 | }
106 | },
107 | {
108 | "faceId": null,
109 | "faceRectangle": {
110 | "top": 187,
111 | "left": 400,
112 | "width": 31,
113 | "height": 31
114 | },
115 | "attributes": {
116 | "gender": "Female",
117 | "age": 24
118 | }
119 | }
120 | ]
121 | */
122 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/model/FaceRectangle.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.model;
2 |
3 | public class FaceRectangle{
4 | public int left;
5 | public int top;
6 | public int width;
7 | public int height;
8 |
9 | @Override
10 | public String toString() {
11 | return "FaceRectangle{" +
12 | "left=" + left +
13 | ", top=" + top +
14 | ", width=" + width +
15 | ", height=" + height +
16 | '}';
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/AnalysePresenterCompl.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapFactory;
8 | import android.net.Uri;
9 | import android.provider.MediaStore;
10 | import android.util.Log;
11 |
12 | import com.loopj.android.http.AsyncHttpClient;
13 | import com.loopj.android.http.AsyncHttpResponseHandler;
14 | import com.loopj.android.http.RequestParams;
15 |
16 | import org.apache.http.Header;
17 | import org.json.JSONArray;
18 | import org.json.JSONObject;
19 |
20 | import java.io.File;
21 | import java.io.IOException;
22 | import java.io.UnsupportedEncodingException;
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | import me.kaede.howoldrobot.R;
27 | import me.kaede.howoldrobot.analyse.activity.MainActivity;
28 | import me.kaede.howoldrobot.analyse.model.Face;
29 | import me.kaede.howoldrobot.analyse.view.IPhotoView;
30 | import me.kaede.howoldrobot.util.AppUtil;
31 | import me.kaede.howoldrobot.util.BitmapUtil;
32 | import me.kaede.howoldrobot.util.FileUtil;
33 |
34 | /**
35 | * Created by kaede on 2015/5/23.
36 | */
37 | public class AnalysePresenterCompl implements IAnalysePresenter {
38 | private static final String TAG = "AnalysePresenterCompl";
39 | public static final int TYPE_PICK_CAMERA = 0;
40 | public static final int TYPE_PICK_GALLERY = 1;
41 | private static final String OUTPUT_IMAGE_JPG = "output_image.jpg";
42 | private static final String OUTPUT_IMAGE_SMALL_JPG = "output_image_small.jpg";
43 | IPhotoView iPhotoView;
44 | File appBaseDir;
45 | private Uri imageUri;
46 | private AsyncHttpClient asyncHttpClient;
47 |
48 | public AnalysePresenterCompl(IPhotoView iPhotoView) {
49 | this.iPhotoView = iPhotoView;
50 | File dir = new File(FileUtil.getSdpath() + File.separator + "Moe Studio");
51 | dir.mkdir();
52 | appBaseDir = new File(dir.getAbsolutePath() + File.separator + "How Old Robot");
53 | appBaseDir.mkdir();
54 | }
55 |
56 | @Override
57 | public void doAnalyse(String imgPath) {
58 | File file = new File(imgPath);
59 | if (!file.exists()) {
60 | Log.w(TAG, "Image Not Exists!");
61 | return;
62 | }
63 | postRequest(imgPath);
64 |
65 | }
66 |
67 | @Override
68 | public void pickPhoto(Activity activity, int type) {
69 | File outputImage;
70 | switch (type) {
71 | case TYPE_PICK_CAMERA:
72 | Intent takePicture = new Intent("android.media.action.IMAGE_CAPTURE");
73 | outputImage = new File(appBaseDir.getAbsolutePath() + File.separator + OUTPUT_IMAGE_JPG);
74 | if (!outputImage.exists()) try {
75 | outputImage.createNewFile();
76 | } catch (IOException e) {
77 | e.printStackTrace();
78 | }
79 | imageUri = Uri.fromFile(outputImage);
80 | //takePicture.putExtra("return-data", false);
81 | takePicture.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
82 | try {
83 | activity.startActivityForResult(takePicture, MainActivity.ACTIVITY_REQUEST_CAMERA);
84 | } catch (Exception e) {
85 | e.printStackTrace();
86 | iPhotoView.toast(activity.getResources().getString(R.string.main_pick_camera_fail));
87 | }
88 | break;
89 | case TYPE_PICK_GALLERY:
90 | Intent pickPhoto = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
91 | pickPhoto.putExtra("crop", "true");//允许裁剪
92 | outputImage = new File(appBaseDir.getAbsolutePath() + File.separator + OUTPUT_IMAGE_JPG);
93 | if (!outputImage.exists()) try {
94 | outputImage.createNewFile();
95 | } catch (IOException e) {
96 | e.printStackTrace();
97 | }
98 | imageUri = Uri.fromFile(outputImage);
99 | //takePicture.putExtra("return-data", false);
100 | pickPhoto.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
101 | try {
102 | activity.startActivityForResult(pickPhoto, MainActivity.ACTIVITY_REQUEST_GALLERY);
103 | } catch (Exception e) {
104 | e.printStackTrace();
105 | pickPhoto.putExtra("crop", false);//不允许裁剪
106 | try {
107 | activity.startActivityForResult(pickPhoto, MainActivity.ACTIVITY_REQUEST_GALLERY);
108 | } catch (Throwable t) {
109 | t.printStackTrace();
110 | iPhotoView.toast(activity.getResources().getString(R.string.main_pick_gallery_fail));
111 | }
112 | }
113 | break;
114 | default:
115 | break;
116 | }
117 | }
118 |
119 | @Override
120 | public void getImage(Context context, Intent intent) {
121 | try {
122 | Bitmap bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(imageUri));
123 | //为防止原始图片过大导致内存溢出,这里先缩小原图显示,然后释放原始Bitmap占用的内存
124 | int widthBitmap = bitmap.getWidth();
125 | int heightBitmap = bitmap.getHeight();
126 | int widthMax = AppUtil.getScreenWitdh(context) - (context.getResources().getDimensionPixelSize(R.dimen.margin_main_left) + context.getResources().getDimensionPixelSize(R.dimen.border_main_photo) + context.getResources().getDimensionPixelSize(R.dimen.offset_main_photo)) * 2;
127 | int heightMax = iPhotoView.getPhotoContainer().getHeight() - (context.getResources().getDimensionPixelSize(R.dimen.border_main_photo) + context.getResources().getDimensionPixelSize(R.dimen.offset_main_photo)) * 2;
128 | if (widthBitmap > widthMax && heightBitmap > heightMax) {
129 | float rateWidth = (float)widthBitmap/(float)widthMax;
130 | float rateHeight = (float)heightBitmap/(float)heightMax;
131 | if (rateWidth>=rateHeight)
132 | bitmap = BitmapUtil.zoomBitmapToWidth(bitmap, widthMax);
133 | else
134 | bitmap = BitmapUtil.zoomBitmapToHeight(bitmap, heightMax);
135 | }else if (widthBitmap > widthMax){
136 | bitmap = BitmapUtil.zoomBitmapToWidth(bitmap, widthMax);
137 | }else if(heightBitmap>heightMax){
138 | bitmap = BitmapUtil.zoomBitmapToHeight(bitmap, heightMax);
139 | }
140 | String imgPath = appBaseDir.getAbsolutePath() + File.separator + OUTPUT_IMAGE_SMALL_JPG;
141 | if (BitmapUtil.saveBitmapToSd(bitmap,80,imgPath))
142 | iPhotoView.onGetImage(bitmap, imgPath);
143 | } catch (Exception e) {
144 | iPhotoView.toast(context.getResources().getString(R.string.main_get_img_fail));
145 | e.printStackTrace();
146 | }
147 | }
148 |
149 | private void postRequest(String imagePath) {
150 | iPhotoView.showProgressDialog(true);
151 | try {
152 | if (asyncHttpClient==null)asyncHttpClient = new AsyncHttpClient();
153 | RequestParams params = new RequestParams();
154 | params.put("data", new File(imagePath)); // Upload a File
155 | //params.put("data", new Base64InputStream(new FileInputStream(imagePath),Base64.DEFAULT)); // Upload a File
156 | params.put("isTest", "False");
157 | Log.d(TAG, "do post ");
158 | asyncHttpClient.post("http://how-old.net/Home/Analyze?isTest=False", params, new AsyncHttpResponseHandler() {
159 | @Override
160 | public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
161 | Log.d(TAG, "onSuccess: statusCode = " + statusCode);
162 | try {
163 | String string = new String(responseBody, "UTF-8");
164 | String str1 = string.replaceAll("\\\\", "");
165 | String str2 = str1.replaceAll("rn", "");
166 | String json = str2.substring(str2.indexOf("\"Faces\":[") + 8, str2.lastIndexOf("]") + 1);
167 | Log.d(TAG, "onSuccess: json = " + json);
168 | parserJson(json);
169 | } catch (UnsupportedEncodingException e) {
170 | e.printStackTrace();
171 | }
172 | }
173 |
174 | @Override
175 | public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
176 | Log.d(TAG, "onFailure: statusCode = " + statusCode);
177 | parserJson(null);
178 | }
179 | });
180 |
181 | } catch (Exception e) {
182 | e.printStackTrace();
183 | parserJson(null);
184 | }
185 |
186 | //new PostHandler().execute(imagePath);
187 | }
188 |
189 | private void parserJson(String string) {
190 | if (string == null) {
191 | iPhotoView.onGetFaces(null);
192 | return;
193 | }
194 | List faceList = new ArrayList<>();
195 | try {
196 | JSONArray jsonArray = new JSONArray(string);
197 | if (jsonArray.length() <= 0) {
198 | Log.w(TAG, "No Face");
199 | }
200 | for (int i = 0; i < jsonArray.length(); i++) {
201 | JSONObject item = jsonArray.getJSONObject(i);
202 | Face face = new Face();
203 | face.faceId = item.optInt("faceId", 0);
204 | JSONObject faceRectangle = item.optJSONObject("faceRectangle");
205 | face.faceRectangle.left = faceRectangle.optInt("left", 0);
206 | face.faceRectangle.top = faceRectangle.optInt("top", 0);
207 | face.faceRectangle.width = faceRectangle.optInt("width", 65);
208 | face.faceRectangle.height = faceRectangle.optInt("height", 65);
209 | JSONObject attributes = item.optJSONObject("attributes");
210 | face.attributes.gender = attributes.optString("gender", "Female");
211 | face.attributes.age = attributes.optInt("age", 17);
212 | faceList.add(face);
213 | }
214 | } catch (Exception e) {
215 | e.printStackTrace();
216 | }
217 |
218 | /*Iterator iterator = faceList.iterator();
219 | while (iterator.hasNext()) {
220 | Face item = iterator.next();
221 | Log.d(TAG, "Face : " + item.toString());
222 | }*/
223 | iPhotoView.onGetFaces(faceList);
224 | }
225 |
226 |
227 |
228 | /*class PostHandler extends AsyncTask {
229 |
230 |
231 | @Override
232 | protected String doInBackground(String... params) {
233 | try {
234 | HttpClient httpclient = new DefaultHttpClient();
235 | HttpPost httppost = new HttpPost("http://how-old.net/Home/Analyze?isTest=False");
236 | // 一个本地的文件
237 | FileBody file = new FileBody(new File(params[0]));
238 | // 一个字符串
239 | StringBody comment = new StringBody("False");
240 | // 多部分的实体
241 | MultipartEntity reqEntity = new MultipartEntity();
242 | // 增加
243 | reqEntity.addPart("data", file);
244 | reqEntity.addPart("isTest", comment);
245 | // 设置
246 | httppost.setEntity(reqEntity);
247 |
248 | Log.d(TAG, "执行: " + httppost.getRequestLine());
249 |
250 | HttpResponse response = httpclient.execute(httppost);
251 | HttpEntity resEntity = response.getEntity();
252 | Header[] headers = response.getAllHeaders();
253 | for (Header header : headers) {
254 | System.out.println(header.getName() + " " + header.getValue());
255 | }
256 | System.out.println("----------------------------------------");
257 | System.out.println(response.getStatusLine());
258 | if (resEntity != null) {
259 | Log.d(TAG, "返回长度: " + resEntity.getContentLength());
260 | String result = EntityUtils.toString(resEntity, "utf-8");
261 | String str1 = result.replaceAll("\\\\", "");
262 | String str2 = str1.replaceAll("rn", "");
263 | String json = str2.substring(str2.indexOf("\"Faces\":[") + 8, str2.lastIndexOf("]") + 1);
264 | resEntity.consumeContent();
265 | Log.d(TAG, json);
266 | return json;
267 | }
268 | } catch (Exception e) {
269 | e.printStackTrace();
270 | }
271 | return null;
272 |
273 | }
274 |
275 | @Override
276 | protected void onPreExecute() {
277 | super.onPreExecute();
278 | iPhotoView.showProgressDialog(true);
279 | }
280 |
281 | @Override
282 | protected void onPostExecute(String s) {
283 | super.onPostExecute(s);
284 | parserJson(s);
285 | }
286 | }*/
287 | }
288 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/AnimationPresenterCompl.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import android.view.View;
4 | import android.view.animation.AlphaAnimation;
5 | import android.view.animation.AnimationSet;
6 | import android.view.animation.TranslateAnimation;
7 |
8 | /**
9 | * Created by Kaede on 2015/6/2.
10 | */
11 | public class AnimationPresenterCompl implements IAnimationPresenter {
12 | @Override
13 | public void doLogoAnimation(View view) {
14 | AnimationSet animationSet = new AnimationSet(false);
15 | AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
16 | alphaAnimation.setDuration(1000);
17 | alphaAnimation.setFillAfter(true);
18 | TranslateAnimation translateAnimation = new TranslateAnimation(0f,0f,100f,0f);
19 | translateAnimation.setDuration(1000);
20 | translateAnimation.setFillAfter(true);
21 | animationSet.addAnimation(alphaAnimation);
22 | animationSet.addAnimation(translateAnimation);
23 | view.startAnimation(animationSet);
24 | }
25 |
26 | @Override
27 | public void doIntroduceAnimation(View view) {
28 | AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
29 | alphaAnimation.setDuration(500);
30 | alphaAnimation.setStartOffset(500);
31 | alphaAnimation.setFillAfter(true);
32 | view.startAnimation(alphaAnimation);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/DrawPresenterCompl.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import android.app.Activity;
4 | import android.view.View;
5 |
6 | import me.kaede.howoldrobot.analyse.model.Face;
7 | import me.kaede.howoldrobot.analyse.view.IPhotoView;
8 | import me.kaede.howoldrobot.widget.FaceImageView;
9 | import me.kaede.howoldrobot.widget.AgeIndicatorLayout;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | /**
15 | * Created by kaede on 2015/5/24.
16 | */
17 | public class DrawPresenterCompl implements IDrawPresenter {
18 | Listviews;
19 | IPhotoView iPhotoView;
20 | /*private WindowManager windowManager;
21 | private WindowManager.LayoutParams params;*/
22 |
23 | public DrawPresenterCompl(Activity activity,IPhotoView iPhotoView) {
24 | this.iPhotoView = iPhotoView;
25 | views = new ArrayList<>();
26 |
27 | /*windowManager = activity.getWindowManager();
28 | params = new WindowManager.LayoutParams(
29 | WindowManager.LayoutParams.WRAP_CONTENT,
30 | WindowManager.LayoutParams.WRAP_CONTENT,
31 | WindowManager.LayoutParams.LAST_APPLICATION_WINDOW,
32 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
33 | PixelFormat.TRANSLUCENT);
34 | params.gravity = Gravity.TOP | Gravity.START;*/
35 |
36 | }
37 |
38 |
39 | @Override
40 | public void drawFaces(AgeIndicatorLayout ageIndicatorLayout, FaceImageView faceImageView, List faces) {
41 | faceImageView.drawFaces(faces);
42 | ageIndicatorLayout.drawAges(faces, (ageIndicatorLayout.getMeasuredWidth()-faceImageView.getMeasuredWidth())/2, (ageIndicatorLayout.getMeasuredHeight()-faceImageView.getMeasuredHeight())/2);
43 |
44 |
45 | //使用WindowManager显示AgeIndicator
46 | /*View photoContainer = activity.findViewById(R.id.layout_main_photo);
47 | *//* 获取状态栏高度
48 | Rect frame = new Rect();
49 | activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
50 | int statusBarHeight = frame.top;*//*
51 | int x_center = photoContainer.getMeasuredWidth()/2;
52 | int y_center = photoContainer.getMeasuredHeight()/2;
53 | int x = x_center - faceImageView.getMeasuredWidth()/2 + activity.getResources().getDimensionPixelSize(R.dimen.margin_main_left);
54 | int y = y_center - faceImageView.getMeasuredHeight()/2+ activity.getResources().getDimensionPixelSize(R.dimen.margin_main_top) + activity.getResources().getDimensionPixelSize(R.dimen.common_actionbar_height);
55 |
56 |
57 | Iterator iterator = faces.iterator();
58 | while (iterator.hasNext()){
59 | Face item = iterator.next();
60 | params.x = x+item.faceRectangle.left - (activity.getResources().getDimensionPixelSize(R.dimen.indicator_width) - item.faceRectangle.width)/2;
61 | params.y = y+item.faceRectangle.top - activity.getResources().getDimensionPixelSize(R.dimen.indicator_height);
62 | View ageIndicateView = LayoutInflater.from(activity.getApplicationContext()).inflate(
63 | R.layout.item_age_indicator, null);
64 | if (ageIndicateView!=null){
65 | TextView tvAge = (TextView) ageIndicateView.findViewById(R.id.tv_ageindicator_age);
66 | tvAge.setText(String.valueOf(item.attributes.age));
67 | ImageView ivGender = (ImageView) ageIndicateView.findViewById(R.id.iv_ageindicator_gender);
68 | if (item.attributes.gender.equalsIgnoreCase("Male")){
69 | ivGender.setImageResource(R.drawable.icon_gende_male);
70 | }else if(item.attributes.gender.equalsIgnoreCase("Female")){
71 | ivGender.setImageResource(R.drawable.icon_gender_female);
72 | }
73 | views.add(ageIndicateView);
74 | windowManager.addView(ageIndicateView, params);
75 | }
76 | }*/
77 | }
78 |
79 | @Override
80 | public void clearViews() {
81 | /*Iterator iterator = views.iterator();
82 | while (iterator.hasNext()){
83 | View view = iterator.next();
84 | windowManager.removeViewImmediate(view);
85 | }
86 | views.clear();*/
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/IAnalysePresenter.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | /**
8 | * Created by kaede on 2015/5/23.
9 | */
10 | public interface IAnalysePresenter {
11 | public void doAnalyse(String imgPath);
12 | public void pickPhoto(Activity activity,int type);
13 | public void getImage(Context context,Intent intent);
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/IAnimationPresenter.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Created by Kaede on 2015/6/2.
7 | */
8 | public interface IAnimationPresenter {
9 |
10 | public void doLogoAnimation(View view);
11 | public void doIntroduceAnimation(View view);
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/IDrawPresenter.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import java.util.List;
4 |
5 | import me.kaede.howoldrobot.analyse.model.Face;
6 | import me.kaede.howoldrobot.widget.AgeIndicatorLayout;
7 | import me.kaede.howoldrobot.widget.FaceImageView;
8 |
9 | /**
10 | * Created by kaede on 2015/5/24.
11 | */
12 | public interface IDrawPresenter {
13 | public void drawFaces(AgeIndicatorLayout ageIndicatorLayout, FaceImageView faceImageView,List faces);
14 | public void clearViews();
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/IOptionsPresenter.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by kaede on 2015/5/26.
7 | */
8 | public interface IOptionsPresenter {
9 | public void onOptionsItemClick(Context context,int id);
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/ISharePresenter.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | /**
7 | * Created by kaede on 2015/5/25.
8 | */
9 | public interface ISharePresenter {
10 | public void doShare(Context context, View view);
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/OptionsPresenterCompl.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 |
7 | import me.kaede.howoldrobot.R;
8 | import me.kaede.howoldrobot.util.AppUtil;
9 | import me.kaede.howoldrobot.util.NavigationUtil;
10 |
11 | /**
12 | * Created by kaede on 2015/5/26.
13 | */
14 | public class OptionsPresenterCompl implements IOptionsPresenter {
15 | @Override
16 | public void onOptionsItemClick(Context context, int id) {
17 | switch(id) {
18 | case R.id.action_star:
19 | NavigationUtil.naviToMarket(context, AppUtil.getpackageName(context));
20 | break;
21 | case R.id.action_web:
22 | Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://how-old.net"));
23 | context.startActivity(browserIntent);
24 | //NavigationUtil.toWebViewActivity(context,"http://how-old.net/","Online");
25 | break;
26 | default:
27 | break;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/presenter/SharePresenterCompl.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.presenter;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.graphics.Bitmap;
6 | import android.net.Uri;
7 | import android.provider.MediaStore;
8 | import android.view.View;
9 |
10 | import java.io.ByteArrayOutputStream;
11 | import java.io.File;
12 |
13 | import me.kaede.howoldrobot.R;
14 | import me.kaede.howoldrobot.analyse.view.IPhotoView;
15 | import me.kaede.howoldrobot.util.BitmapUtil;
16 | import me.kaede.howoldrobot.util.FileUtil;
17 |
18 | /**
19 | * Created by kaede on 2015/5/25.
20 | */
21 | public class SharePresenterCompl implements ISharePresenter {
22 | IPhotoView iPhotoView;
23 | File appBaseDir;
24 |
25 | public SharePresenterCompl(IPhotoView iPhotoView) {
26 | this.iPhotoView = iPhotoView;
27 | File dir = new File(FileUtil.getSdpath() + File.separator + "Moe Studio");
28 | dir.mkdir();
29 | appBaseDir = new File(dir.getAbsolutePath() + File.separator + "How Old Robot");
30 | appBaseDir.mkdir();
31 | }
32 |
33 | @Override
34 | public void doShare(Context context, View view) {
35 | Bitmap b = BitmapUtil.getViewBitmap(view);
36 | if (b!=null){
37 | File temp = FileUtil.getTempFile(appBaseDir.getAbsolutePath(),".jpg");
38 | if (temp != null) {
39 | BitmapUtil.saveBitmapToSd(b,80,temp.getAbsolutePath());
40 | }
41 | Intent share = new Intent(Intent.ACTION_SEND);
42 | share.setType("image/jpeg");
43 | ByteArrayOutputStream bytes = new ByteArrayOutputStream();
44 | b.compress(Bitmap.CompressFormat.JPEG, 80, bytes);
45 | String path = MediaStore.Images.Media.insertImage(context.getContentResolver(),b, "Share Image", "How Old Camera's Share Image");
46 | Uri imageUri = Uri.parse(path);
47 | share.putExtra(Intent.EXTRA_STREAM, imageUri);
48 | try {
49 | context.startActivity(Intent.createChooser(share, context.getResources().getString(R.string.share_select_title)));
50 | } catch (Exception e) {
51 | iPhotoView.toast(context.getResources().getString(R.string.share_fail));
52 | e.printStackTrace();
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/analyse/view/IPhotoView.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.analyse.view;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | import java.util.List;
6 |
7 | import android.view.View;
8 | import me.kaede.howoldrobot.analyse.model.Face;
9 |
10 | /**
11 | * Created by kaede on 2015/5/23.
12 | */
13 | public interface IPhotoView {
14 | public void onGetFaces(List faces);
15 | public void onGetImage(Bitmap bitmap,String imgPath);
16 | public void showProgressDialog(Boolean isShow);
17 | public void toast(String msg);
18 | public View getPhotoContainer();
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/util/AppUtil.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.util;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageInfo;
5 | import android.content.pm.PackageManager;
6 | import android.util.DisplayMetrics;
7 |
8 | /**
9 | * Created by kaede on 2015/5/24.
10 | */
11 | public class AppUtil {
12 | public static int getScreenWitdh(Context context){
13 | DisplayMetrics dm = new DisplayMetrics();
14 | dm = context.getResources().getDisplayMetrics();
15 | return dm.widthPixels;
16 | }
17 |
18 | public static int getScreenHeight(Context context){
19 | DisplayMetrics dm = new DisplayMetrics();
20 | dm = context.getResources().getDisplayMetrics();
21 | return dm.heightPixels;
22 | }
23 |
24 | public static String getpackageName(Context context) {
25 | // 获取packagemanager的实例
26 | PackageManager packageManager = context.getPackageManager();
27 | // getPackageName()是你当前类的包名,0代表是获取版本信息
28 | PackageInfo packInfo = null;
29 | try {
30 | packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
31 | } catch (PackageManager.NameNotFoundException e) {
32 | e.printStackTrace();
33 | }
34 | String pack = packInfo.packageName;
35 | return pack;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/util/BitmapUtil.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.util;
2 |
3 | import android.content.Context;
4 | import android.graphics.*;
5 | import android.graphics.drawable.Drawable;
6 | import android.util.DisplayMetrics;
7 | import android.util.Log;
8 | import android.view.Display;
9 | import android.view.View;
10 | import android.view.WindowManager;
11 |
12 | import java.io.*;
13 |
14 | /**
15 | * Created by kaede on 2015/5/24.
16 | */
17 | public class BitmapUtil {
18 |
19 | private static final String TAG = "BitmapUtil";
20 |
21 | public static Bitmap zoomBitmapToWidth(Bitmap bitmap, int width) {
22 | Log.e(TAG,"[kaede][zoomBitmapToWidth] width="+width);
23 | Matrix matrix = new Matrix();
24 | matrix.postScale((float) width / bitmap.getWidth(), (float) width / bitmap.getWidth());
25 | return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
26 |
27 | }
28 |
29 | public static Bitmap zoomBitmapToHeight(Bitmap bitmap, int height) {
30 | Log.e(TAG,"[kaede][zoomBitmapToHeight] height="+height);
31 | Matrix matrix = new Matrix();
32 | matrix.postScale((float) height / bitmap.getHeight(), (float) height / bitmap.getHeight());
33 | return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
34 |
35 | }
36 |
37 | public static Boolean saveBitmapToSd(Bitmap bitmap,int quality,String path) {
38 | File imagePath = new File(path);
39 | if (!imagePath.exists()) try {
40 | imagePath.createNewFile();
41 | } catch (IOException e) {
42 | Log.e(TAG,"[kaede] Create file fail!");
43 | e.printStackTrace();
44 | return false;
45 | }
46 | if (imagePath.delete()){
47 | FileOutputStream fos;
48 | try {
49 | fos = new FileOutputStream(imagePath);
50 | bitmap.compress(Bitmap.CompressFormat.JPEG, quality, fos);
51 | fos.flush();
52 | fos.close();
53 | return true;
54 | } catch (Exception e) {
55 | Log.e(TAG, e.getMessage(), e);
56 | return false;
57 | }
58 | }else {
59 | Log.e(TAG,"[kaede] Image had exist and can not be deleted!");
60 | return false;
61 | }
62 |
63 | }
64 |
65 | public static Bitmap getViewBitmap(View view){
66 | View rootView = view.getRootView();
67 | view.invalidate();
68 | rootView.setDrawingCacheEnabled(true);
69 | return rootView.getDrawingCache();
70 | }
71 |
72 | public static Bitmap getBitmapFromView(View v,Boolean isUseDrawingCache) {
73 | if (v.getMeasuredHeight()<=0||v.getMeasuredWidth()<=0){
74 | // Either this
75 | //int specWidth = View.MeasureSpec.makeMeasureSpec(parentWidth, View.MeasureSpec.AT_MOST);// Or this
76 | int specWidth = View.MeasureSpec.makeMeasureSpec(0 /* any */, View.MeasureSpec.UNSPECIFIED);
77 | int specHeight = View.MeasureSpec.makeMeasureSpec(0 /* any */, View.MeasureSpec.UNSPECIFIED);
78 | v.measure(specWidth, specHeight);
79 | int questionWidth = v.getMeasuredWidth();
80 | int questionHeight = v.getMeasuredHeight();
81 | Log.d(TAG, "[kaede][getBitmapFromView] questionWidth = " + questionWidth + " questionHeight=" + questionHeight);
82 | v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
83 | }
84 | return getBitmapFromVisiableView(v, isUseDrawingCache);
85 | }
86 |
87 | private static Bitmap getBitmapFromVisiableView(View view,Boolean isUseDrawingCache){
88 | if (isUseDrawingCache){
89 | View rootView = view.getRootView();
90 | view.invalidate();
91 | rootView.setDrawingCacheEnabled(true);
92 | return rootView.getDrawingCache();
93 | }
94 | Bitmap b = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
95 | Canvas c = new Canvas(b);
96 | Drawable bgDrawable =view.getBackground();
97 | if (bgDrawable!=null)
98 | bgDrawable.draw(c);
99 | //else c.drawColor(Color.TRANSPARENT);
100 | view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
101 | view.draw(c);
102 | return b;
103 |
104 | }
105 |
106 | public static Bitmap getScreenshot(Context context){
107 | FileInputStream graphics = null;
108 | try {
109 | graphics = new FileInputStream("/dev/graphics/fb0");
110 | } catch (FileNotFoundException e) {
111 | e.printStackTrace();
112 | return null;
113 | }
114 |
115 | DisplayMetrics dm = new DisplayMetrics();
116 | Display display =((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
117 | display.getMetrics(dm);
118 | int screenWidth = dm.widthPixels; // 屏幕宽(像素,如:480px)
119 | int screenHeight = dm.heightPixels; // 屏幕高(像素,如:800p)
120 |
121 | PixelFormat pixelFormat = new PixelFormat();
122 | PixelFormat.getPixelFormatInfo(PixelFormat.RGBA_8888, pixelFormat);
123 | int deepth = pixelFormat.bytesPerPixel; // 位深
124 | byte[] piex = new byte[screenHeight * screenWidth * deepth]; // 像素
125 |
126 | try {
127 | DataInputStream dStream = new DataInputStream(graphics);
128 | dStream.readFully(piex);
129 | dStream.close();
130 |
131 | int[] colors = new int[screenHeight * screenWidth];
132 | // 将rgb转为色值
133 | for (int m = 0; m < colors.length; m++) {
134 | int r = (piex[m * 4] & 0xFF);
135 | int g = (piex[m * 4 + 1] & 0xFF);
136 | int b = (piex[m * 4 + 2] & 0xFF);
137 | int a = (piex[m * 4 + 3] & 0xFF);
138 | colors[m] = (a << 24) + (r << 16) + (g << 8) + b;
139 | }
140 |
141 | return Bitmap.createBitmap(colors, screenWidth, screenHeight,
142 | Bitmap.Config.ARGB_8888);
143 | } catch (IOException e) {
144 | e.printStackTrace();
145 | return null;
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/util/FileUtil.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.util;
2 |
3 | import android.os.Environment;
4 | import android.util.Log;
5 |
6 | import java.io.File;
7 | import java.io.IOException;
8 |
9 | /**
10 | * Created by Kaede on 2015/5/25.
11 | */
12 | public class FileUtil {
13 |
14 | private static final String TAG = "FileUtil";
15 |
16 | public static String getSdpath(){
17 | return Environment.getExternalStorageDirectory().getAbsolutePath();
18 | }
19 |
20 | public static File getTempFile(String dir, String fieExtension) {
21 | String filePath = dir + File.separator + String.valueOf(System.currentTimeMillis()) + fieExtension;
22 | File file = new File(filePath);
23 | if (!file.exists()){
24 | try {
25 | file.createNewFile();
26 | } catch (IOException e) {
27 | Log.e(TAG,e.getMessage(),e );
28 | return null;
29 | }
30 | }
31 | return file;
32 |
33 | }
34 |
35 | public static Boolean makeFile(String[] dirs) throws IOException {
36 | String path = getSdpath();
37 | for (int i = 1; i <= dirs.length; i++) {
38 | if (i != dirs.length) {
39 | path = path + File.separator + dirs[i - 1];
40 | File dir = new File(path);
41 | if (!dir.exists())
42 | dir.mkdir();
43 | } else {
44 | path = path + File.separator + dirs[i - 1];
45 | File file = new File(path);
46 | if (!file.exists())
47 | file.createNewFile();
48 | }
49 | }
50 | return true;
51 | }
52 |
53 | public static File makeSdFile(String[] dirs) {
54 | String path = getSdpath();
55 | try {
56 | for (int i = 1; i <= dirs.length; i++) {
57 | if (i != dirs.length) {
58 | path = path + File.separator + dirs[i - 1];
59 | File dir = new File(path);
60 | if (!dir.exists())
61 | dir.mkdir();
62 | } else {
63 | path = path + File.separator + dirs[i - 1];
64 | File file = new File(path);
65 | if (!file.exists())
66 | file.createNewFile();
67 | return file;
68 | }
69 | }
70 | } catch (Exception e) {
71 | Log.e(TAG, e.getMessage(), e);
72 | }
73 |
74 | return null;
75 | }
76 |
77 |
78 |
79 | public static String UriToFileName(String url, String replace) {
80 | return url.replaceAll("[/:\\\\|?*<>\"]", replace);
81 |
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/util/NavigationUtil.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.util;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.widget.Toast;
7 |
8 | /**
9 | * Created by kaede on 2015/5/27.
10 | */
11 | public class NavigationUtil {
12 | public static void naviToMarket(Context context, String packageName) {
13 | Uri uri = Uri.parse("market://details?id=" + packageName);
14 | Intent it = new Intent(Intent.ACTION_VIEW, uri);
15 | try {
16 | context.startActivity(it);
17 | } catch (Exception e) {
18 | e.printStackTrace();
19 | Toast.makeText(context, "找不到安卓市场", Toast.LENGTH_LONG).show();;
20 | }
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/widget/AgeIndicatorLayout.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.util.AttributeSet;
9 | import android.util.Log;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.widget.ImageView;
13 | import android.widget.LinearLayout;
14 | import android.widget.TextView;
15 | import me.kaede.howoldrobot.R;
16 | import me.kaede.howoldrobot.analyse.model.Face;
17 | import me.kaede.howoldrobot.util.BitmapUtil;
18 |
19 | import java.util.Iterator;
20 | import java.util.List;
21 |
22 | /**
23 | * Created by kaede on 2015/5/23.
24 | */
25 | public class AgeIndicatorLayout extends LinearLayout {
26 | private static final String TAG = "AgeIndicatorLayout";
27 | Boolean isDrawFace = false;
28 | List faces;
29 | Paint paint;
30 | private int xOffset;
31 | private int yOffset;
32 |
33 | private void init(){
34 | this.isDrawFace = false;
35 | paint = new Paint();
36 | paint.setStyle(Paint.Style.STROKE);
37 | paint.setColor(Color.WHITE);
38 | }
39 | public AgeIndicatorLayout(Context context) {
40 | super(context);
41 | init();
42 | }
43 |
44 | public AgeIndicatorLayout(Context context, AttributeSet attrs) {
45 | super(context, attrs);
46 | init();
47 | }
48 |
49 | @Override
50 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
51 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
52 | init();
53 | }
54 |
55 | @Override
56 | protected void onDraw(Canvas canvas) {
57 | super.onDraw(canvas);
58 | if (isDrawFace&&faces!=null){
59 | Iterator iterator = faces.iterator();
60 | while (iterator.hasNext()){
61 | Face item = iterator.next();
62 | //draw age indicator
63 | View ageIndicateView = LayoutInflater.from(getContext().getApplicationContext()).inflate(R.layout.item_age_indicator, null);
64 | if (ageIndicateView!=null){
65 | TextView tvAge = (TextView) ageIndicateView.findViewById(R.id.tv_ageindicator_age);
66 | tvAge.setText(String.valueOf(item.attributes.age));
67 | ImageView ivGender = (ImageView) ageIndicateView.findViewById(R.id.iv_ageindicator_gender);
68 | if (item.attributes.gender.equalsIgnoreCase("Male")){
69 | ivGender.setImageResource(R.drawable.icon_gende_male);
70 | }else if(item.attributes.gender.equalsIgnoreCase("Female")){
71 | ivGender.setImageResource(R.drawable.icon_gender_female);
72 | }
73 | Bitmap bitmap = BitmapUtil.getBitmapFromView(ageIndicateView,true);
74 | if (bitmap != null) {
75 | //BitmapUtil.saveBitmapToSd(bitmap, 100, Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp.jpg");
76 | canvas.drawBitmap(bitmap,item.faceRectangle.left+xOffset - (ageIndicateView.getMeasuredWidth() - item.faceRectangle.width)/2,item.faceRectangle.top+yOffset-bitmap.getHeight(),paint);
77 | }
78 | Log.i(TAG, "ageIndicateView getMeasuredHeight()= " + ageIndicateView.getMeasuredHeight() + " getHeight=" + ageIndicateView.getHeight());
79 |
80 | }
81 | }
82 |
83 | }
84 | }
85 |
86 |
87 | public void drawAges( List faces,int xOffset,int yOffset){
88 | this.faces = faces;
89 | this.isDrawFace = true;
90 | this.xOffset = xOffset;
91 | this.yOffset = yOffset;
92 | invalidate();
93 | }
94 |
95 | public void clearAges(){
96 | this.faces = null;
97 | this.isDrawFace = false;
98 | invalidate();
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/app/src/main/java/me/kaede/howoldrobot/widget/FaceImageView.java:
--------------------------------------------------------------------------------
1 | package me.kaede.howoldrobot.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.util.AttributeSet;
8 | import android.widget.ImageView;
9 |
10 | import java.util.Iterator;
11 | import java.util.List;
12 |
13 | import me.kaede.howoldrobot.analyse.model.Face;
14 |
15 | /**
16 | * Created by kaede on 2015/5/23.
17 | */
18 | public class FaceImageView extends ImageView{
19 | private static final String TAG = "FaceImageView";
20 | Boolean isDrawFace = false;
21 | List faces;
22 | private int width;
23 | private int height;
24 | private Paint paint;
25 |
26 | public FaceImageView(Context context) {
27 | super(context);
28 | init();
29 | }
30 |
31 | public FaceImageView(Context context, AttributeSet attrs) {
32 | super(context, attrs);
33 | init();
34 | }
35 |
36 | public FaceImageView(Context context, AttributeSet attrs, int defStyleAttr) {
37 | super(context, attrs, defStyleAttr);
38 | init();
39 | }
40 |
41 | private void init(){
42 | this.isDrawFace = false;
43 | paint = new Paint();
44 | paint.setStyle(Paint.Style.STROKE);
45 | paint.setColor(Color.WHITE);
46 | }
47 |
48 | @Override
49 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
50 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
51 | width = getMeasuredWidth();
52 | height = getMeasuredHeight();
53 | }
54 |
55 | @Override
56 | protected void onDraw(Canvas canvas) {
57 | super.onDraw(canvas);
58 | if (isDrawFace&&faces!=null){
59 | Iterator iterator = faces.iterator();
60 | while (iterator.hasNext()){
61 | Face item = iterator.next();
62 | //draw rect
63 | canvas.drawRect(item.faceRectangle.left,item.faceRectangle.top,item.faceRectangle.left+item.faceRectangle.width,item.faceRectangle.top+item.faceRectangle.height, paint);
64 | }
65 |
66 | }
67 | }
68 |
69 | public void drawFaces( List faces){
70 | this.faces = faces;
71 | this.isDrawFace = true;
72 | invalidate();
73 | }
74 |
75 | public void clearFaces(){
76 | this.faces = null;
77 | this.isDrawFace = false;
78 | invalidate();
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_button_round.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xhdpi/bg_button_round.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_how_old_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xhdpi/icon_how_old_02.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/bg_indicator.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xxhdpi/bg_indicator.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/cardui_round_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xxhdpi/cardui_round_bg.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xxhdpi/icon_camera.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_gallery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xxhdpi/icon_gallery.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_gende_male.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xxhdpi/icon_gende_male.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_gender_female.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xxhdpi/icon_gender_female.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xxhdpi/icon_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xxhdpi/icon_search.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/app/src/main/res/drawable-xxhdpi/icon_share.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_bg_button_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_browser.xml:
--------------------------------------------------------------------------------
1 |
5 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
8 |
14 |
20 |
21 |
24 |
36 |
41 |
46 |
47 |
48 |
49 |
60 |
66 |
72 |
78 |
87 |
96 |
105 |
106 |
107 |
108 |
119 |
128 |
130 |
136 |
137 |
147 |
149 |
155 |
156 |
157 |
166 |
168 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_browser.xml:
--------------------------------------------------------------------------------
1 |
5 |
9 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_age_indicator.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
16 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_browser.xml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
20 |
21 |
22 |
23 |
27 |
28 |
31 |
32 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 年龄相机
3 | 年龄相机
4 |
5 | 分析中…
6 | 无法打开相机
7 | 无法打开图库
8 | 获取图片失败
9 | 图片分析失败
10 | 没有找到脸蛋哦
11 | 相机
12 | 图库
13 | 分享
14 | ① 从相机或者图库获取一张图片
15 | ② 会自动分析图片中脸蛋的性别年龄
16 | ③ 别忘了跟小伙伴们分享图片分析的结果
17 |
18 | 5星好评
19 | 搜索脸蛋
20 | 反馈
21 |
22 | 没有找到分享APP
23 | 选择APP
24 |
25 | Hello world!
26 | Settings
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/values/color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF9800
4 | #FFCC80
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 5dp
6 | 5dp
7 | 3dp
8 | 10dp
9 | 49dp
10 | 40dp
11 | 70dp
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | How Old You Look
3 | HOW OLD
4 |
5 | Analysing…
6 | Open camera fail
7 | Pick photo fail
8 | Get image fail
9 | Analyze fail
10 | Find no face
11 | CAMERA
12 | GALLERY
13 | SHARE
14 | ① pick a photo from camera or gallery
15 | ② wait for analyse to get age and gender
16 | ③ don\'t forget to share with your peers
17 |
18 | Five Star
19 | Search Face
20 | Feedback
21 |
22 | Can\'t find Share APP
23 | Select APP
24 |
25 | Hello world!
26 | Settings
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
17 |
18 |
19 |
25 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.1.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaedea/how-old-camera/f032a272d9482c9a0edc02d3c603819fa60d5275/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | ###Demo Apk
2 | [Google Play](https://play.google.com/store/apps/details?id=me.kaede.howoldrobot)
3 |
4 | ###Description
5 | An android application for Microsoft how-old.net, as Example usage for Android `MVP` design pattern and `android-async-http`
6 |
7 | ###ScreenShot
8 | 
9 |
10 | 
11 |
12 | 
13 |
14 | 
15 |
16 | 
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------