-
结果展示:
当点击默认头像的时候可以弹上传头像提示框,你可以选择相册中挑选或拍照。
我这里选了拍照,然后填写昵称,完成按钮变成可点击,点击完成,更新Bmob后台用户信息。
这里是我的Bmob后台用户信息的更新结果,你可以看见用户昵称是嘤嘤嘤,用户头像也有了url地址。
-
bug:在上传准备更新后台用户信息的时候,提示上传失败,要开通域名管理。查了官网,解决办法是要购买独立域名:
目前有2种解决方案:(这是官方的解决方案,虽然心疼,但想着为知识付费,还是乖乖扫了码)
方案一:(100/年)我们提供了备案域名:在控制台->应用设置->应用配置->开启文件独立域名,开启后图片即可访问。
方案二:(免费)自有已经备案的域名,进入应用设置,域名管理,绑定自有域名。
-
接下来是代码:
-
首先要写好跳转的相关代码,这里就不给出来啦,很简单,就按照你自己的逻辑,什么时候跳转到上传头像和昵称页就看个人啦。
-
接着就是上传头像和昵称页,写好布局文件,在Activity页进行控件初始化。以下是布局文件代码。
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".UI.FirstUploadActivity">
<LinearLayout
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:gravity="center"
android:textSize="20sp"
android:textColor="@android:color/black"
android:layout_marginTop="50dp"
android:layout_marginBottom="30dp"
android:text="@string/attractPeople"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</TextView>
<!-- 中间的头像-->
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:background="@drawable/img_upload_photo_bg"
android:layout_centerInParent="true"
android:layout_width="200dp"
android:layout_height="200dp">
</ImageView>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/circleImageView"
android:src="@drawable/ic_launcher2"
android:layout_width="145dp"
android:layout_centerInParent="true"
android:layout_height="145dp">
</de.hdodenhof.circleimageview.CircleImageView>
</RelativeLayout>
<TextView
android:id="@+id/tv_nameStory"
android:layout_marginBottom="10dp"
android:layout_marginTop="30dp"
android:textSize="20sp"
android:textColor="@android:color/black"
android:text="@string/oneNameOneStory"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<EditText
android:id="@+id/et_nickname"
android:hint="昵称"
android:layout_width="300dp"
android:gravity="center"
android:background="@drawable/login_edit_bg"
android:layout_height="50dp">
</EditText>
<Button
android:id="@+id/btn_finish"
android:textSize="15sp"
android:textColor="@android:color/white"
android:text="@string/finish_first_upload"
android:layout_marginTop="50dp"
android:background="@drawable/btnbg"
android:layout_width="300dp"
android:layout_height="wrap_content">
</Button>
</LinearLayout>
</ScrollView>
布局效果图:
- 然后写代码逻辑:在点击头像的时候弹出上传提示框,上传提示框有DialogManager类控制;在点击拍照是时候跳转到相机,跳转到相机有FileHelper控制;在点击相册的时候跳转到手机相册,也是有FileHelper类控制;在准备好头像和填写完昵称的时候,点击完成,更新用户信息,监听用户信息是否上传成功,有BmobManager控制。这期间有等待提示框也是有LodingView类控制。以下是各个控制类的代码:
DialogManager:
package com.example.framework.Manager;
import android.content.Context;
import android.view.Gravity;
import com.example.framework.R;
import com.example.framework.View.DialogView;
/**
* Created By LicaiWen
* To DO:
*/
public class DialogManager {
private volatile static DialogManager dialogManager = null;
private DialogManager() {
}
public static DialogManager getDialogManagerInstance() {
if (dialogManager == null) {
synchronized (DialogManager.class) {
if (dialogManager == null) {
dialogManager = new DialogManager();
}
}
}
return dialogManager;
}
//initView方法返回DiaogView实例
public DialogView initView(Context context, int layout, int gravity) {
return new DialogView(context, layout, R.style.Theme_Dialog, gravity);
}
//重写initView方法,因为大多是dialog的位置是在中间的,而且背景是透明无标题的,所以这个initView方法默认背景透明,无标题,且弹出位置在中间。
public DialogView initView(Context context, int layout) {
return new DialogView(context, layout, R.style.Theme_Dialog, Gravity.CENTER);
}
//显示DialogView
public void show(DialogView view) {
if (view != null) {
if (!view.isShowing()) {
view.show();
}
}
}
//隐藏DialogView
public void hide(DialogView view) {
if (view != null) {
if (view.isShowing()) {
view.dismiss();
}
}
}
}
FileHelper类:
package helper;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import androidx.core.content.FileProvider;
import androidx.loader.content.CursorLoader;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created By LicaiWen
* To DO:
*/
//文件帮助类
public class FileHelper {
public static final int CAMERA_REQUEST_CODE = 1004;
public static final int ALBUM_REQUEST_CODE = 1005;
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MMM-ddd");
private Uri uriFile;
private File storageFile = null;
private static FileHelper fileHelperInstance = null;
private FileHelper() {
}
public static FileHelper getFileHelperInstance() {
if (fileHelperInstance == null) {
synchronized (FileHelper.class) {
if (fileHelperInstance == null) {
fileHelperInstance = new FileHelper();
}
}
}
return fileHelperInstance;
}
public File getStorageFile() {
return storageFile;
}
/*
* 跳转到照相
* */
public void toCamera(Activity activity) {
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
String fileName = simpleDateFormat.format(new Date());
storageFile = new File(Environment.getExternalStorageDirectory(), fileName + ".jpg");
//兼容android7.0
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
//小于7.0
uriFile = Uri.fromFile(storageFile);
} else {
uriFile = FileProvider.getUriForFile(activity, "com.example.meet.fileprovider", storageFile);
//android在7.0后是要添加的
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriFile);
activity.startActivityForResult(intent, CAMERA_REQUEST_CODE);
}
/*
* 跳转到相册
* */
public void toAlbum(Activity activity) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
activity.startActivityForResult(intent, ALBUM_REQUEST_CODE);
}
/*
* 得到uri的真实地址,一位获取到的uri是经过封装的
* */
public String getRealPathFRomUri(Context context, Uri uri) {
String[] project = {MediaStore.Images.Media.DATA};
CursorLoader cursorLoader = new CursorLoader(context, uri, project, null, null, null);
Cursor cursor = cursorLoader.loadInBackground();
int index = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(index);
}
}
LodingView类:
package com.example.framework.View;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Build;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.framework.R;
import com.example.framework.Manager.DialogManager;
import com.example.framework.utils.AnimUtils;
/**
* Created By LicaiWen
* To DO:
*/
public class LodingView {
private DialogView mLodingView;
private ImageView iv_loding;
private TextView tv_loding;
private ObjectAnimator anim;
public LodingView(Context context) {
mLodingView = DialogManager.getDialogManagerInstance().initView(context, R.layout.loding_view);
iv_loding = (ImageView) mLodingView.findViewById(R.id.iv_loding);
tv_loding = (TextView) mLodingView.findViewById(R.id.tv_loding);
anim = AnimUtils.animRotation(iv_loding);
}
public void setLoadingText(String text) {
tv_loding.setText(text);
}
public void show() {
anim.start();
DialogManager.getDialogManagerInstance().show(mLodingView);
}
public void hide() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
anim.pause();
}
DialogManager.getDialogManagerInstance().hide(mLodingView);
}
public void show(String text) {
setLoadingText(text);
anim.start();
DialogManager.getDialogManagerInstance().show(mLodingView);
}
}
BmobManager类:
package com.example.framework.Manager;
import android.content.Context;
import com.example.framework.bmob.MyBmobUser;
import com.example.framework.entity.StaticClass;
import java.io.File;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobSMS;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.datatype.BmobFile;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.LogInListener;
import cn.bmob.v3.listener.QueryListener;
import cn.bmob.v3.listener.UpdateListener;
import cn.bmob.v3.listener.UploadFileListener;
import io.rong.imlib.RongIMClient;
import static cn.bmob.v3.BmobUser.signOrLoginByMobilePhone;
/**
* Created By LicaiWen
* To DO:
*/
//bmob管理类
public class BmobManager {
public static final String BMOB_APPID = "8c4aa55ae7076048f72fa40e05945293";
private volatile static BmobManager bmobManager = null;
private BmobManager() {
}
public static BmobManager getBmobManagerInstance() {
if (bmobManager == null) {
synchronized (BmobManager.class) {
if (bmobManager == null) {
bmobManager = new BmobManager();
}
}
}
return bmobManager;
}
public void initBmob(Context context) {
Bmob.initialize(context, BMOB_APPID);
// RongIMClient.init(context,StaticClass.RONGYUN_APPID);
}
//发送验证码
public void sendVerifyNumber(String phone, QueryListener<Integer> listener) {
BmobSMS.requestSMSCode(phone, "", listener);
}
//核对验证码
public void ensureVerifyNumber(String phone, String code, LogInListener<MyBmobUser> listener) {
signOrLoginByMobilePhone(phone, code, listener);
}
//获取登录成功的对象
public MyBmobUser getMyBombUser() {
return BmobUser.getCurrentUser(MyBmobUser.class);
}
public boolean isLogining() {
return BmobUser.isLogin();
}
//用于获取用户第一次填写的昵称和头像,更新用户信息
public void firstUploadPhoto(final String nickName, File storageFile, final UploadPhotoListener listener) {
//获取当前登录的bmob用户
final MyBmobUser myBmobUser = getMyBombUser();
//上传头像文件到bmob
final BmobFile bmobFile = new BmobFile(storageFile);
bmobFile.uploadblock(new UploadFileListener() {
@Override
public void done(BmobException e) {
if (e == null) {
//上传成功
//更新用户信息
myBmobUser.setNickName(nickName);
myBmobUser.setPhoto(bmobFile.getFileUrl());
//更新用户token
myBmobUser.setTokenNickName(nickName);
myBmobUser.setTokenPhoto(bmobFile.getFileUrl());
myBmobUser.update(new UpdateListener() {
@Override
public void done(BmobException e) {
if (e == null) {
//更新成功
listener.uploadDone();
} else {
//更新失败
listener.uploadFail(e);
}
}
});
} else {
//上传失败
listener.uploadFail(e);
}
}
});
}
public interface UploadPhotoListener {
void uploadDone();
void uploadFail(BmobException e);
}
}
Activity的逻辑代码:
package com.example.meet.UI;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.example.framework.Manager.BmobManager;
import com.example.framework.Manager.DialogManager;
import com.example.framework.View.DialogView;
import com.example.framework.View.LodingView;
import com.example.framework.base.BaseBackActivity;
import com.example.framework.utils.LogUtils;
import com.example.meet.R;
import java.io.File;
import cn.bmob.v3.exception.BmobException;
import de.hdodenhof.circleimageview.CircleImageView;
import helper.FileHelper;
public class FirstUploadActivity extends BaseBackActivity implements View.OnClickListener {
private CircleImageView circleImageView;
private TextView tvNameStory;
private EditText etNickname;
private Button btnFinish;
private DialogView upload_Dialog;
private TextView tvTakephoto;
private TextView tvPictures;
private TextView tvCancel;
private File storageFile;
private LodingView lodingView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first_upload);
initView();
}
private void initView() {
circleImageView = (CircleImageView) findViewById(R.id.circleImageView);
tvNameStory = (TextView) findViewById(R.id.tv_nameStory);
etNickname = (EditText) findViewById(R.id.et_nickname);
btnFinish = (Button) findViewById(R.id.btn_finish);
btnFinish.setEnabled(false);
btnFinish.setBackground(getResources().getDrawable(R.color.darkGray));
etNickname.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.length() > 0) {
btnFinish.setEnabled(storageFile != null);
btnFinish.setBackground(getResources().getDrawable(storageFile != null ? R.color.orange_dark : R.color.darkGray));
} else {
btnFinish.setEnabled(false);
btnFinish.setBackground(getResources().getDrawable(R.color.darkGray));
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
circleImageView.setOnClickListener(this);
btnFinish.setOnClickListener(this);
//在初始化的时候调用 creatUploadDialog()方法创建上传提示框并初始化提示框中的按钮
creatUploadDialog();
}
public static void startFirstUploadActivity(Activity content, int requestCode) {
Intent intent = new Intent(content, FirstUploadActivity.class);
content.startActivityForResult(intent, requestCode);
}
public void creatUploadDialog() {
upload_Dialog = DialogManager.getDialogManagerInstance().initView(this, R.layout.upload_dialog, Gravity.BOTTOM);
upload_Dialog.setCancelable(false);
tvTakephoto = (TextView) upload_Dialog.findViewById(R.id.tv_takephoto);
tvPictures = (TextView) upload_Dialog.findViewById(R.id.tv_pictures);
tvCancel = (TextView) upload_Dialog.findViewById(R.id.tv_cancel);
tvTakephoto.setOnClickListener(this);
tvPictures.setOnClickListener(this);
tvCancel.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.circleImageView:
// creatUploadDialog();
// Toast.makeText(this, "点击了", Toast.LENGTH_SHORT).show();
//弹出上传提示框
DialogManager.getDialogManagerInstance().show(upload_Dialog);
break;
//完成,更改bmob
case R.id.btn_finish:
uploadPhoto();
break;
//跳转到照相
case R.id.tv_takephoto:
DialogManager.getDialogManagerInstance().hide(upload_Dialog);
FileHelper.getFileHelperInstance().toCamera(this);
break;
//跳转到相册
case R.id.tv_pictures:
DialogManager.getDialogManagerInstance().hide(upload_Dialog);
FileHelper.getFileHelperInstance().toAlbum(this);
break;
case R.id.tv_cancel:
DialogManager.getDialogManagerInstance().hide(upload_Dialog);
break;
default:
break;
}
}
private void uploadPhoto() {
lodingView = new LodingView(this);
lodingView.show();
String nickName = etNickname.getText().toString().trim();
BmobManager.getBmobManagerInstance().firstUploadPhoto(nickName, storageFile, new BmobManager.UploadPhotoListener() {
@Override
public void uploadDone() {
//更新成功的监听
lodingView.hide();
finish();
}
@Override
public void uploadFail(BmobException e) {
//更新失败的监听
lodingView.hide();
Toast.makeText(FirstUploadActivity.this, "上传事变" + e.toString(), Toast.LENGTH_SHORT).show();
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//LogUtils.i("jnru result");
if (resultCode == Activity.RESULT_OK) {
// LogUtils.i("resultok");
if (requestCode == FileHelper.CAMERA_REQUEST_CODE) {
storageFile = FileHelper.getFileHelperInstance().getStorageFile();
// LogUtils.i("是否为空:"+storageFile==null?"yes":"no");
} else if (requestCode == FileHelper.ALBUM_REQUEST_CODE) {
LogUtils.i("进入相册");
Uri uri = data.getData();
if (uri != null) {
// LogUtils.i("uribuweikong");
String path = FileHelper.getFileHelperInstance().getRealPathFRomUri(this, uri);
storageFile = new File(path);
}
}
//放置图片
if (storageFile != null) {
// LogUtils.i("buweikong ");
Bitmap bitmap = BitmapFactory.decodeFile(storageFile.getPath());
circleImageView.setImageBitmap(bitmap);
}
boolean nickNameIsEmpty = TextUtils.isEmpty(etNickname.getText().toString().trim());
btnFinish.setEnabled(!nickNameIsEmpty);
btnFinish.setBackground(getResources().getDrawable(!nickNameIsEmpty ? R.color.orange_dark : R.color.darkGray));
}
//设置头像
super.onActivityResult(requestCode, resultCode, data);
}
}