PhotoSharing Part III: PhotoSharing with OSS Image Processing

本文涉及的产品
对象存储 OSS,标准 - 本地冗余存储 20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000 次 1年
简介: We will build a photo sharing Android app with real-time image uploading and downloading functionality using Alibaba Cloud OSS.

PrincipleofSearchingForSimilarImages_part1

By Sai Sarath Chandra, Alibaba Cloud Tech Share Author and Alibaba Cloud MVP

This is the last section of the photo sharing Android application tutorial. We will create the corresponding Java code and complete the whole application after changing some of the configuration values. We will then run the application and see the results correspondingly.

Updating strings.xml

Open your strings.xml file and update the file with the below values make sure you update the Access key ID, access key secret, end point, bucket name, bucket endpoint and STS token.

<resources>
    <string name="app_name">Photo Sharing</string>

    <!-- Alibaba KMS Service details-->
    <!-- Please replace this details with your own -->
    <!--Public Endpoint-->
    <string name="Endpoint">PLEASE REPLACE WITH YOUR REGION ENDPOINT</string>
    <!-- STS Access ID -->
    <string name="AccessKey">PLEASE REPLACE WITH YOUR STS ACCESS KEY</string>
    <!-- STS Access key Secret -->
    <string name="AccessKeySecret">PLEASE REPLACE WITH YOUR STS SECRET ACCESS KEY</string>
    <string name="Bucket_Endpoint">REPLACE FULLY QUALIFIED ENDPOINT OF BUCKET WITH REGION</string>
    <string name="Bucket_Name">PLEASE REPLACE WITH YOUR BUCKET NAME</string>
    <string name="stsToken">PLEASE REPLACE WITH YOUR STS TOKEN</string>


    <string name="bungee_regular">fonts/Bungee-Regular.ttf</string>
    <string name="breeserif">fonts/BreeSerif-Regular.ttf</string>

</resources>

Downloading Fonts

I used two types of fonts for this application. You can download the font from https://fonts.google.com or from anywhere else. All the fonts used are open source and we can use them in our projects. The fonts used in this application are:

• BreeSerif-Regular.ttf
• Bungee-Regular.ttf

Creating Java Code

Util:

Create a util package under the existing package and create the below mentioned Java files.

Let's create some utility classes for the application that is common for all the functionalities, such as providing customised font and application level constants.

CustomFont.java

This class contains provides the functionality of providing the typeface for the customized font.

Creating an object of this class requires the context parameter to be passed after initialization. Create the Java file as mentioned and update the code with the below provided:

package sample.alibabacloud.photosharing.util;

import android.content.Context;
import android.graphics.Typeface;

import sample.alibabacloud.photosharing.R;

/**
 * Created by saisarathchandra on 25/12/17.
 */

public class CustomFont {

    private Context mContext;

    public CustomFont(Context mContext) {
        this.mContext = mContext;
    }

    public Typeface getBungeeRegular(){
        return Typeface.createFromAsset(mContext.getAssets(),mContext.getString(R.string.bungee_regular));
    }

    public Typeface getBreeSerifRegular(){
        return Typeface.createFromAsset(mContext.getAssets(),mContext.getString(R.string.breeserif));
    }
}

Constants.java

This class contains all the static field members. These are the style definitions for various image processing functionalities in an application and their corresponding names. Create the file and update the code with the below provided:

package sample.alibabacloud.photosharing.util;

/**
 * Created by saisarathchandra on 25/12/17.
 */

public class Constants {

    public final static String RESIZE_STYLE_DEF = "image/resize,m_fixed,w_100,h_100";
    public final static String RESIZE_STYLE_NAME = "resized";
    public final static String CROP_STYLE_DEF = "image/crop,w_100,h_100,x_100,y_100,r_1";
    public final static String CROP_STYLE_NAME = "cropped";
    public final static String ROTATE_STYLE_DEF = "image/rotate,90";
    public final static String ROTATE_STYLE_NAME = "rotated";
    public final static String SHARPEN_STYLE_DEF = "image/sharpen,100";
    public final static String SHARPEN_STYLE_NAME = "sharpened";
    public final static String WATERMARK_STYLE_DEF = "image/watermark,text_QWxpYmFiYUNsb3Vk";
    public final static String WATERMARK_STYLE_NAME = "watermarked";
}

model

Here we create the model classes for the application, which represents the information in a particular object

Create model package under the existing package at the same level of util package and create the below mentioned files:

ImageProcessDataModel.java

