diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6c3e2fc..c5a1df7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,9 @@ package="com.community.pocket"> + + + liveData, String forumId, String content) { HttpUtil.getRequest(HttpUtil.Method.POST, new SimpleHttpParse(liveData).getInterface(ForumDataResponse.class), - new FormBody.Builder() + LocalToken.create() .add("forumId", forumId) .add("content", content) - .add("token", LocalToken.getToken()) - .add("username", LocalToken.getUsername()) .build() ); } diff --git a/app/src/main/java/com/community/pocket/data/main/forum/ForumPostRequest.java b/app/src/main/java/com/community/pocket/data/main/forum/ForumPostRequest.java index b4df0fa..b2ba54a 100644 --- a/app/src/main/java/com/community/pocket/data/main/forum/ForumPostRequest.java +++ b/app/src/main/java/com/community/pocket/data/main/forum/ForumPostRequest.java @@ -34,15 +34,13 @@ public class ForumPostRequest { public void sendActive(MutableLiveData liveData, String title, String content, String activeStartTime, String activeEndTime, String activeScore, String registrationDeadline) { HttpUtil.getRequest(HttpUtil.Method.POST, new SimpleHttpParse(liveData).getInterface(ForumPostResponse.class), - new FormBody.Builder() + LocalToken.create() .add("title", title) .add("content", content) .add("registrationDeadline", registrationDeadline) .add("activeStartTime", activeStartTime) .add("activeEndTime", activeEndTime) .add("activeScore", activeScore) - .add("token", LocalToken.getToken()) - .add("username", LocalToken.getUsername()) .add("forumType", ForumType.active.name()) .build()); } @@ -52,12 +50,10 @@ public class ForumPostRequest { public void sendComplain(MutableLiveData liveData, String title, String content, String complain) { HttpUtil.getRequest(HttpUtil.Method.POST, new SimpleHttpParse(liveData).getInterface(ForumPostResponse.class), - new FormBody.Builder() + LocalToken.create() .add("title", title) .add("content", content) .add("complain", complain) - .add("token", LocalToken.getToken()) - .add("username", LocalToken.getUsername()) .add("forumType", ForumType.complan.name()) .build()); } @@ -67,11 +63,9 @@ public class ForumPostRequest { public void sendTopic(MutableLiveData liveData, String title, String content) { HttpUtil.getRequest(HttpUtil.Method.POST, new SimpleHttpParse(liveData).getInterface(ForumPostResponse.class), - new FormBody.Builder() + LocalToken.create() .add("title", title) .add("content", content) - .add("token", LocalToken.getToken()) - .add("username", LocalToken.getUsername()) .add("forumType", ForumType.topic.name()) .build()); } @@ -92,12 +86,10 @@ public class ForumPostRequest { public void sendScore(MutableLiveData liveData, String title, String content, String activeScore) { HttpUtil.getRequest(HttpUtil.Method.POST, new SimpleHttpParse(liveData).getInterface(ForumPostResponse.class), - new FormBody.Builder() + LocalToken.create() .add("title", title) .add("content", content) .add("activeScore", activeScore) - .add("token", LocalToken.getToken()) - .add("username", LocalToken.getUsername()) .add("forumType", ForumType.score.name()) .build()); } diff --git a/app/src/main/java/com/community/pocket/data/main/info/InfoRequest.java b/app/src/main/java/com/community/pocket/data/main/info/InfoRequest.java index de61356..7b00681 100644 --- a/app/src/main/java/com/community/pocket/data/main/info/InfoRequest.java +++ b/app/src/main/java/com/community/pocket/data/main/info/InfoRequest.java @@ -1,15 +1,21 @@ package com.community.pocket.data.main.info; +import android.graphics.Bitmap; + import androidx.lifecycle.MutableLiveData; import com.community.pocket.data.model.LocalToken; import com.community.pocket.ui.main.ui.info.InfoResponse; +import com.community.pocket.util.HttpFileResponse; import com.community.pocket.util.HttpRequest; import com.community.pocket.util.HttpUtil; import com.community.pocket.util.SimpleHttpParse; -import okhttp3.FormBody; +import java.io.File; + +import okhttp3.MediaType; +import okhttp3.RequestBody; /** * 个人信息请求接口 @@ -32,11 +38,9 @@ public class InfoRequest { public void modifyPwd(MutableLiveData liveData, String oldPassword, String newPassword) { HttpUtil.getRequest(HttpUtil.Method.POST, new SimpleHttpParse(liveData).getInterface(InfoResponse.class), - new FormBody.Builder() + LocalToken.create() .add("oldPassword", oldPassword) .add("newPassword", newPassword) - .add("token", LocalToken.getToken()) - .add("username", LocalToken.getUsername()) .build()); } @@ -45,9 +49,20 @@ public class InfoRequest { public void loadInfo(MutableLiveData liveData) { HttpUtil.getRequest(HttpUtil.Method.GET, new SimpleHttpParse(liveData).getInterface(InfoResponse.class), - new FormBody.Builder() - .add("token", LocalToken.getToken()) - .add("username", LocalToken.getUsername()) + LocalToken.create().build()); + } + + //上传头像 + @HttpRequest("/uploadHeadImg") + public void uploadImg(MutableLiveData liveData, File picFile) { + HttpUtil.getRequest(new SimpleHttpParse(liveData).getInterface(InfoResponse.class), + LocalToken.createM() + .addFormDataPart("file", picFile.getName(), RequestBody.create(picFile, MediaType.parse("image/png"))) .build()); } + + //获取头像 + public void getImg(MutableLiveData liveData, String url) { + HttpUtil.getRequest(new HttpFileResponse(liveData), url); + } } diff --git a/app/src/main/java/com/community/pocket/data/main/visitor/VisitorMyRequest.java b/app/src/main/java/com/community/pocket/data/main/visitor/VisitorMyRequest.java index f87bc12..77d1cbc 100644 --- a/app/src/main/java/com/community/pocket/data/main/visitor/VisitorMyRequest.java +++ b/app/src/main/java/com/community/pocket/data/main/visitor/VisitorMyRequest.java @@ -31,9 +31,7 @@ public class VisitorMyRequest { */ @HttpRequest("/visitor/my") public void loadMy(MutableLiveData liveData, String startDate, String endDate, Long page) { - FormBody.Builder builder = new FormBody.Builder() - .add("username", LocalToken.getUsername()) - .add("token", LocalToken.getToken()); + FormBody.Builder builder = LocalToken.create(); if (startDate != null && !startDate.isEmpty()) { builder.add("startDate", startDate); } diff --git a/app/src/main/java/com/community/pocket/data/main/visitor/VisitorRequest.java b/app/src/main/java/com/community/pocket/data/main/visitor/VisitorRequest.java index a06be32..9e4600d 100644 --- a/app/src/main/java/com/community/pocket/data/main/visitor/VisitorRequest.java +++ b/app/src/main/java/com/community/pocket/data/main/visitor/VisitorRequest.java @@ -33,14 +33,12 @@ public class VisitorRequest { public void appointment(MutableLiveData liveData, String appointment, String chooseDate, String chooseTime, String notes, boolean checked) { HttpUtil.getRequest(HttpUtil.Method.POST, new SimpleHttpParse(liveData).getInterface(VisitorResponse.class), - new FormBody.Builder() + LocalToken.create() .add("appointment", appointment) .add("chooseDate", chooseDate) .add("chooseTime", chooseTime) .add("notes", notes) .add("isOutPeople", String.valueOf(checked)) - .add("token", LocalToken.getToken()) - .add("username", LocalToken.getUsername()) .build()); } diff --git a/app/src/main/java/com/community/pocket/data/main/visitor/VisitorReservationRequest.java b/app/src/main/java/com/community/pocket/data/main/visitor/VisitorReservationRequest.java index 5af3dc3..06ff21c 100644 --- a/app/src/main/java/com/community/pocket/data/main/visitor/VisitorReservationRequest.java +++ b/app/src/main/java/com/community/pocket/data/main/visitor/VisitorReservationRequest.java @@ -31,9 +31,7 @@ public class VisitorReservationRequest { */ @HttpRequest("/visitor/reservation") public void loadReservation(MutableLiveData liveData, String startDate, String endDate, Long currentPage) { - FormBody.Builder builder = new FormBody.Builder() - .add("username", LocalToken.getUsername()) - .add("token", LocalToken.getToken()); + FormBody.Builder builder = LocalToken.create(); if (startDate != null && !startDate.isEmpty()) { builder.add("startDate", startDate); } diff --git a/app/src/main/java/com/community/pocket/data/model/LocalToken.java b/app/src/main/java/com/community/pocket/data/model/LocalToken.java index d2e9766..2b8b755 100644 --- a/app/src/main/java/com/community/pocket/data/model/LocalToken.java +++ b/app/src/main/java/com/community/pocket/data/model/LocalToken.java @@ -1,5 +1,8 @@ package com.community.pocket.data.model; +import okhttp3.FormBody; +import okhttp3.MultipartBody; + public class LocalToken { private final String token; private final Long time; @@ -47,4 +50,16 @@ public class LocalToken { public static Token getTokenInstance() { return tokenInstance; } + + public static FormBody.Builder create() { + return new FormBody.Builder() + .add("token", LocalToken.getToken()) + .add("username", LocalToken.getUsername()); + } + + public static MultipartBody.Builder createM() { + return new MultipartBody.Builder() + .addFormDataPart("token", LocalToken.getToken()) + .addFormDataPart("username", LocalToken.getUsername()); + } } diff --git a/app/src/main/java/com/community/pocket/ui/login/LoginActivity.java b/app/src/main/java/com/community/pocket/ui/login/LoginActivity.java index d3b2ef2..a0318be 100644 --- a/app/src/main/java/com/community/pocket/ui/login/LoginActivity.java +++ b/app/src/main/java/com/community/pocket/ui/login/LoginActivity.java @@ -27,8 +27,8 @@ import com.community.pocket.ui.main.ui.share.Response; import com.community.pocket.ui.register.RegisterActivity; import com.community.pocket.ui.resetpwd.ResetPwdActivity; import com.community.pocket.util.AppDatabase; +import com.community.pocket.util.HttpJSONResponse; import com.community.pocket.util.HttpRequest; -import com.community.pocket.util.HttpResponse; import com.community.pocket.util.HttpUtil; import com.community.pocket.util.PropertiesUtil; @@ -188,9 +188,10 @@ public class LoginActivity extends BaseActivity { List tokenList = sInstance.tokenDao().queryAll(); if (tokenList != null && tokenList.size() == 1) { Token currentToken = tokenList.get(0); - HttpUtil.getRequest(HttpUtil.Method.POST, new HttpResponse<>(LoginResponse.class, (call, response, loginResponse) -> loginViewModel.getCheckToken().postValue(loginResponse)), + HttpUtil.getRequest(HttpUtil.Method.POST, new HttpJSONResponse<>(LoginResponse.class, (call, response, loginResponse) -> loginViewModel.getCheckToken().postValue(loginResponse)), new FormBody.Builder() .add("token", currentToken.getToken()) + .add("username", currentToken.getUsername()) .build() ); } else if (tokenList != null && tokenList.size() > 1) { diff --git a/app/src/main/java/com/community/pocket/ui/main/ui/info/InfoFragment.java b/app/src/main/java/com/community/pocket/ui/main/ui/info/InfoFragment.java index 6b9e156..d334a6e 100644 --- a/app/src/main/java/com/community/pocket/ui/main/ui/info/InfoFragment.java +++ b/app/src/main/java/com/community/pocket/ui/main/ui/info/InfoFragment.java @@ -1,27 +1,36 @@ package com.community.pocket.ui.main.ui.info; +import android.Manifest; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.graphics.Bitmap; import android.graphics.Paint; import android.graphics.Rect; +import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.provider.MediaStore; import android.text.Editable; import android.text.TextWatcher; +import android.util.Log; +import android.view.Gravity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AlertDialog; -import androidx.lifecycle.Observer; +import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModelProvider; import com.community.pocket.R; @@ -34,6 +43,7 @@ import com.community.pocket.ui.login.LoginActivity; import com.community.pocket.ui.main.ui.share.Response; import com.community.pocket.util.AppDatabase; import com.community.pocket.util.Param; +import com.community.pocket.util.PermissionsUtils; import com.community.pocket.util.PropertiesUtil; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; @@ -49,6 +59,9 @@ import org.xutils.view.annotation.ContentView; import org.xutils.view.annotation.Event; import org.xutils.view.annotation.ViewInject; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -100,6 +113,7 @@ public class InfoFragment extends BaseFragment { //确认新密码 private EditText confirmNewPwd; + //打开修改密码弹窗 @ViewInject(R.id.open_modify_password) private Button openModify; @@ -110,7 +124,15 @@ public class InfoFragment extends BaseFragment { @ViewInject(R.id.logout) private Button logout; - private Handler handler; + //修改密码 + private Handler modifyPwdHandler; + + //上传头像 + private Handler uploadImgHandler; + + //检测是否有读写文件权限 + private MutableLiveData bool = new MutableLiveData<>(); + @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override @@ -124,82 +146,85 @@ public class InfoFragment extends BaseFragment { viewModel.loadInfo(); //监听修改密码表单状态 - viewModel.getModifyFormState().observe(getViewLifecycleOwner(), new Observer() { - @Override - public void onChanged(InfoFormState infoFormState) { - if (infoFormState == null) { - return; - } - if (infoFormState.getOldPwdError() != null) { - oldPwd.setError(getString(infoFormState.getOldPwdError(), PropertiesUtil.getIntValue("password.length"))); - } + viewModel.getModifyFormState().observe(getViewLifecycleOwner(), infoFormState -> { + if (infoFormState == null) { + return; + } + if (infoFormState.getOldPwdError() != null) { + oldPwd.setError(getString(infoFormState.getOldPwdError(), PropertiesUtil.getIntValue("password.length"))); + } - if (infoFormState.getNewPwdError() != null) { - if (infoFormState.getNewPwdError() == R.string.invalid_password) { - newPwd.setError(getString(infoFormState.getNewPwdError(), PropertiesUtil.getIntValue("password.length"))); - } else { - newPwd.setError(getString(infoFormState.getNewPwdError())); - } + if (infoFormState.getNewPwdError() != null) { + if (infoFormState.getNewPwdError() == R.string.invalid_password) { + newPwd.setError(getString(infoFormState.getNewPwdError(), PropertiesUtil.getIntValue("password.length"))); + } else { + newPwd.setError(getString(infoFormState.getNewPwdError())); } + } - if (infoFormState.getConfirmNewPwdError() != null) { - if (infoFormState.getConfirmNewPwdError() == R.string.invalid_password) { - confirmNewPwd.setError(getString(infoFormState.getConfirmNewPwdError(), PropertiesUtil.getIntValue("password.length"))); - } else { - confirmNewPwd.setError(getString(infoFormState.getConfirmNewPwdError())); - } + if (infoFormState.getConfirmNewPwdError() != null) { + if (infoFormState.getConfirmNewPwdError() == R.string.invalid_password) { + confirmNewPwd.setError(getString(infoFormState.getConfirmNewPwdError(), PropertiesUtil.getIntValue("password.length"))); + } else { + confirmNewPwd.setError(getString(infoFormState.getConfirmNewPwdError())); } + } - Message message = new Message(); - Bundle bundle = new Bundle(); - bundle.putBoolean(Param.enable.name(), infoFormState.isDataValid()); - message.setData(bundle); - handler.sendMessage(message); + Message message = new Message(); + Bundle bundle = new Bundle(); + bundle.putBoolean(Param.enable.name(), infoFormState.isDataValid()); + message.setData(bundle); + modifyPwdHandler.sendMessage(message); - } }); //监听修改密码的请求状态 - viewModel.getModifyResponse().observe(getViewLifecycleOwner(), new Observer() { - @Override - public void onChanged(InfoResponse infoResponse) { - if (infoResponse == null) { - return; - } - - infoResponse.toast(getContext()); + viewModel.getModifyResponse().observe(getViewLifecycleOwner(), infoResponse -> { + if (infoResponse == null) { + return; + } - if (infoResponse.getResult() == Response.Result.OK) { - logout(logout); - } + infoResponse.toast(getContext()); + if (infoResponse.getResult() == Response.Result.OK) { + logout(logout); } + }); //监听个人信息请求状态 - viewModel.getInfoResponse().observe(getViewLifecycleOwner(), new Observer() { - @Override - public void onChanged(InfoResponse myInfoInfoResponse) { - if (myInfoInfoResponse == null) { - return; - } + viewModel.getInfoResponse().observe(getViewLifecycleOwner(), myInfoInfoResponse -> { + if (myInfoInfoResponse == null) { + return; + } - myInfoInfoResponse.toast(getContext()); + myInfoInfoResponse.toast(getContext()); - if (myInfoInfoResponse.getResult() == Response.Result.OK) { - loadInfo(myInfoInfoResponse.getMyInfo()); - } + if (myInfoInfoResponse.getResult() == Response.Result.OK) { + loadInfo(myInfoInfoResponse.getMyInfo()); } }); //打开修改密码弹窗 - openModify.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - openModifyPassword(); + openModify.setOnClickListener(v -> openModifyPassword()); + + checkPermissions(); + + clickHeadImg(); + + //监听上传头像状态 + viewModel.getUploadImg().observe(getViewLifecycleOwner(), infoResponse -> { + if (infoResponse == null) { + return; } + + uploadImgHandler.sendEmptyMessage(infoResponse.getResult().ordinal()); + + infoResponse.toast(getContext()); }); + //监听获取头像状态 + viewModel.getGetImg().observe(getViewLifecycleOwner(), bitmap -> headimg.setImageBitmap(bitmap)); } /** @@ -214,12 +239,194 @@ public class InfoFragment extends BaseFragment { recentPosts.setText(getString(R.string.recent_posts, myInfo.getPosts())); mobie.setText(myInfo.getMobie()); email.setText(myInfo.getEmail()); + if (myInfo.getHeadImg() != null && !myInfo.getHeadImg().isEmpty()) { + viewModel.getImg(myInfo.getHeadImg()); + } if (myInfo.getScoreHistory() != null && myInfo.getScoreHistory().size() >= 2) { loadChart(myInfo.getScoreHistory()); } } + private enum Action { + //打开相册 + OPEN_GALLERY, + //打开相机 + OPEN_CAMERA, + //裁剪 + CROP + } + + /** + * 检查读写权限 + */ + private void checkPermissions() { + PermissionsUtils.getInstance().checkPermissions(getActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, + new PermissionsUtils.IPermissionsResult() { + @Override + public void passPermissons() { + File file = getPhotoDir(); + if (file.exists()) { + bool.postValue(true); + } else { + bool.postValue(false); + String msg = "无法创建照片目录"; + Log.e(InfoFragment.class.getName(), msg); + throw new RuntimeException(msg); + } + } + + @Override + public void forbitPermissons() { + bool.postValue(false); + } + }); + + } + + + /** + * 点击头像操作 + */ + private void clickHeadImg() { + bool.observe(getViewLifecycleOwner(), aBoolean -> { + if (aBoolean) { + headimg.setOnClickListener(v -> new AlertDialog.Builder(Objects.requireNonNull(getContext())) + .setNegativeButton(R.string.open_photo_album, (dialog, which) -> { + // 打开相册 + Intent intent = new Intent(Intent.ACTION_PICK); + intent.setType("image/*"); + startActivityForResult(intent, Action.OPEN_GALLERY.ordinal()); + }) + .setNeutralButton(R.string.take_photo, (dialog, which) -> { + //定义图片存储的位置 + + File file = getPhotoDir(); + File photoFile = new File(file, System.currentTimeMillis() + "origin.png"); + Log.i(InfoFragment.class.getName(), "图片存储到" + photoFile.getAbsolutePath()); + // 隐式意图打开系统界面 --要求回传 + Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + // 存到什么位置 + intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile)); + intent.putExtra(Action.OPEN_CAMERA.name(), photoFile); + startActivityForResult(intent, Action.OPEN_CAMERA.ordinal()); + }) + .setPositiveButton(R.string.action_close, (dialog, which) -> dialog.dismiss()).show()); + } else { + headimg.setOnClickListener(v -> Toast.makeText(getContext(), R.string.not_permissions, Toast.LENGTH_LONG).show()); + } + }); + + } + + private File getPhotoDir() { + return new File(Environment.getExternalStorageDirectory(), + getString(R.string.app_name)); + } + + //打开裁剪应用 + private Intent getCropIntent() { + return new Intent("com.android.camera.action.CROP"); + } + + //判断是否有裁剪应用 + private boolean hasCrop() { + Context context = getContext(); + return context != null && getCropIntent().resolveActivity(getContext().getPackageManager()) != null; + } + + //设置头像 + private void setHeadImg(Bitmap bitmap) { + File picFile = new File(getPhotoDir(), System.currentTimeMillis() + ".png"); + try { + if (picFile.createNewFile()) { + bitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream( + picFile)); + Context context = Objects.requireNonNull(getContext()); + TextView textView = new TextView(context); + textView.setTextSize(18); + textView.setGravity(Gravity.CENTER | Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL); + textView.setText(R.string.upload_img); + AlertDialog alertDialog = new AlertDialog.Builder(context) + .setView(textView).show(); + uploadImgHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(@NonNull Message msg) { + alertDialog.dismiss(); + if (msg.what == Response.Result.OK.ordinal()) { + headimg.setImageBitmap(bitmap); + } + } + }; + viewModel.uploadImg(picFile); + } + } catch (IOException e) { + e.printStackTrace(); + Log.e(InfoFragment.class.getName(), e.toString()); + } + } + + // 手机自带裁剪功能--调用系统裁剪的意图 + private void crop(Uri uri) { + // 定义图片裁剪意图 + Intent intent = getCropIntent(); + + intent.setDataAndType(uri, "image/*"); + // 设置是否裁剪 + intent.putExtra("crop", "true"); + // 裁剪框的比例 + intent.putExtra("aspectX", 1); + intent.putExtra("aspectY", 1); + + // 设置输出图片的尺寸大小 + int size = getResources().getInteger(R.integer.photo_size); + intent.putExtra("outputX", size); + intent.putExtra("outputY", size); + + // 设置图片格式 + intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.name()); + //是否返回数据 + intent.putExtra("return-data", true); + + startActivityForResult(intent, Action.CROP.ordinal()); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + Log.i(InfoFragment.class.getName(), "requestCode:" + requestCode + ",resultCode:" + resultCode); + + if (data != null) { + //获取路径 + if (requestCode == Action.OPEN_GALLERY.ordinal() || requestCode == Action.OPEN_CAMERA.ordinal()) { + if (hasCrop()) { + crop(data.getData()); + } else { + Context context = getContext(); + if (context != null) { + try { + Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), data.getData()); + setHeadImg(bitmap); + } catch (IOException e) { + e.printStackTrace(); + Log.e(InfoFragment.class.getName(), e.toString()); + } + } else { + Log.e(InfoFragment.class.getName(), "无法获取Context"); + } + } + } else if (requestCode == Action.CROP.ordinal()) { + //直接拿到一张图片 + Bitmap bitmap = data.getParcelableExtra("data"); + if (bitmap != null) { + setHeadImg(bitmap); + } else { + Log.e(InfoFragment.class.getName(), "无法获取裁剪图片"); + } + } + } + + } + /** * 打开修改密码弹窗 */ @@ -245,21 +452,13 @@ public class InfoFragment extends BaseFragment { AlertDialog.Builder alert = new AlertDialog.Builder(Objects.requireNonNull(getContext())); final AlertDialog alertDialog = alert.setTitle(R.string.modify_password).setView(view) - .setNegativeButton(R.string.modify_password, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - viewModel.modifyPwd(oldPwd.getText().toString(), newPwd.getText().toString()); - dialog.dismiss(); - } - }) - .setNeutralButton(R.string.action_close, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } + .setNegativeButton(R.string.modify_password, (dialog, which) -> { + viewModel.modifyPwd(oldPwd.getText().toString(), newPwd.getText().toString()); + dialog.dismiss(); }) + .setNeutralButton(R.string.action_close, (dialog, which) -> dialog.dismiss()) .create(); - handler = new Handler(Looper.getMainLooper()) { + modifyPwdHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(@NonNull Message msg) { alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setEnabled(msg.getData().getBoolean(Param.enable.name())); @@ -276,13 +475,10 @@ public class InfoFragment extends BaseFragment { @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Event(value = R.id.logout) private void logout(final View view) { - new Thread(new Runnable() { - @Override - public void run() { - AppDatabase.getInstance(getContext()).tokenDao().delete(LocalToken.getTokenInstance()); - LocalToken.logout(); - startActivity(new Intent(view.getContext(), LoginActivity.class)); - } + new Thread(() -> { + AppDatabase.getInstance(getContext()).tokenDao().delete(LocalToken.getTokenInstance()); + LocalToken.logout(); + startActivity(new Intent(view.getContext(), LoginActivity.class)); }).start(); } diff --git a/app/src/main/java/com/community/pocket/ui/main/ui/info/InfoViewModel.java b/app/src/main/java/com/community/pocket/ui/main/ui/info/InfoViewModel.java index 62d67ab..dda35ca 100644 --- a/app/src/main/java/com/community/pocket/ui/main/ui/info/InfoViewModel.java +++ b/app/src/main/java/com/community/pocket/ui/main/ui/info/InfoViewModel.java @@ -1,5 +1,7 @@ package com.community.pocket.ui.main.ui.info; +import android.graphics.Bitmap; + import androidx.lifecycle.MutableLiveData; import com.community.pocket.R; @@ -7,6 +9,8 @@ import com.community.pocket.data.main.info.InfoRequest; import com.community.pocket.ui.main.ui.share.BaseViewModel; import com.community.pocket.util.ValidUtil; +import java.io.File; + //个人信息UI数据管理 public class InfoViewModel extends BaseViewModel { @@ -16,6 +20,12 @@ public class InfoViewModel extends BaseViewModel { //修改密码请求状态 private MutableLiveData modifyResponse = new MutableLiveData<>(); + //上传头像状态 + private MutableLiveData uploadImg = new MutableLiveData<>(); + + //获取头像 + private MutableLiveData getImg = new MutableLiveData<>(); + //个人信息请求状态 private MutableLiveData infoResponse = new MutableLiveData<>(); @@ -31,6 +41,14 @@ public class InfoViewModel extends BaseViewModel { return infoResponse; } + MutableLiveData getGetImg() { + return getImg; + } + + MutableLiveData getUploadImg() { + return uploadImg; + } + //修改密码表单校验状态 void modifyPwdChanged(String oldpwd, String newpwd, String confirmNewPwd) { if (!ValidUtil.passwordvalid(oldpwd)) { @@ -48,6 +66,11 @@ public class InfoViewModel extends BaseViewModel { } } + //上传头像 + void uploadImg(File picFile) { + getRequest().uploadImg(uploadImg, picFile); + } + //修改密码 void modifyPwd(String oldpwd, String newpwd) { getRequest().modifyPwd(modifyResponse, oldpwd, newpwd); @@ -58,6 +81,12 @@ public class InfoViewModel extends BaseViewModel { getRequest().loadInfo(infoResponse); } + //获取头像 + void getImg(String url) { + getRequest().getImg(getImg, url); + } + + @Override protected InfoRequest getRequest() { return InfoRequest.getInstance(); diff --git a/app/src/main/java/com/community/pocket/util/HttpFileResponse.java b/app/src/main/java/com/community/pocket/util/HttpFileResponse.java new file mode 100644 index 0000000..ebf9bc6 --- /dev/null +++ b/app/src/main/java/com/community/pocket/util/HttpFileResponse.java @@ -0,0 +1,52 @@ +package com.community.pocket.util; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.util.Log; + +import androidx.lifecycle.MutableLiveData; + +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Response; +import okhttp3.ResponseBody; + +public class HttpFileResponse implements Callback { + + private static final String header = "Content-Type"; + + private final MutableLiveData image; + + public HttpFileResponse(MutableLiveData image) { + this.image = image; + } + + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + e.printStackTrace(); + Log.e(HttpJSONResponse.class.getName(), e.toString()); + } + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) { + String contentType = response.header(header); + if ("image/png".equals(contentType)) { + ResponseBody responseBody = response.body(); + if (responseBody != null) { + Bitmap bitmap = BitmapFactory.decodeStream(responseBody.byteStream()); + image.postValue(bitmap); + } + } else { + onParseError(call, response, "接口不是响应图片数据,非法响应头" + header + "=" + contentType); + } + } + + private void onParseError(@NotNull Call call, @NotNull Response response, String err) { + Log.e(HttpJSONResponse.class.getName(), err); + throw new RuntimeException(err); + } +} diff --git a/app/src/main/java/com/community/pocket/util/HttpResponse.java b/app/src/main/java/com/community/pocket/util/HttpJSONResponse.java similarity index 82% rename from app/src/main/java/com/community/pocket/util/HttpResponse.java rename to app/src/main/java/com/community/pocket/util/HttpJSONResponse.java index 42171ab..4a62430 100644 --- a/app/src/main/java/com/community/pocket/util/HttpResponse.java +++ b/app/src/main/java/com/community/pocket/util/HttpJSONResponse.java @@ -19,7 +19,7 @@ import okhttp3.ResponseBody; * * @param 响应实体类型 */ -public class HttpResponse implements Callback { +public class HttpJSONResponse implements Callback { private Class tClass; @@ -27,7 +27,7 @@ public class HttpResponse tClass, HttpParse httpParse) { + public HttpJSONResponse(Class tClass, HttpParse httpParse) { this.tClass = tClass; this.httpParse = httpParse; } @@ -35,7 +35,7 @@ public class HttpResponse { + + private final int mRequestCode = 100;//权限请求码 + + private PermissionsUtils() { + } + + private static PermissionsUtils permissionsUtils; + private IPermissionsResult mPermissionsResult; + + public static PermissionsUtils getInstance() { + if (permissionsUtils == null) { + permissionsUtils = new PermissionsUtils(); + } + return permissionsUtils; + } + + public void checkPermissions(Activity context, String[] permissions, @NonNull IPermissionsResult permissionsResult) { + mPermissionsResult = permissionsResult; + + if (Build.VERSION.SDK_INT < 23) {//6.0才用动态权限 + permissionsResult.passPermissons(); + return; + } + + //创建一个mPermissionList,逐个判断哪些权限未授予,未授予的权限存储到mPerrrmissionList中 + List mPermissionList = new ArrayList<>(); + //逐个判断你要的权限是否已经通过 + for (String permission : permissions) { + if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { + mPermissionList.add(permission);//添加还未授予的权限 + } + } + + //申请权限 + if (mPermissionList.size() > 0) {//有权限没有通过,需要申请 + ActivityCompat.requestPermissions(context, permissions, mRequestCode); + } else { +//说明权限都已经通过,可以做你想做的事情去 + permissionsResult.passPermissons(); + } + } + + //请求权限后回调的方法 + //参数: requestCode 是我们自己定义的权限请求码 + //参数: permissions 是我们请求的权限名称数组 + //参数: grantResults 是我们在弹出页面后是否允许权限的标识数组,数组的长度对应的是权限名称数组的长度,数组的数据0表示允许权限,-1表示我们点击了禁止权限 + + public void onRequestPermissionsResult(Activity context, int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + boolean hasPermissionDismiss = false;//有权限没有通过 + if (mRequestCode == requestCode) { + for (int grantResult : grantResults) { + if (grantResult == -1) { + hasPermissionDismiss = true; + break; + } + } + //如果有权限没有被允许 + if (hasPermissionDismiss) { + if (context.getResources().getBoolean(R.bool.showSystemSetting)) { + showSystemPermissionsSettingDialog(context);//跳转到系统设置权限页面,或者直接关闭页面,不让他继续访问 + } else { + mPermissionsResult.forbitPermissons(); + } + } else { + //全部权限通过,可以进行下一步操作。。。 + mPermissionsResult.passPermissons(); + } + } + + } + + /** + * 不再提示权限时的展示对话框 + */ + private AlertDialog mPermissionDialog; + + private void showSystemPermissionsSettingDialog(final Activity context) { + final String mPackName = context.getPackageName(); + if (mPermissionDialog == null) { + mPermissionDialog = new AlertDialog.Builder(context) + .setMessage("已禁用权限,请手动授予") + .setPositiveButton("设置", (dialog, which) -> { + cancelPermissionDialog(); + + Uri packageURI = Uri.parse("package:" + mPackName); + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI); + context.startActivity(intent); + context.finish(); + }) + .setNegativeButton("取消", (dialog, which) -> { + //关闭页面或者做其他操作 + cancelPermissionDialog(); + //mContext.finish(); + mPermissionsResult.forbitPermissons(); + }) + .create(); + } + mPermissionDialog.show(); + } + + //关闭对话框 + private void cancelPermissionDialog() { + if (mPermissionDialog != null) { + mPermissionDialog.cancel(); + mPermissionDialog = null; + } + + } + + + public interface IPermissionsResult { + void passPermissons(); + + void forbitPermissons(); + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/community/pocket/util/SimpleHttpParse.java b/app/src/main/java/com/community/pocket/util/SimpleHttpParse.java index 632f434..f9f652f 100644 --- a/app/src/main/java/com/community/pocket/util/SimpleHttpParse.java +++ b/app/src/main/java/com/community/pocket/util/SimpleHttpParse.java @@ -20,8 +20,8 @@ public class SimpleHttpParse getInterface(Class tClass) { - return new HttpResponse<>(tClass, this); + public HttpJSONResponse getInterface(Class tClass) { + return new HttpJSONResponse<>(tClass, this); } @Override diff --git a/app/src/main/res/layout/main/layout/info/layout/info_fragment.xml b/app/src/main/res/layout/main/layout/info/layout/info_fragment.xml index a40ea0c..88c3ddb 100644 --- a/app/src/main/res/layout/main/layout/info/layout/info_fragment.xml +++ b/app/src/main/res/layout/main/layout/info/layout/info_fragment.xml @@ -50,6 +50,17 @@ android:textSize="24sp" app:layout_constraintStart_toEndOf="@id/headimg" app:layout_constraintTop_toBottomOf="@id/nickname" /> + + + android:gravity="center" + android:textSize="18sp" /> + android:gravity="center" + android:textSize="18sp" /> + android:text="@string/mobie" + android:textSize="18sp" /> + android:gravity="center" + android:textSize="18sp" /> + android:text="@string/email" + android:textSize="18sp" /> + android:gravity="center" + android:textSize="18sp" /> load more forum OK no more data load more data OK + open photo album + take photo + unselected any photo + not permissions + click to set headimg + upload img.... \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 822d8f6..825c465 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -230,4 +230,10 @@ 成功加载更多帖子 没有更多数据 成功加载更多数据 + 打开相册 + 拍照上传 + 没有选中任何照片 + 你当前没有文件读写权限执行此操作 + 点击上方设置头像 + 上传头像中。。。。 \ No newline at end of file diff --git a/app/src/main/res/values/boolean.xml b/app/src/main/res/values/boolean.xml new file mode 100644 index 0000000..b1763ef --- /dev/null +++ b/app/src/main/res/values/boolean.xml @@ -0,0 +1,4 @@ + + + true + \ No newline at end of file diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml index b4fe0cb..acd0802 100644 --- a/app/src/main/res/values/integers.xml +++ b/app/src/main/res/values/integers.xml @@ -2,4 +2,5 @@ 200 10 + 100 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7bf1072..65cef66 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -231,6 +231,12 @@ load more forum OK no more data load more data OK + open photo album + take photo + unselected any photo + not permissions + click to set headimg + upload img....