This demo uses Qiniu to upload pictures and videos.
If you don't want to see it, you can drag it to the bottom and download it from my github.
Step 1:
build.gradle imports:
compile'top.zibin:Luban:1.0.9'//luban for image compression
compile 'com.android.support:design:25.3.1'
compile'com.qiniu:qiniu-android-sdk:7.2. +'//Qiniu
Compoile'me.iwf.photopicker:PhotoPicker:0.1.8'//Picture selection
compile'cn.fanrunqi:waveprogress:1.0.1'//upload effect
Step 2:
Server integrates Qiniu and provides interface
For example: String url=“ http://112.74.28.179:8080/Chislim/Travel_notes_Servlet?dowhat=getUpLoadToken";
Initialization settings for Qiniu upload in the code
//Initialization of Seven Cattle
private void initConfig() {
Configuration config = new Configuration.Builder()
.chunkSize(256 * 1024) //When uploading fragments, the size of each fragment. Default 256K
.putThreshhold(512 * 1024) // Enable slice upload threshold. Default 512K
.connectTimeout(10) // Link timeout. Default 10 seconds
.responseTimeout(60) // The server response timed out. Default 60 seconds
// When the recorder // recorder fragments are uploaded, the film recorder has been uploaded. Default null
// When A. recorder (keyGen) // keyGen fragment is uploaded, an identifier is generated for the slice recorder to distinguish the uploaded record of that file.
.zone(Zone.zone0) // Set up area, specify upload domain name, standby domain name and standby IP of different area. Default Zone.zone 0
.build();
// Reuse upload Manager. Generally, you just need to create an uploadManager object
uploadManager = new UploadManager(config);
}
After initializing Qiniu, click on the button to send the request to get Qiniu's token and bring it to the page of sending talk.
client.newCall(request).enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
String token = response.body().string();
Log.i("Seven oxen", token);
//Step 3: Jump to the Publishing Talk Page
Intent intent = new Intent(MainActivity.this , PublishHumorActivity.class);
intent.putExtra("token" , token) ;
startActivityForResult(intent , GOTO_PUBLISH_HUMOR_REQUEST);
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
Log.i("Seven oxen", e.getMessage());
}
});
Step 3
Create bean objects to receive uploaded information
public class HumorImgAndVideoBean {
public String fileName =""; //file name
public String path =""; // Local Path
public String urlPath ="" ; //Network path, when uploading only need to upload this to the server storage.
public String compresPath="" ; //Path after image compression
public boolean isVideo ;//Judging whether it's a video or not
public int proess = 0 ; //Upload progress
}
Step 4
Build the layout file, this part is not coded.
The adapter built for recyclerView
public class HumorImgAndVideoAdpter extends RecyclerView.Adapter {
private Context mContext ;
private List<HumorImgAndVideoBean> lists ;
private OnMyItemClick onMyItemClick ;
public void setOnMyItemClick(OnMyItemClick onMyItemClick) {
this.onMyItemClick = onMyItemClick;
}
//Provide click-back events
public interface OnMyItemClick{
public void addData();
public void ImageClick(int position) ;
public void VideoClick() ;
public void addDataNoVideo();
public void deleteItem(int position);
}
public HumorImgAndVideoAdpter(Context mContext , List<HumorImgAndVideoBean> lists){
this.mContext = mContext ;
this.lists = lists ;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.humor_img_video_item , parent , false) ;
return new ImgAndVideoHodler(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
ImgAndVideoHodler holder1 = (ImgAndVideoHodler) holder;
holder1.icon_cancel.setTag(position);
//When the list has no data
if(lists == null || lists.size() == 0){
holder1.icon_cancel.setVisibility(View.GONE);
holder1.waveProgressbar.setVisibility(View.GONE);
Picasso.with(mContext).load(R.mipmap.btn_add).into(holder1.tu_pian);
holder1.tu_pian.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(onMyItemClick != null){
onMyItemClick.addData();
}
}
});
}else {
//When the list has data
//1. Only one is video data.
if(lists.get(0).isVideo == true){
/*Picasso.with(mContext).load(new File(lists.get(position).path) ).resize(200 , 200).into(holder1.tu_pian);*/
holder1.waveProgressbar.setVisibility(View.VISIBLE);
holder1.icon_cancel.setVisibility(View.VISIBLE);
if(lists.get(0).proess != 100) {
holder1.waveProgressbar.setCurrent(lists.get(0).proess, lists.get(0).proess + "%");
}else{
holder1.waveProgressbar.setVisibility(View.GONE);
}
Glide.with(mContext).load(new File(lists.get(position).path)).into(holder1.tu_pian);
holder1.tu_pian.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(onMyItemClick != null){
onMyItemClick.VideoClick();
}
}
});
}else{
//2. When it's all pictures,
if(lists.size() >= 9){
holder1.waveProgressbar.setVisibility(View.VISIBLE);
holder1.icon_cancel.setVisibility(View.VISIBLE);
if(lists.get(position).proess != 100) {
holder1.waveProgressbar.setCurrent(lists.get(position).proess, lists.get(position).proess + "%");
}else{
holder1.waveProgressbar.setVisibility(View.GONE);
}
Picasso.with(mContext).load(new File(lists.get(position).path) ).resize(200 , 200).into(holder1.tu_pian);
holder1.tu_pian.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(onMyItemClick != null){
onMyItemClick.ImageClick(position);
}
}
});
}else{
if(position != lists.size() ){
holder1.waveProgressbar.setVisibility(View.VISIBLE);
holder1.icon_cancel.setVisibility(View.VISIBLE);
if(lists.get(position).proess != 100) {
holder1.waveProgressbar.setCurrent(lists.get(position).proess, lists.get(position).proess + "%");
}else{
holder1.waveProgressbar.setVisibility(View.GONE);
}
Picasso.with(mContext).load(new File(lists.get(position).path) ).resize(200 , 200).into(holder1.tu_pian);
holder1.tu_pian.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(onMyItemClick != null){
onMyItemClick.ImageClick(position);
}
}
});
}else{
holder1.waveProgressbar.setVisibility(View.GONE);
holder1.icon_cancel.setVisibility(View.GONE);
Picasso.with(mContext).load(R.mipmap.btn_add).into(holder1.tu_pian);
holder1.tu_pian.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(onMyItemClick != null){
onMyItemClick.addDataNoVideo();
}
}
});
}
}
}
}
holder1.icon_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(onMyItemClick != null){
onMyItemClick.deleteItem(position);
}
}
});
}
@Override
public int getItemCount() {
if(lists == null || lists.size() == 0 || lists.get(0).isVideo == true){
return 1 ;
}
if(lists.size() >= 9 ){
return 9 ;
}
return lists.size() + 1;
}
public class ImgAndVideoHodler extends RecyclerView.ViewHolder{
public ImageView tu_pian ;
public ImageView icon_cancel ;
public WaveProgressView waveProgressbar ;
public ImgAndVideoHodler(View itemView) {
super(itemView);
// ButterKnife.bind(this , itemView);
tu_pian = (ImageView) itemView.findViewById(R.id.tu_pian);
icon_cancel = (ImageView) itemView.findViewById(R.id.delete_iv);
waveProgressbar = (WaveProgressView)itemView.findViewById(R.id.waveProgressbar);
waveProgressbar.setMaxProgress(100);
}
}
}
Step 5
Implementation of callback method in Adaper
adapter.setOnMyItemClick(new HumorImgAndVideoAdpter.OnMyItemClick() {
@Override
public void addData() {
/* Toast.makeText(mActivity, "No data loading data ", Toast.LENGTH_SHORT).show();
PhotoPickerIntent intentPhoto = new PhotoPickerIntent(mActivity);
intentPhoto.setPhotoCount(9 - lists.size());
intentPhoto.setShowCamera(true);
startActivityForResult(intentPhoto,CHECK_IMAGE_REQUEST );*/
/*Intent intent = new Intent();
intent.setType("video*//*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, CHECK_VIDEO_REQUEST);*/
if (view == null) {
view = LayoutInflater.from(mActivity).inflate(R.layout.layout_popupwindow , null);
}
TextView btnCarema = (TextView) view.findViewById(R.id.btn_camera);
TextView btnPhoto = (TextView) view.findViewById(R.id.btn_photo);
TextView btnCancel = (TextView) view.findViewById(R.id.btn_cancel);
final PopupWindow popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.setBackgroundDrawable(getResources().getDrawable(android.R.color.transparent));
popupWindow.setOutsideTouchable(true);
View parent = LayoutInflater.from(mActivity).inflate(R.layout.activity_publish_humor
, null);
popupWindow.showAtLocation(parent, Gravity.BOTTOM, 0, 0);
//The background of popup window is translucent when it bounces
final WindowManager.LayoutParams params = getWindow().getAttributes();
params.alpha = 0.5f;
getWindow().setAttributes(params);
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
params.alpha = 1.0f;
getWindow().setAttributes(params);
}
});
btnCarema.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Jump to the calling system camera
Intent intent = new Intent();
intent.setType("video/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, CHECK_VIDEO_REQUEST);
popupWindow.dismiss();
}
});
btnPhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Jump to the Call System Gallery
PhotoPickerIntent intentPhoto = new PhotoPickerIntent(mActivity);
intentPhoto.setPhotoCount(9 - lists.size());
intentPhoto.setShowCamera(true);
startActivityForResult(intentPhoto,CHECK_IMAGE_REQUEST );
popupWindow.dismiss();
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popupWindow.dismiss();
}
});
}
@Override
public void ImageClick(int position) {
Toast.makeText(mActivity, "Look at the big picture", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(mActivity , PhotoActivity.class);
PhotoActivity.bitmap = lists ;
intent.putExtra("ID" , position) ;
startActivity(intent);
}
@Override
public void VideoClick() {
//Used to play video
}
@Override
public void addDataNoVideo() {
Toast.makeText(mActivity, "You can't add videos after adding images.", Toast.LENGTH_SHORT).show();
PhotoPickerIntent intentPhoto = new PhotoPickerIntent(mActivity);
intentPhoto.setPhotoCount(9 - lists.size());
intentPhoto.setShowCamera(true);
startActivityForResult(intentPhoto,CHECK_IMAGE_REQUEST );
}
@Override
public void deleteItem(int position) {
lists.remove(position) ;
adapter.notifyDataSetChanged();
}
});
}
Step 6
Select the method of page callback after image or video:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK ){
switch (requestCode){
case CHECK_IMAGE_REQUEST :
//Select the path set returned from the picture
List<String> mResultsPath = data.getStringArrayListExtra(PhotoPickerActivity.KEY_SELECTED_PHOTOS);
for(int i = 0 ; i < mResultsPath.size() ; i++){
final int postion = i ;
final HumorImgAndVideoBean bean = new HumorImgAndVideoBean();
bean.path = mResultsPath.get(i);
//Name of Named File (by Time)
bean.fileName = System.currentTimeMillis()+""+i;
lists.add(bean);
//Compressed pictures
Luban.get(this)
.setFilename(bean.fileName) //Set the file name after compression
.load(new File(bean.path)) //Pictures to be compressed
.putGear(Luban.THIRD_GEAR) //Set compression grade, default three gear
.setCompressListener(new OnCompressListener() { //Setting callback
@Override
public void onStart() {
// Called before TODO compression starts, loading UI can be started within the method
}
@Override
public void onSuccess(File file) {
// TODO is called after successful compression and returns the compressed image file
//Because of the asynchronous compression, the file name is used for comparison here, and the image is not compressed when it is too small.
String name2 = file.getName().split("\\.")[0];
for (int i = 0 ; i< lists.size() ; i++){
String name1 = lists.get(i).fileName;
String pa = lists.get(i).path;
if(name1.equals(name2) || file.getAbsolutePath().equals(pa)){
lists.get(i).compresPath = file.getPath() ;
Message message = myHandler.obtainMessage() ;
message.what = YANSUO_SUCCESS ;
message.arg1 = i ;
myHandler.sendMessage(message) ;
}
}
}
@Override
public void onError(Throwable e) {
// TODO is called when compression has problems in the past
Log.d("There was a problem." , e.getMessage()) ;
}
}).launch(); //Start compression
adapter.notifyDataSetChanged();
}
break;
case CHECK_VIDEO_REQUEST :
HumorImgAndVideoBean bean = new HumorImgAndVideoBean();
bean.isVideo = true ;
Uri uri = data.getData();
Cursor cursor = getContentResolver().query(uri, null, null,
null, null);
cursor.moveToFirst();
// String imgNo = cursor.getString(0); //Picture number
String v_path = cursor.getString(1); // Picture File Path
bean.path = v_path ;
lists.add(bean);
adapter.notifyDataSetChanged();
lists.get(0).compresPath = lists.get(0).path ;
getUpimg(lists.get(0));
break;
}
}
}
When choosing the image compression, luban is used, and the compressed image is asynchronous operation. So according to the name of the compressed file set during compression, the compressed file is compared with it after compression. If the compressed path is the same, the compresPath attribute of the bean is given. Then the compressed image is uploaded to Qiniu's clothes using Qiniu upload. Service side.
**
The first time I wrote a blog, maybe I didn't write it clearly. You can go to github to download my code and see how it works. Project address
If you have any questions, you can add me QQ2372949410. Let's learn a wave together.
**