This class represents the information required for the image processing feature of Alibaba Cloud. Our application will not be using all the attributes mentioned in this Bean class, but in other applications, we may use all the attributes. Create the corresponding file by copying the below code:

package sample.alibabacloud.photosharing.model;

/**
 * Created by saisarathchandra on 25/12/17.
 */

public class ImageProcessDataModel {

    private String style;
    private String styleName;
    private String imageName;
    private String imageStyle;

    public String getStyle() {
        return style;
    }

    public void setStyle(String style) {
        this.style = style;
    }

    public String getStyleName() {
        return styleName;
    }

    public void setStyleName(String styleName) {
        this.styleName = styleName;
    }

    public String getImageName() {
        return imageName;
    }

    public void setImageName(String imageName) {
        this.imageName = imageName;
    }

    public String getImageStyle() {
        return imageStyle;
    }

    public void setImageStyle(String imageStyle) {
        this.imageStyle = imageStyle;
    }
}

ImageData.java

This class is created to transfer the file related information provided by camera, gallery, and documents to the OSS. Create the corresponding file and copy the code below

package sample.alibabacloud.photosharing.model;

/**
 * Created by saisarathchandra on 25/12/17.
 */

public class ImageData {
    private String imageURL;
    private String imageName;

    public String getImageURL() {
        return imageURL;
    }

    public void setImageURL(String imageURL) {
        this.imageURL = imageURL;
    }

    public String getImageName() {
        return imageName;
    }

    public void setImageName(String imageName) {
        this.imageName = imageName;
    }
}

Now, we create multiple Java files which interacts with the XML files created in the previous section and provides the functionality for the same.

WelcomeActivity.java

This Java file load the "welcome activity" XML and bootstrap the upload files and view images to the corresponding screens. You can even see that the fonts are being applied here. Create the file as named and copy the below code:

package sample.alibabacloud.photosharing;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.Button;

import sample.alibabacloud.photosharing.util.CustomFont;

/**
 * Created by saisarathchandra on 25/12/17.
 */

public class WelcomeActivity extends Activity implements View.OnClickListener{

    Button uploadFiles,viewImages;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_welcome);

        CustomFont customFont = new CustomFont(this);

        uploadFiles = findViewById(R.id.uploadFiles);
        viewImages = findViewById(R.id.viewImages);

        uploadFiles.setTypeface(customFont.getBungeeRegular());
        viewImages.setTypeface(customFont.getBungeeRegular());
        uploadFiles.setOnClickListener(this);
        viewImages.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if(id == R.id.uploadFiles){
            Intent i = new Intent(this,MainActivity.class);
            startActivity(i);
        }else if(id == R.id.viewImages){
            Intent i = new Intent(this,ImageRecyclerList.class);
            startActivity(i);
        }
    }
}

ImageDataAdapter.java

This is the adapter class for the recyclerview. This class functionality is to provide the input for the recyclerview and render the items in the recyclerview as requested by the Android system. Create the corresponding file and copy the below code:

package sample.alibabacloud.photosharing;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.List;

import sample.alibabacloud.photosharing.model.ImageData;

/**
 * Created by saisarathchandra on 25/12/17.
 */

public class ImageDataAdapter extends RecyclerView.Adapter<ImageDataAdapter.MyViewHolder> {

    private List<ImageData> imageDataList;
    private Context mContext;

    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView imageName;
        public ImageView imageView;


        public MyViewHolder(View view) {
            super(view);
           imageView = view.findViewById(R.id.imageView);
           imageName = view.findViewById(R.id.imageName);
        }
    }


    public ImageDataAdapter(List<ImageData> imageDataList,Context mContext) {
        this.imageDataList = imageDataList;
        this.mContext = mContext;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recyclerview_row, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        ImageData imageData = imageDataList.get(position);
        Glide.with(mContext).load(imageData.getImageURL()).into(holder.imageView);
        holder.imageName.setText(imageData.getImageName());
    }

    @Override
    public int getItemCount() {
        return imageDataList.size();
    }
}

ImageRecyclerList.java

This class is responsible for showing the list of images retrieved from Alibaba Cloud and updates the list when there is a change on the Alibaba Cloud OSS. This information will be shown when the user selects view images in the welcome activity. Create the file as mentioned and copy the code from below:

package sample.alibabacloud.photosharing;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.ListObjectsRequest;
import com.alibaba.sdk.android.oss.model.ListObjectsResult;

import java.util.ArrayList;
import java.util.List;

