充电桩app代码

EditQuestionTwoActivity.java 31KB

    package com.electric.chargingpile.activity; import android.Manifest; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.ViewTreeObserver; import android.view.animation.AnimationUtils; import android.view.inputmethod.InputMethodManager; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.electric.chargingpile.R; import com.electric.chargingpile.application.MainApplication; import com.electric.chargingpile.engine.GlideEngine; import com.electric.chargingpile.util.AndroidBug5497Workaround; import com.electric.chargingpile.util.BarColorUtil; import com.electric.chargingpile.util.FileUtils; import com.electric.chargingpile.util.ImageUitl; import com.electric.chargingpile.util.JsonUtils; import com.electric.chargingpile.util.ScreenUtils; import com.electric.chargingpile.util.StringUtils; import com.electric.chargingpile.util.ToastUtil; import com.electric.chargingpile.util.Util; import com.electric.chargingpile.view.CarTypeDialog; import com.electric.chargingpile.view.xrichtext.RichTextEditor; import com.electric.chargingpile.view.xrichtext.SDCardUtil; import com.luck.picture.lib.PictureSelector; import com.luck.picture.lib.animators.AnimationType; import com.luck.picture.lib.config.PictureConfig; import com.luck.picture.lib.config.PictureMimeType; import com.luck.picture.lib.entity.LocalMedia; import com.umeng.analytics.MobclickAgent; import com.zhy.http.okhttp.OkHttpUtils; import com.zhy.http.okhttp.callback.StringCallback; import java.io.ByteArrayOutputStream; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import okhttp3.Call; import pub.devrel.easypermissions.AfterPermissionGranted; import pub.devrel.easypermissions.EasyPermissions; import top.zibin.luban.Luban; import top.zibin.luban.OnCompressListener; import static com.electric.chargingpile.activity.EditAnswerActivity.dpToPx; public class EditQuestionTwoActivity extends AppCompatActivity implements View.OnClickListener, EasyPermissions.PermissionCallbacks { private static final String TAG = "EditQuestionTwoActivity"; private TextView tv_submit, tv_back, tv_point; private RichTextEditor et_new_content; private InputMethodManager imm; private ProgressDialog loadingDialog; private ProgressDialog insertDialog; private ProgressDialog uploadDialog; private RelativeLayout rl_bottom; private ImageView iv_edit_down, iv_edit_pic; private String creat_id, title; private String c_path = "", u_path = ""; private Map<String, String> map = new HashMap<>(); private RelativeLayout rl_root, rl_point; private LinearLayout ll; public static android.view.animation.Animation animation; private static final int RC_ALBUM_PERM = 123; public static final int REQUEST_CODE_CHOOSE = 339; private Bitmap insertBitmap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit_question_two); BarColorUtil.initStatusBarColor(EditQuestionTwoActivity.this); AndroidBug5497Workaround.assistActivity(this); creatId(); getIntentData(); initViews(); initLintener(); if (!MainApplication.q_content.equals("")) { et_new_content.post(new Runnable() { @Override public void run() { //showEditData(myContent); et_new_content.clearAllLayout(); showDataSync(MainApplication.q_content); } }); } if (!MainApplication.q_map.isEmpty()) { map.putAll(MainApplication.q_map); } MobclickAgent.onEvent(getApplicationContext(), "0079"); } private void getIntentData() { title = getIntent().getStringExtra("question"); } private void initViews() { ll = (LinearLayout) findViewById(R.id.ll); imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); rl_point = (RelativeLayout) findViewById(R.id.rl_point); tv_point = (TextView) findViewById(R.id.tv_point); animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.nn); tv_submit = (TextView) findViewById(R.id.tv_submit); tv_back = (TextView) findViewById(R.id.tv_back); et_new_content = (RichTextEditor) findViewById(R.id.et_new_content); insertDialog = new ProgressDialog(this); insertDialog.setMessage("正在插入图片..."); insertDialog.setCanceledOnTouchOutside(false); loadingDialog = new ProgressDialog(this); loadingDialog.setMessage("图片解析中..."); loadingDialog.setCanceledOnTouchOutside(false); uploadDialog = new ProgressDialog(this); uploadDialog.setMessage("正在提交..."); uploadDialog.setCanceledOnTouchOutside(false); rl_bottom = (RelativeLayout) findViewById(R.id.rl_bottom); rl_root = (RelativeLayout) findViewById(R.id.rl_root); iv_edit_down = (ImageView) findViewById(R.id.iv_edit_down); iv_edit_pic = (ImageView) findViewById(R.id.iv_edit_pic); } private void initLintener() { tv_back.setOnClickListener(this); tv_submit.setOnClickListener(this); iv_edit_pic.setOnClickListener(this); iv_edit_down.setOnClickListener(this); rl_root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = rl_root.getRootView().getHeight() - rl_root.getHeight(); if (heightDiff > dpToPx(EditQuestionTwoActivity.this, 150)) { // if more than 200 dp, it's probably a keyboard... rl_bottom.setVisibility(View.VISIBLE); } else { rl_bottom.setVisibility(View.GONE); } } }); } /** * 异步方式显示数据 * * @param html */ private void showDataSync(final String html) { loadingDialog.show(); Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> subscriber) throws Exception { showEditData(subscriber, html); } }) .subscribeOn(Schedulers.io())//生产事件在io .observeOn(AndroidSchedulers.mainThread())//消费事件在UI线程 .subscribe(new Observer<String>() { @Override public void onComplete() { loadingDialog.dismiss(); getEditData(); } @Override public void onError(Throwable e) { loadingDialog.dismiss(); } @Override public void onSubscribe(Disposable d) { } @Override public void onNext(String text) { if (text.contains(SDCardUtil.getPictureDir())) { et_new_content.addImageViewAtIndex(et_new_content.getLastIndex(), text); } else { et_new_content.addEditTextAtIndex(et_new_content.getLastIndex(), text); } } }); } /** * 显示数据 */ protected void showEditData(ObservableEmitter<String> subscriber, String html) { try { List<String> textList = StringUtils.cutStringByImgTag(html); for (int i = 0; i < textList.size(); i++) { String text = textList.get(i); Log.e(TAG, "showEditData: " + text); if (text.contains("<cdz img")) { String imagePath = StringUtils.getImgSrc(text); Log.e(TAG, "showEditData: imagePath= " + imagePath); if (new File(imagePath).exists()) { subscriber.onNext(imagePath); } else { ToastUtil.showToast(getApplicationContext(), "图片" + i + "已丢失,请重新插入!", Toast.LENGTH_SHORT); } } else { subscriber.onNext(text); } } subscriber.onComplete(); } catch (Exception e) { e.printStackTrace(); subscriber.onError(e); } } private int getPicNum() { int num = 0; List<RichTextEditor.EditData> editList = et_new_content.buildEditData(); for (int i = 0; i < editList.size(); i++) { if (null != editList.get(i).imagePath) { num++; } } return num; } private int getTextNum() { int num = 0; List<RichTextEditor.EditData> editList = et_new_content.buildEditData(); for (int i = 0; i < editList.size(); i++) { if (null != editList.get(i).inputStr) { num = num + editList.get(i).inputStr.length(); } } return num; } /** * 负责处理编辑数据提交等事宜,请自行实现 */ private String getEditData() { List<RichTextEditor.EditData> editList = et_new_content.buildEditData(); StringBuffer content = new StringBuffer(); StringBuffer contentt = new StringBuffer(); for (RichTextEditor.EditData itemData : editList) { if (itemData.inputStr != null) { content.append(itemData.inputStr); contentt.append(itemData.inputStr); } else if (itemData.imagePath != null) { Bitmap bitmap = BitmapFactory.decodeFile(itemData.imagePath); int width = bitmap.getWidth(); int height = bitmap.getHeight(); Iterator keys = map.keySet().iterator(); while (keys.hasNext()) { String key = (String) keys.next(); if (itemData.imagePath.equals(key)) { content.append("<cdz img src=\"").append(map.get(itemData.imagePath)).append("\" width=" + "\"" + width + "\"" + " height=" + "\"" + height + "\" /cdz>"); contentt.append("<cdz img src=\"").append(itemData.imagePath).append("\" width=" + "\"" + width + "\"" + " height=" + "\"" + height + "\" /cdz>"); } } } } MainApplication.q_content = contentt.toString(); MainApplication.q_map.putAll(map); Log.e(TAG, "getEditData_content: " + content.toString()); Log.e(TAG, "getEditData_contentt: " + contentt.toString()); return content.toString(); } private Bitmap imageZoom(Bitmap bm) { // 图片允许最大空间 单位:KB double maxSize = 200.00; // 将bitmap放至数组中,意在bitmap的大小(与实际读取的原文件要大) ByteArrayOutputStream baos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); byte[] b = baos.toByteArray(); // 将字节换成KB double mid = b.length / 1024; // 判断bitmap占用空间是否大于允许最大空间 如果大于则压缩 小于则不压缩 if (mid > maxSize) { // 获取bitmap大小 是允许最大大小的多少倍 double i = mid / maxSize; // 开始压缩 此处用到平方根 将宽带和高度压缩掉对应的平方根倍 // (1.保持刻度和高度和原bitmap比率一致,压缩后也达到了最大大小占用空间的大小) bm = zoomImage(bm, bm.getWidth() / Math.sqrt(i), bm.getHeight() / Math.sqrt(i)); } return bm; } public Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) { // 获取这个图片的宽和高 float width = bgimage.getWidth(); float height = bgimage.getHeight(); // 创建操作图片用的matrix对象 Matrix matrix = new Matrix(); // 计算宽高缩放率 float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // 缩放图片动作 matrix.postScale(scaleWidth, scaleHeight); Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width, (int) height, matrix, true); // iv_2.setImageBitmap(bitmap); // tv_2.setText(bitmap.getRowBytes() * bitmap.getHeight() + ""); return bitmap; } /** * 异步方式插入图片 * * @param data */ private void insertImagesSync(final Intent data) { insertDialog.show(); Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> subscriber) throws Exception { try { et_new_content.measure(0, 0); List<LocalMedia> selectionData= PictureSelector.obtainMultipleResult(data); if (selectionData!=null && selectionData.size()>0) { LocalMedia media = selectionData.get(0); /*List<Uri> uriList = Matisse.obtainResult(data); Uri uri = uriList.get(0); Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri)); File file = FileUtils.from(EditQuestionTwoActivity.this, uri); bitmap = FileUtils.rotateIfRequired(file, bitmap); bitmap = imageZoom(bitmap); insertBitmap = bitmap;*/ String path=""; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ path= media.getAndroidQToPath(); }else{ path=media.getPath(); } insertBitmap = imageZoom(BitmapFactory.decodeFile(path)); u_path = path; subscriber.onNext(u_path); subscriber.onComplete(); }else{ subscriber.onError(new Exception()); } } catch (Exception e) { e.printStackTrace(); subscriber.onError(e); } } }) .subscribeOn(Schedulers.io())//生产事件在io .observeOn(AndroidSchedulers.mainThread())//消费事件在UI线程 .subscribe(new Observer<String>() { @Override public void onComplete() { insertDialog.dismiss(); // compressAndUpload(c_path, u_path); uploadPic(insertBitmap, u_path); } @Override public void onError(Throwable e) { insertDialog.dismiss(); Log.e(TAG, "onError: " + "图片插入失败:" + e.getMessage()); ToastUtil.showToast(getApplicationContext(), "图片插入失败", Toast.LENGTH_SHORT); } @Override public void onSubscribe(Disposable d) { } @Override public void onNext(String imagePath) { et_new_content.insertImage(imagePath, et_new_content.getMeasuredWidth()); } }); } private void compressAndUpload(String path, final String u_path) { loadingDialog.show(); Log.e(TAG, "compressAndUpload: path= " + path); File file = new File(path); Log.e(TAG, "compressAndUpload: length= " + file.length() / 1024 + "kb"); Luban.with(EditQuestionTwoActivity.this).load(file).setCompressListener(new OnCompressListener() { @Override public void onStart() { } @Override public void onSuccess(File file) { Log.e(TAG, "onSuccess: path= " + file.getPath()); Log.e(TAG, "onSuccess: length= " + file.length() / 1024 + "kb"); uploadPic(file.getPath(), u_path); } @Override public void onError(Throwable e) { Log.e(TAG, "onError: " + e.getMessage()); } }).launch(); } private void uploadPic(String picPath, final String path) { Log.e(TAG, "uploadPic: path= " + picPath); Log.e(TAG, "uploadPic: length= " + new File(picPath).length() / 1024 + "kb"); Bitmap bitmap = BitmapFactory.decodeFile(picPath); // Log.e(TAG, "uploadPic: bit= "+bitmap.ge()/1024+"kb" ); String url = MainApplication.url + "/zhannew/basic/web/index.php/fileupload/uploadone"; OkHttpUtils.post().url(url).addParams("file", ImageUitl.bitmapToString(picPath)).addParams("filename", "android.jpg").addParams("id", creat_id) .build().execute(new StringCallback() { @Override public void onError(Call call, Exception e) { } @Override public void onResponse(String response) { loadingDialog.dismiss(); Log.e(TAG, "onResponse: " + response); String rtnCode = JsonUtils.getKeyResult(response, "rtnCode"); if ("01".equals(rtnCode)) { String fileUrl = JsonUtils.getKeyResult(response, "fileUrl"); map.put(path, fileUrl); et_new_content.addEditTextAtIndex(et_new_content.getLastIndex(), " "); ToastUtil.showToast(getApplicationContext(), "图片插入成功", Toast.LENGTH_SHORT); // Log.e(TAG, "onResponse: map的key="+path+"的value="+map.get(path) ); } else { ToastUtil.showToast(getApplicationContext(), "图片插入失败", Toast.LENGTH_SHORT); } } }); } private void uploadPic(Bitmap bitmap, final String path) { String url = MainApplication.url + "/zhannew/basic/web/index.php/fileupload/uploadone"; OkHttpUtils.post().url(url). addParams("file", FileUtils.bitmapToString(bitmap)). addParams("filename", "android.jpg"). addParams("id", creat_id) .build().execute(new StringCallback() { @Override public void onError(Call call, Exception e) { e.printStackTrace(); } @Override public void onResponse(String response) { loadingDialog.dismiss(); String rtnCode = JsonUtils.getKeyResult(response, "rtnCode"); if ("01".equals(rtnCode)) { String fileUrl = JsonUtils.getKeyResult(response, "fileUrl"); map.put(path, fileUrl); et_new_content.addEditTextAtIndex(et_new_content.getLastIndex(), " "); ToastUtil.showToast(getApplicationContext(), "图片插入成功", Toast.LENGTH_SHORT); } else { ToastUtil.showToast(getApplicationContext(), "图片插入失败", Toast.LENGTH_SHORT); } } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.tv_submit: if (imm.isActive()) { imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } int text_num = getTextNum(); if (text_num <= 5000) { uploadQuestion(); // ToastUtil.showToast(getApplicationContext(),text_num+"",Toast.LENGTH_SHORT); } else { ToastUtil.showToast(getApplicationContext(), "提问最多只能输入5000字" + ",当前字数为" + text_num, Toast.LENGTH_SHORT); } break; case R.id.tv_back: if (imm.isActive()) { imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } getEditData(); finish(); break; case R.id.iv_edit_pic: int num = getPicNum(); Log.e(TAG, "onClick: num=" + num); if (num >= 10) { ToastUtil.showToast(getApplicationContext(), "提问最多只能添加10张图片", Toast.LENGTH_SHORT); } else { permissionTask(); } break; case R.id.iv_edit_down: if (imm.isActive()) { imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } break; } } /** * 调用图库选择 */ private void callGallery() { // Matisse.from(EditQuestionTwoActivity.this) // .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF)) // .showSingleMediaType(true) // .countable(true) // .maxSelectable(1) // .capture(true) // .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider")) // .imageEngine(new GlideEngine()) // .forResult(REQUEST_CODE_CHOOSE); PictureSelector.create(this) .openGallery(PictureMimeType.ofImage()) .maxSelectNum(1) .selectionMode(PictureConfig.SINGLE) .isSingleDirectReturn(true) .isCompress(true)//是否压缩 .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验 .isGif(true)//是否显示gif .isAndroidQTransform(true) .imageEngine(GlideEngine.createGlideEngine()) .isWeChatStyle(false)// 是否开启微信图片选择风格 .isUseCustomCamera(false)// 是否使用自定义相机 .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启 .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题 .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果 .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果 .imageSpanCount(4)// 每行显示个数 .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回 .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部 .forResult(REQUEST_CODE_CHOOSE); } @Override protected void onActivityResult(int requestCode, int resultCode, final Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { if (data != null) { if (requestCode == 1) { //处理调用系统图库 } else if (requestCode == REQUEST_CODE_CHOOSE) { //异步方式插入图片 insertImagesSync(data); } } } } private void creatId() { String url = MainApplication.url + "/zhannew/basic/web/index.php/question/createid"; OkHttpUtils.post().url(url).addParams("phone", MainApplication.userPhone).addParams("password", MainApplication.userPassword).build().connTimeOut(6000).readTimeOut(6000).execute(new StringCallback() { @Override public void onError(Call call, Exception e) { ToastUtil.showToast(getApplicationContext(), "请检查当前网络", Toast.LENGTH_SHORT); } @Override public void onResponse(String response) { // Log.e(TAG, "onResponse: id"+response ); String rtnCode = JsonUtils.getKeyResult(response, "rtnCode"); if ("01".equals(rtnCode)) { String rtnMsg = JsonUtils.getKeyResult(response, "rtnMsg"); creat_id = rtnMsg; } } }); } private void uploadQuestion() { uploadDialog.show(); String description = getEditData(); Map<String, String> map = new HashMap<>(); map.put("id", creat_id); map.put("phone", MainApplication.userPhone); map.put("password", MainApplication.userPassword); map.put("title", title); map.put("description", description); String url = MainApplication.url + "/zhannew/basic/web/index.php/question/question"; try { OkHttpUtils.post().url(url).params(map).build().connTimeOut(6000).readTimeOut(6000).execute(new StringCallback() { @Override public void onError(Call call, Exception e) { uploadDialog.dismiss(); ToastUtil.showToast(getApplicationContext(), "请检查当前网络", Toast.LENGTH_SHORT); } @Override public void onResponse(String response) { // Log.e(TAG, "onResponse: "+response ); uploadDialog.dismiss(); String rtnCode = JsonUtils.getKeyResult(response, "rtnCode"); String rtnMsg = JsonUtils.getKeyResult(response, "rtnMsg"); if ("01".equals(rtnCode)) { // ToastUtil.showToast(getApplicationContext(),rtnMsg,Toast.LENGTH_SHORT); EditQuestionOneActivity.activity.finish(); MainApplication.q_content = ""; MainApplication.q_map.clear(); QaActivity.isRefresh = true; String plusScore = JsonUtils.getKeyResult(rtnMsg, "plusScore"); if ("0".equals(plusScore)) { ToastUtil.showToast(getApplicationContext(), "提问成功", Toast.LENGTH_SHORT); // if (MainApplication.userCar.equals("") || MainApplication.userCar.equals("nullnull") || MainApplication.userCar.equals("&&") // || MainApplication.userCar.equals("null&&null")) { // new CarTypeDialog(EditQuestionTwoActivity.this, EditQuestionTwoActivity.this).builder().setCancelable(false).show(new View.OnClickListener() { // @Override // public void onClick(View v) { // startActivity(new Intent(getApplicationContext(), UserInfoActivity.class)); // finish(); // } // }); // } else { finish(); // } } else { ll.setVisibility(View.VISIBLE); tv_point.setText(plusScore); rl_point.setVisibility(View.VISIBLE); rl_point.startAnimation(animation); new Handler().postDelayed(new Runnable() { public void run() { rl_point.setVisibility(View.GONE); } }, 1000); new Handler().postDelayed(new Runnable() { @Override public void run() { // if (MainApplication.userCar.equals("") || MainApplication.userCar.equals("nullnull") || MainApplication.userCar.equals("&&") // || MainApplication.userCar.equals("null&&null")) { // new CarTypeDialog(EditQuestionTwoActivity.this, EditQuestionTwoActivity.this).builder().setCancelable(false).show(new View.OnClickListener() { // @Override // public void onClick(View v) { // startActivity(new Intent(getApplicationContext(), UserInfoActivity.class)); // finish(); // } // }); // } else { finish(); } // } }, 1500); } } else { ToastUtil.showToast(getApplicationContext(), rtnMsg, Toast.LENGTH_SHORT); } } }); } catch (NullPointerException e) { e.printStackTrace(); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { getEditData(); finish(); return true; } return super.onKeyDown(keyCode, event); } @Override protected void onPause() { super.onPause(); MobclickAgent.onPause(this); } @Override protected void onResume() { super.onResume(); MobclickAgent.onResume(this); } @Override public void onPermissionsGranted(int requestCode, List<String> perms) { } @Override public void onPermissionsDenied(int requestCode, List<String> perms) { } @AfterPermissionGranted(RC_ALBUM_PERM) public void permissionTask() { if (isPermissionOK()) { callGallery(); } else { EasyPermissions.requestPermissions( this, "充电桩想要获取您的图片读取权限,是否允许?", RC_ALBUM_PERM, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA ); } } private boolean isPermissionOK() { return EasyPermissions.hasPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA ); } }