Android Photo App

minio_ANDROID1

本示例将会指导你如何构建一个简单的Android Photo app。在这个app中,你将会学习一个Android client是如何访问Photo API Service并随机加载一张图片。你可以通过这里获取完整的代码,代码是以Apache 2.0 License发布的。

1. 依赖

我们将使用Android Studio进行开发。这个app也会访问我们发布的Photo API Service来随机获取一张图片的presigned url。

  • Android Studio
  • JDK 1.8

    2. 设置

  • 步骤1 - 启动Android Studio -> New Project -> Create a new Android Project。将你的工程命名为AndroidPhotoApp。
    minio_ANDROID2

  • 步骤2 - 选择Phone & Tablet。在本示例中,我们选择Marshmallow Android 6.0 SDK来编译和构建这个app。
    minio_ANDROID3

  • 步骤3 - 选择一个Blank或者Basic Activity模板,然后点击Next。
    minio_ANDROID4

  • 步骤4 - 不用修改Activity Name和Layout Name,直接点击Finish。
    minio_ANDROID5

  • 步骤5 - 你应该可以看见gradle进行build并创建了一个工程,现在我们可以开始敲代码了。
    minio_ANDROID6

3. App Layout

删除初始的Hello World TextView。

  • 拖拽一个Button widget到content_main.xml。
  • 从Layouts(在palette下面)里拖拽一个FrameLayout。
  • 然后从widgets中拖拽一个imageView到刚才的FrameLayout中。
    minio_ANDROID7

下面就是content_main.xml的完整xml。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. app:layout_behavior="@string/appbar_scrolling_view_behavior"
  8. tools:context="examples.minio.com.androidphotoapp.MainActivity"
  9. tools:showIn="@layout/activity_main">
  10. <Button
  11. android:id="@+id/button"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:text="Button"
  15. tools:layout_constraintTop_creator="1"
  16. tools:layout_constraintRight_creator="1"
  17. app:layout_constraintRight_toRightOf="parent"
  18. android:layout_marginTop="16dp"
  19. tools:layout_constraintLeft_creator="1"
  20. app:layout_constraintLeft_toLeftOf="parent"
  21. app:layout_constraintTop_toTopOf="parent" />
  22. <FrameLayout
  23. android:layout_width="0dp"
  24. android:layout_height="308dp"
  25. tools:layout_constraintTop_creator="1"
  26. tools:layout_constraintRight_creator="1"
  27. android:layout_marginStart="36dp"
  28. android:layout_marginEnd="36dp"
  29. app:layout_constraintRight_toRightOf="parent"
  30. app:layout_constraintTop_toBottomOf="@+id/button"
  31. tools:layout_constraintLeft_creator="1"
  32. app:layout_constraintLeft_toLeftOf="parent">
  33. <ImageView
  34. android:id="@+id/imageView"
  35. android:layout_width="wrap_content"
  36. android:layout_height="wrap_content"
  37. app:srcCompat="@android:color/background_light" />
  38. </FrameLayout>
  39. </android.support.constraint.ConstraintLayout>

4. MainActivity.java