import sample.alibabacloud.photosharing.model.ImageData;

/**
 * Created by saisarathchandra on 25/12/17.
 */

public class ImageRecyclerList extends Activity {

    private List<ImageData> imageDataList = new ArrayList<>();
    private RecyclerView recyclerView;
    private ImageDataAdapter mAdapter;
    OSS oss;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_img_recycler);

        recyclerView = findViewById(R.id.recycler_view);
        mAdapter = new ImageDataAdapter(imageDataList,this);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(mAdapter);

        OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(getString(R.string.AccessKey),getString(R.string.AccessKeySecret),getString(R.string.stsToken));
        oss = new OSSClient(getApplicationContext(), getString(R.string.Endpoint), credentialProvider);

        getFiles();

    }

    public void getFiles(){
        ListObjectsRequest listObjects = new ListObjectsRequest(getString(R.string.Bucket_Name));

        OSSAsyncTask task = oss.asyncListObjects(listObjects, new OSSCompletedCallback<ListObjectsRequest, ListObjectsResult>() {
            @Override
            public void onSuccess(ListObjectsRequest request, ListObjectsResult result) {
                Log.d("AyncListObjects", "Success!");
                imageDataList.clear();
                for (int i = 0; i < result.getObjectSummaries().size(); i++) {
                    Log.d("AyncListObjects", "object: " + result.getObjectSummaries().get(i).getKey() + " "
                            + result.getObjectSummaries().get(i).getETag() + " "
                            + result.getObjectSummaries().get(i).getLastModified());

                    ImageData imageData = new ImageData();
                    imageData.setImageName(result.getObjectSummaries().get(i).getKey());
                    imageData.setImageURL(getString(R.string.Bucket_Endpoint)+result.getObjectSummaries().get(i).getKey());
                    imageDataList.add(imageData);
                }
                mAdapter.notifyDataSetChanged();
            }
            @Override
            public void onFailure(ListObjectsRequest request, ClientException clientExcepion, ServiceException serviceException) {
                // Request exception
                if (clientExcepion != null) {
                    // Local exception, such as a network exception
                    clientExcepion.printStackTrace();
                }
                if (serviceException != null) {
                    // Service exception
                    Log.e("ErrorCode", serviceException.getErrorCode());
                    Log.e("RequestId", serviceException.getRequestId());
                    Log.e("HostId", serviceException.getHostId());
                    Log.e("RawMessage", serviceException.getRawMessage());
                }
            }
        });
        task.waitUntilFinished();
    }

}

MainActivity.java

This class contains the complete functionality of the image processing feature. This class also invokes the camera, gallery, and documents folder. We will be using a third-party library called EasyImage. We will discuss more about main activity once we complete creating the files.

Copy below code into the activity:

package sample.alibabacloud.photosharing;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;

import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.callback.OSSProgressCallback;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.GetObjectRequest;
import com.alibaba.sdk.android.oss.model.GetObjectResult;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import pl.aprilapps.easyphotopicker.DefaultCallback;
import pl.aprilapps.easyphotopicker.EasyImage;
import sample.alibabacloud.photosharing.model.ImageProcessDataModel;
import sample.alibabacloud.photosharing.util.Constants;
import sample.alibabacloud.photosharing.util.CustomFont;

public class  MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int REQUEST_CODE_CHOOSE = 800;
    private final static String TAG = "MainActivity";
    ImageButton cameraBtn, galleryBtn, documentsBtn;
    Button resizeImg, cropImg, rotateImg, sharpenImg, watermarkImg;
    List<Uri> mSelected;
    OSS oss;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        CustomFont customFont = new CustomFont(this);

        cameraBtn = findViewById(R.id.cameraBtn);
        galleryBtn = findViewById(R.id.galleryBtn);
        documentsBtn = findViewById(R.id.documentsBtn);

        resizeImg = findViewById(R.id.resizeImg);
        cropImg = findViewById(R.id.cropImg);
        rotateImg = findViewById(R.id.rotateImg);
        sharpenImg = findViewById(R.id.sharpenImg);
        watermarkImg = findViewById(R.id.watermarkImg);

        resizeImg.setTypeface(customFont.getBreeSerifRegular());
        cropImg.setTypeface(customFont.getBreeSerifRegular());
        rotateImg.setTypeface(customFont.getBreeSerifRegular());
        sharpenImg.setTypeface(customFont.getBreeSerifRegular());
        watermarkImg.setTypeface(customFont.getBreeSerifRegular());

        mSelected = new ArrayList<>();

        cameraBtn.setOnClickListener(this);
        galleryBtn.setOnClickListener(this);
        documentsBtn.setOnClickListener(this);
        resizeImg.setOnClickListener(this);
        cropImg.setOnClickListener(this);
        rotateImg.setOnClickListener(this);
        sharpenImg.setOnClickListener(this);
        watermarkImg.setOnClickListener(this);
//         Create the Client

        OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(getString(R.string.AccessKey),getString(R.string.AccessKeySecret),getString(R.string.stsToken));
        oss = new OSSClient(getApplicationContext(), getString(R.string.Endpoint), credentialProvider);


    }


    @Override
    public void onClick(View view) {
        int id = view.getId();

        if(id == R.id.cameraBtn){
            Toast.makeText(this,"Opening Camera",Toast.LENGTH_SHORT).show();
            EasyImage.openCamera(this,0);
        }else if(id == R.id.galleryBtn){
            Toast.makeText(this,"Opening Gallery",Toast.LENGTH_SHORT).show();
            EasyImage.openGallery(this,0);
        }else if(id == R.id.documentsBtn){
            Toast.makeText(this,"Opening Documents",Toast.LENGTH_SHORT).show();
            EasyImage.openDocuments(this,0);
        }else if(id == R.id.resizeImg){
            Toast.makeText(this,"Image Resize Requested",Toast.LENGTH_SHORT).show();
            ProcessImg processImg = new ProcessImg(this);
            ImageProcessDataModel imgProcess = new ImageProcessDataModel();
            imgProcess.setStyle(Constants.RESIZE_STYLE_DEF);
            imgProcess.setStyleName(Constants.RESIZE_STYLE_NAME);
            processImg.execute(imgProcess);
        }else if(id == R.id.cropImg){
            Toast.makeText(this,"Image Crop Requested",Toast.LENGTH_SHORT).show();
            ProcessImg processImg = new ProcessImg(this);
            ImageProcessDataModel imgProcess = new ImageProcessDataModel();
            imgProcess.setStyle(Constants.CROP_STYLE_DEF);
            imgProcess.setStyleName(Constants.CROP_STYLE_NAME);
            processImg.execute(imgProcess);
        }else if(id == R.id.rotateImg){
            Toast.makeText(this,"Image Rotate Requested",Toast.LENGTH_SHORT).show();
            ProcessImg processImg = new ProcessImg(this);
            ImageProcessDataModel imgProcess = new ImageProcessDataModel();
            imgProcess.setStyle(Constants.ROTATE_STYLE_DEF);
            imgProcess.setStyleName(Constants.ROTATE_STYLE_NAME);
            processImg.execute(imgProcess);
        }else if(id == R.id.sharpenImg){
            Toast.makeText(this,"Image Sharpening Requested",Toast.LENGTH_SHORT).show();
            ProcessImg processImg = new ProcessImg(this);
            ImageProcessDataModel imgProcess = new ImageProcessDataModel();
            imgProcess.setStyle(Constants.SHARPEN_STYLE_DEF);
            imgProcess.setStyleName(Constants.SHARPEN_STYLE_NAME);
            processImg.execute(imgProcess);
        }else if(id == R.id.watermarkImg){
            Toast.makeText(this,"Image Watermarking Requested",Toast.LENGTH_SHORT).show();
            ProcessImg processImg = new ProcessImg(this);
            ImageProcessDataModel imgProcess = new ImageProcessDataModel();
            imgProcess.setStyle(Constants.WATERMARK_STYLE_DEF);
            imgProcess.setStyleName(Constants.WATERMARK_STYLE_NAME);
            processImg.execute(imgProcess);
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        EasyImage.handleActivityResult(requestCode, resultCode, data, this, new DefaultCallback() {
            @Override
            public void onImagePickerError(Exception e, EasyImage.ImageSource source, int type) {
                Log.d(TAG, "onImagePickerError: Error in Image handling");
            }

            @Override
            public void onImagePicked(File imageFile, EasyImage.ImageSource source, int type) {
                Log.d(TAG, "onImagePicked:"+imageFile.getAbsolutePath());
                putFileOSS(imageFile.getAbsolutePath());

            }

            @Override
            public void onCanceled(EasyImage.ImageSource source, int type) {
                //Cancel handling, you might wanna remove taken photo if it was canceled
                if (source == EasyImage.ImageSource.CAMERA) {
                    File photoFile = EasyImage.lastlyTakenButCanceledPhoto(MainActivity.this);
                    if (photoFile != null)
                        photoFile.delete();
                }
            }
        });
    }

    public void putFileOSS(String filePath){
        PutObjectRequest put = new PutObjectRequest(getString(R.string.Bucket_Name), "Demo_Picture_1.png", filePath);
        put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
            @Override
            public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
            }
        });
        OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
            @Override
            public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                Log.d("PutObject", "UploadSuccess");
                Log.d("ETag", result.getETag());
                Log.d("RequestId", result.getRequestId());
            }
            @Override
            public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                // Request exception
                if (clientExcepion != null) {
                    // Local exception, such as a network exception
                    clientExcepion.printStackTrace();
                }
                if (serviceException != null) {
                    // Service exception
                    Log.e("ErrorCode", serviceException.getErrorCode());
                    Log.e("RequestId", serviceException.getRequestId());
                    Log.e("HostId", serviceException.getHostId());
                    Log.e("RawMessage", serviceException.getRawMessage());
                }
            }
        });

    }

    class ProcessImg extends AsyncTask<ImageProcessDataModel, Void, Void> {
        private ProgressDialog dialog;

        public ProcessImg(Activity activity) {
            dialog = new ProgressDialog(activity);
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            dialog.setMessage("Processing Image");
            dialog.show();
            dialog.setCancelable(false);
        }

        @Override
        protected Void doInBackground(ImageProcessDataModel... dataModel) {

                ImageProcessDataModel data = dataModel[0];
                String fileName = "Demo_Picture_1";
                String transformedFileName = fileName+"_"+data.getStyleName()+".jpg";

                try {
//                    String style = "image/resize,m_fixed,w_100,h_100";
                    GetObjectRequest request = new GetObjectRequest(getString(R.string.Bucket_Name), fileName+".png");
                    TestGetCallback getCallback = new TestGetCallback();

                    request.setxOssProcess(data.getStyle());

                    request.setProgressListener(new OSSProgressCallback<GetObjectRequest>() {
                        @Override
                        public void onProgress(GetObjectRequest request, long currentSize, long totalSize) {
                            Log.d(TAG, "getobj_progress: " + currentSize+"  total_size: " + totalSize);
                            final long percent= currentSize/totalSize;
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    dialog.setMessage("Processed : "+(percent*100));
                                }
                            });
                        }
                    });

                    OSSAsyncTask task = oss.asyncGetObject(request, getCallback);
                    task.waitUntilFinished();

                    Log.d(TAG, "resizeImg: "+getCallback.result.getMetadata().toString());
                    Log.d(TAG, "resizeImg: "+getCallback.request.getObjectKey());


                    PutObjectRequest put = new PutObjectRequest(getString(R.string.Bucket_Name), transformedFileName, org.apache.commons.io.IOUtils.toByteArray(getCallback.result.getObjectContent()));
                    put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
                        @Override
                        public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                            Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
                        }
                    });

                    OSSAsyncTask task2 = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
                        @Override
                        public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                            Log.d("PutObject", "UploadSuccess");
                            Log.d("ETag", result.getETag());
                            Log.d("RequestId", result.getRequestId());
                        }
                        @Override
                        public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                            // Request exception
                            if (clientExcepion != null) {
                                // Local exception, such as a network exception
                                clientExcepion.printStackTrace();
                            }
                            if (serviceException != null) {
                                // Service exception
                                Log.e("ErrorCode", serviceException.getErrorCode());
                                Log.e("RequestId", serviceException.getRequestId());
                                Log.e("HostId", serviceException.getHostId());
                                Log.e("RawMessage", serviceException.getRawMessage());
                            }
                        }
                    });
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            if(dialog.isShowing()){
                dialog.dismiss();
            }

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "Operation Completed", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

    public final static class TestGetCallback implements OSSCompletedCallback<GetObjectRequest, GetObjectResult> {

        private GetObjectRequest request;
        private GetObjectResult result;
        private ClientException clientException;
        private ServiceException serviceException;


        @Override
        public void onSuccess(GetObjectRequest request, GetObjectResult result) {
            this.request = request;
            this.result = result;

            Log.d(TAG, "onSuccess: "+result);
        }

        @Override
        public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
            this.request = request;
            this.clientException = clientExcepion;
            this.serviceException = serviceException;
        }
    }
}