我们将会用到之前构建的Phtoto API Service来给我们的AndroidPhotoApp提供服务。为了简单起见,我们没有用到ListView或者是GridView来显示图片列表,我们只是从PhotoAPI Service返回的多个presigned URL中随机选一个进行加载。

  1. package examples.minio.com.androidphotoapp;
  2. import android.app.ProgressDialog;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.os.AsyncTask;
  6. import android.os.Bundle;
  7. import android.support.design.widget.FloatingActionButton;
  8. import android.support.v7.app.AppCompatActivity;
  9. import android.support.v7.widget.Toolbar;
  10. import android.view.Menu;
  11. import android.view.MenuItem;
  12. import android.view.View;
  13. import android.widget.Button;
  14. import android.widget.ImageView;
  15. import android.widget.Toast;
  16. import org.json.JSONArray;
  17. import org.json.JSONObject;
  18. import java.io.BufferedReader;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.InputStreamReader;
  22. import java.net.HttpURLConnection;
  23. import java.net.URL;
  24. import java.util.Random;
  25. public class MainActivity extends AppCompatActivity {
  26. Button refreshButton;
  27. ProgressDialog pDialog;
  28. private static final String PHOTOSERVICE_URL = "http://play.minio.io:8080/PhotoAPIService-0.0.1-SNAPSHOT/minio/photoservice/list";
  29. ImageView imageView;
  30. @Override
  31. protected void onCreate(Bundle savedInstanceState) {
  32. super.onCreate(savedInstanceState);
  33. setContentView(R.layout.activity_main);
  34. Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
  35. setSupportActionBar(toolbar);
  36. //For the sake of simplicity we use an array of images. We recommend using ListViews or GridViews in your real applications.
  37. imageView = (ImageView) findViewById(R.id.imageView);
  38. refreshButton = (Button) findViewById(R.id.button);
  39. FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
  40. refreshButton.setOnClickListener(new View.OnClickListener() {
  41. @Override
  42. public void onClick(View view) {
  43. // An async task fetches all the latest photo URLs from the PhotoAPIService.
  44. new LoadImage().execute(PHOTOSERVICE_URL);
  45. }
  46. });
  47. }

我们会用一个AsyncTask在后台线程中来获取并处理这些url,而不是在UI线程中,这也是Android开发的惯用方式。

  1. private class LoadImage extends AsyncTask<String, String, Bitmap> {
  2. @Override
  3. protected void onPreExecute() {
  4. super.onPreExecute();
  5. pDialog = new ProgressDialog(MainActivity.this);
  6. pDialog.setMessage("Fetching Image from Minio Server....");
  7. pDialog.show();
  8. }
  9. protected Bitmap doInBackground(String... args) {
  10. InputStream inputStream = null;
  11. String result = "";
  12. try {
  13. URL url = new URL(args[0]);
  14. HttpURLConnection httpCon =
  15. (HttpURLConnection) url.openConnection();
  16. if (httpCon.getResponseCode() != 200)
  17. throw new Exception("Failed to connect");
  18. // Fetch the content as an inputStream.
  19. inputStream = httpCon.getInputStream();
  20. // Convert the fetched inputstream to string.
  21. if (inputStream != null)
  22. result = convertInputStreamToString(inputStream);
  23. else
  24. result = "Did not work!";
  25. if (result != null) System.out.println(result);
  26. // convert String to JSONObject.
  27. JSONObject json = new JSONObject(result);
  28. // get the array of photos.
  29. JSONArray imageJSON = json.getJSONArray("Album");
  30. int index = imageJSON.length()-1;
  31. Random rand = new Random();
  32. // Let's get a randomly pic a picture to load.
  33. int rindex = rand.nextInt((index - 0) + 1) + 0;
  34. // Return the image.
  35. return BitmapFactory.decodeStream(new URL(imageJSON.getJSONObject(rindex).getString("url")).openStream());
  36. } catch (Exception e) {
  37. System.out.println(e.getMessage());
  38. }
  39. return null;
  40. }
  41. protected void onPostExecute(Bitmap image) {
  42. System.out.println("In Post Execute");
  43. if (image != null) {
  44. pDialog.dismiss();
  45. // Place the image on the ImageView.
  46. imageView.setImageBitmap(image);
  47. } else
  48. {
  49. pDialog.dismiss();
  50. Toast.makeText(MainActivity.this, "Image Does Not exist or Network Error", Toast.LENGTH_SHORT).show();
  51. }
  52. }
  53. }

我们用到一个简单的工具方法将InputStream转成String。

  1. private static String convertInputStreamToString(InputStream inputStream) throws IOException{
  2. BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
  3. String line = "";
  4. String result = "";
  5. // Loop through the stream line by line and convert to a String.
  6. while((line = bufferedReader.readLine()) != null)
  7. result += line;
  8. inputStream.close();
  9. return result;
  10. }

5. AndroidManifest.xml

我们需要在AndroidManifest.xml中加上<uses-permission android:name="android.permission.INTERNET" />,这样app才可以通过网络获取图片。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="examples.minio.com.androidphotoapp">
  4. <application
  5. android:allowBackup="true"
  6. android:icon="@mipmap/ic_launcher"
  7. android:label="@string/app_name"
  8. android:roundIcon="@mipmap/ic_launcher_round"
  9. android:supportsRtl="true"
  10. android:theme="@style/AppTheme">
  11. <activity
  12. android:name=".MainActivity"
  13. android:label="@string/app_name"
  14. android:theme="@style/AppTheme.NoActionBar">
  15. <intent-filter>
  16. <action android:name="android.intent.action.MAIN" />
  17. <category android:name="android.intent.category.LAUNCHER" />
  18. </intent-filter>
  19. </activity>
  20. </application>
  21. <uses-permission android:name="android.permission.INTERNET" />
  22. </manifest>

6. 运行App

  • 启动一个Android模拟器或者连接一个Android设备到你的电脑。
  • 请确认你的模拟器/设备的Android版本是6.0+。
  • 点击这个绿色的play按钮部署并运行你的app。
  • 点击Load Random Image Button随机加载一张图片。
    minio_ANDROID8

7. 了解更多

原文: https://docs.minio.io/cn/android-photo-app.html