Updating Manifest:

The last and most important step after we creating the file is to register them in the AndroidManifest.xml. Update your manifest with the below code:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="sample.alibabacloud.photosharing">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".WelcomeActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".MainActivity"/>
        <activity android:name=".ImageRecyclerList" />

    </application>

</manifest>

As you can see we require multiple permissions in the Android manifest, which includes internet, network state, Wi-Fi state, external storage, and camera. These permissions are required by the application for it to function normally.

Using the Application:

Let's discuss about the logic involved in using the application. When a user clicks on upload images, a screen is launched. The welcome activity code is invoked, which then invokes the main activity code.

The top 3 image buttons, which display the camera gallery and document icon, provide the functionality of launching the default corresponding applications. After a user selects a file, the corresponding file will be uploaded on to the Alibaba Cloud. The user can see the same file by opening the Alibaba Cloud Object Storage Service (OSS) console.

We can use the image processing feature of OSS to perform image editing functionalities like resize, crop, rotate, and watermarking. The application uses a constant file to fit the image style definition and the corresponding image names. The application then invokes the image process task and make a request to the OSS service to transform the image. OSS returns the transformed image as a response to this request.

The processed image needs to be uploaded back onto the server from the client to be saved as an new image. You can also rewrite the existing image with the updated image, but personally, I prefer to keep all the transformed images separated. To do this, I send the original filename with the style we applied during the processing, and the application will save it as a new file using the putobjectrequest in the image process task.

Once all the images are processed, you can navigate to the welcome page to view the images. Recyclerview helps to display and provide the corresponding file names on the app.

1

2

3

Conclusion:

Alibaba Cloud Object Storage Service (OSS) provides excellent response times upon uploading and downloading the images. I really like the asynchronous API provided by them, not many tools out there provide the same feature. It reduces the development time and the number of bugs we face when performing post development activities. There is a gentle learning curve for the beginners or developers working on it but in long-term it is very useful.

If everything is done correctly all your compilation issues will go away and the application starts installing in by clicking the small play (run) button in the status bar of the Android studio.

4

I tried not to modularize the application too much so that it is very easy to understand and clear. You can get the source code on my GitHub repository, which contains the working version of code. I recommend cloning the repository to reduce errors and get started immediately. If you have any issues or clarifications, please raise it as an issue or question here: https://github.com/saichandu415/OSS-Android-Sample/issues

相关实践学习
通义万相文本绘图与人像美化
本解决方案展示了如何利用自研的通义万相AIGC技术在Web服务中实现先进的图像生成。
目录
相关文章
|
缓存 对象存储 数据安全/隐私保护
阿里云OSS图片访问出现跨域:Access to image at from origin has been blocked by CORS policy
阿里云OSS图片访问出现跨域:Access to image at from origin has been blocked by CORS policy
3719 0
阿里云OSS图片访问出现跨域:Access to image at from origin has been blocked by CORS policy
|
1月前
|
存储 人工智能 Cloud Native
阿里云渠道商:OSS与传统存储系统的差异在哪里?
本文对比传统存储与云原生对象存储OSS的架构差异,涵盖性能、成本、扩展性等方面。OSS凭借高持久性、弹性扩容及与云服务深度集成,成为大数据与AI时代的优选方案。
|
3月前
|
存储 运维 安全
阿里云国际站OSS与自建存储的区别
阿里云国际站对象存储OSS提供海量、安全、低成本的云存储解决方案。相比自建存储,OSS具备易用性强、稳定性高、安全性好、成本更低等优势,支持无限扩展、自动冗余、多层防护及丰富增值服务,助力企业高效管理数据。
|
3月前
|
存储 域名解析 前端开发
震惊!不买服务器,还可以用阿里云国际站 OSS 轻松搭建静态网站
在数字化时代,利用阿里云国际站OSS可低成本搭建静态网站。本文详解OSS优势及步骤:创建Bucket、上传文件、配置首页与404页面、绑定域名等,助你快速上线个人或小型业务网站,操作简单,成本低廉,适合初学者与中小企业。
|
机器学习/深度学习 人工智能 专有云
人工智能平台PAI使用问题之怎么将DLC的数据写入到另一个阿里云主账号的OSS中
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
9月前
|
SQL 分布式计算 Serverless
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
240 0
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
存储 机器学习/深度学习 弹性计算
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
226 1
|
消息中间件 分布式计算 DataWorks
DataWorks产品使用合集之如何使用Python和阿里云SDK读取OSS中的文件
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。

热门文章

最新文章

下一篇
oss云网关配置