仿微信使用者反饋功能實現
現在的專案要增加一個使用者反饋功能,由於是臨時提出的需求也沒有UI設計,就想到參照微信的設計來實現。
先看微信的效果:
在web端實現的,開始也想過做在web端這樣更靈活,但目前的架構還是傳統的純native應用,這麼搞太麻煩,估計要搗鼓一段時間,還是就用android端實現。
功能分析
使用者點選新增圖片按鈕後在手機圖片庫中選擇照片,選定後展示出來,最多選擇4張,水平排列,一行不夠排兩行,就想到GridView結合startActivityForResult+ 執行緒池來實現。因為是上傳圖片,最好轉變為webp格式,再加上畫素壓縮處理,可以大大的節省使用者流量。
流程:
輸入文字->startActivityForResult選擇照片->onActivityResult中更新GridView->點選提交->彈出等待提示框->建立檔案List,文字儲存為txt格式,從GridView中取出圖片儲存為webp格式->執行緒池上傳檔案->上傳結束關閉等待提示框。
功能實現
想起來簡單做起來的時候才發現很多問題,上傳圖片時想彈出一個含旋轉動畫的等待提示框(繼承DialogFragment),每個執行緒執行完後得到執行結果,根據結果設定等待提示框的文字,採用ExecutorService.submit() + future.get()實現時發現一個奇怪的現象:從點選提交到上傳結束沒有看到等待提示框,後來一步步排查問題發現,ExecutorService.submit()之後就會進入future.get(),get()方法會阻塞UI執行緒,導致無法彈出提示框;當執行緒池結束才回到UI執行緒,此時會先處理之前的任務(彈出等待提示框),但由於執行緒池結束又呼叫了DialogFragment的dissmiss()方法,等待提示框很快出現又很快消失了。
好吧,由於沒有搞懂執行緒池浪費了大把時間,程式碼也白寫了,但也讓我對執行緒池加深了認識,這一特性大概幾年都不會忘了,於是又重新考慮實現方式。
最終的實現方式是自定義一個執行緒池,用一個迴圈執行Runnable。
自定義執行緒池:
class MyThreadPool extends ThreadPoolExecutor {
private List<File> fileList;
private MyThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, List<File> files) {
super (corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
fileList = files;
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
}
@Override
protected void terminated() {
super.terminated();
//當呼叫shutDown()或者shutDownNow()時會觸發該方法,關掉等待框
waitingDialog.dismissAllowingStateLoss();
for (File file:fileList){
deleteOldLogcatFile(getApplicationContext(), file.getName());
}
//必須用looper才能線上程中用toast
Looper.prepare();
if (uploadSucc){
Toast.makeText(getApplicationContext(), "上傳完成", Toast.LENGTH_LONG).show();
} else{
Toast.makeText(getApplicationContext(), "上傳失敗!", Toast.LENGTH_LONG).show();
}
Looper.loop();
}
}
自定義的好處是線上程池結束後可以自定義提示資訊,在terminated()中刪除了舊檔案,並根據每個執行緒結果提示上傳成功還是失敗。
呼叫自定義執行緒
MyThreadPool myThreadPool = new MyThreadPool(2, 4, 1,
TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(fileCount), files);
for (int i = 0; i < fileCount; i++) {
final File file = files.get(i);
Runnable runnable = new Runnable(){
@Override
public void run() {
int ret = ftpUpload(ftpUrl, fptPort, ftpUserName, ftpPassword, ftpRemotePath, path, file.getName());
ECMLog.i_ui(CLASS_TAG, "ftpUpload ret: " + ret);
uploadSucc = ret == FTP_UPLOAD_SUCC;
}
};
myThreadPool.execute(runnable);
}
myThreadPool.shutdown();
還有個效果是點選選擇好的圖片後放大顯示圖片,圖片下方有個刪除圖示能刪除圖片,這也是通過startActivityForResult實現,在onActivityResult中刪除GridView中對應圖片。
圖片處理
startActivityForResult要用兩次,一次是新增圖片,一次是點選已新增的圖片然後重新啟動一個activity顯示圖片,在這個activity中能刪除已選擇的圖片。
圖片的壓縮處理:onActivityResult拿到圖片uri,根據uri得到路徑,通過路徑加上畫素壓縮演算法得到bitmap,再呼叫bitmap.compress()得到webp格式的圖片檔案。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_ADD_PIC) {
Uri uri = data.getData();
String picPath = Utils.getFilePathFromUri(getApplicationContext(), uri);
if (picPath == null){
ContentResolver cr = this.getContentResolver();
try {
mBitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}else {
mBitmap = Utils.getSmallBitmap(picPath, 480, 800);
}
//加到第一個
mGridViewUris.add(0, uri);
mGridViewDatas.add(0, mBitmap);
mGridViewAdapter=new GridViewAdapter(getApplication(), mGridViewDatas, MAX_UPLOAD_PIC);
mGridView.setAdapter(mGridViewAdapter);
mGridViewAdapter.notifyDataSetChanged();
}else if (resultCode == RESULT_OK && requestCode == REQUEST_SHOW_PIC){
int position = data.getIntExtra(PIC_POSITION, 0);
mGridViewDatas.remove(position);
mGridViewUris.remove(position);
mGridViewAdapter=new GridViewAdapter(getApplication(), mGridViewDatas, MAX_UPLOAD_PIC);
mGridView.setAdapter(mGridViewAdapter);
mGridViewAdapter.notifyDataSetChanged();
}
//包含新增圖片
int totalPictures = mGridViewDatas.size();
currentPicTV.setText(String.valueOf(totalPictures - 1));
}
public static String getFilePathFromUri(final Context context, final Uri uri) {
// final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] { split[1] };
return getDataColumn(context, contentUri, selection, selectionArgs);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
}
return null;
}
//根據路徑獲得圖片並壓縮,返回bitmap用於顯示
public static Bitmap getSmallBitmap(String filePath, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
// options.inSampleSize = calculateInSampleSize(options, 480, 800);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
//計算圖片的縮放值
private static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
通過以上方式,一個截圖檔案原始大小300KB,被壓縮到10KB。
下面是完整程式碼
自定義GridView介面卡:
package com.cetcs.ecmapplication.innerclass;
import android.app.Application;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.cetcs.ecmapplication.R;
import com.cetcs.ecmcommon.ECMLog;
import com.cetcs.ecmcommon.GlobalData;
import java.util.List;
public class GridViewAdapter extends BaseAdapter {
private String CLASS_TAG = getClass().getCanonicalName();
private List<Bitmap> mList;
LayoutInflater mLayoutInflater;
private ImageView mImageView;
private Application mAppllication;
private int mSize;
public GridViewAdapter(Application application, List<Bitmap> list, int size){
mAppllication = application;
mList = list;
mLayoutInflater = LayoutInflater.from(application);
mSize = size;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ECMLog.i_ui(CLASS_TAG, "position: " + position + " mList size: " + mList.size());
convertView = mLayoutInflater.inflate(R.layout.gridviewlayout, null);
mImageView = (ImageView) convertView.findViewById(R.id.ItemImage);
mImageView.setImageBitmap(mList.get(position));
GlobalData globalData = (GlobalData) mAppllication;
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mImageView.getLayoutParams();
layoutParams.height = 240 * globalData.mScreenHeight / 1920;
layoutParams.width = 240 * globalData.mScreenWidth / 1080;
mImageView.setLayoutParams(layoutParams);
return convertView;
}
}
gridviewlayout.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:paddingBottom="4dip" android:layout_width="fill_parent">
<ImageView
android:layout_height="wrap_content"
android:id="@+id/ItemImage"
android:layout_width="wrap_content"
android:layout_centerHorizontal="true">
</ImageView>
</RelativeLayout>
activity的layout
activity_feedback.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:RoundCornerTextView="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_feedback"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:background="#f0f0f0"
tools:context="com.cetcs.ecmapplication.FeedbackActivity">
<TextView
android:id="@+id/titleTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="反饋和意見"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
/>
<RelativeLayout
android:id="@+id/textviewLayout"
android:layout_below="@id/titleTV"
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="wrap_content">
<EditText
android:id="@+id/feedbackET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請填寫10個以上的問題描述"
android:background="@color/white"
android:paddingStart="10dp"
android:paddingEnd="10dp" />
<TextView
android:id="@+id/allowedTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="10dp"
android:text="/200"/>
<TextView
android:id="@+id/currentNumberTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toStartOf="@id/allowedTV"
android:text="0"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/pictureLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:layout_below="@id/textviewLayout">
<TextView
android:id="@+id/pictureTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textColor="@color/black"
android:text="圖片(問題截圖,選填)"/>
<TextView
android:id="@+id/allowedPicTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginEnd="10dp"
android:text="/4"/>
<TextView
android:id="@+id/currentPicTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toStartOf="@id/allowedPicTV"
android:text="0"/>
<GridView
android:id="@+id/gridview"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/pictureTV"
android:numColumns="3"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:columnWidth="90dp"
android:stretchMode="columnWidth"
android:gravity="center">
</GridView>
</RelativeLayout>
<TextView
android:id="@+id/telTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/pictureLayout"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:text="聯絡電話"
android:layout_marginStart="10dp"
/>
<EditText
android:id="@+id/telET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/telTV"
android:background="@color/white"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:hint="選填"/>
<!--自定義控制元件,圓角button-->
<acxingyun.cetcs.com.roundconertextview.RoundConerTextView
android:id="@+id/submitBT"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
RoundCornerTextView:Text="@string/tijiao"
RoundCornerTextView:BackgroundColor="@color/roundconerunpressed"
RoundCornerTextView:ConerRadius="5dp"
RoundCornerTextView:TextColor="@android:color/white"
RoundCornerTextView:pressedColor="@color/finish_pressed"
RoundCornerTextView:unPressedColor="@color/finish_unpressed"
/>
</RelativeLayout>
FeedbackActivity
package com.cetcs.ecmapplication;
import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.cetcs.ecmapplication.dialog.WaitingDialog;
import com.cetcs.ecmapplication.innerclass.GridViewAdapter;
import com.cetcs.ecmcommon.ECMActivity;
import com.cetcs.ecmcommon.ECMLog;
import com.cetcs.ecmcommon.GlobalData;
import com.cetcs.ecmcommon.Utils;
import com.cetcs.jniencardmanager.JniCardLoginedInfo;
import com.cetcs.jniencardmanager.JniCardUnloginInfo;
import com.cetcs.jniencardmanager.JniEnCardManager;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import acxingyun.cetcs.com.roundconertextview.RoundConerTextView;
import static android.util.TypedValue.COMPLEX_UNIT_PX;
import static com.cetcs.ecmcommon.Constants.FTP_UPLOAD_SUCC;
import static com.cetcs.logreport.LogcatUploaderUtils.appendStringToFile;
import static com.cetcs.logreport.LogcatUploaderUtils.deleteOldLogcatFile;
import static com.cetcs.logreport.LogcatUploaderUtils.ftpUpload;
import static com.cetcs.logreport.LogcatUploaderUtils.writeStringToFile;
public class FeedbackActivity extends ECMActivity {
private final String CLASS_TAG = this.getClass().getSimpleName();
private RelativeLayout textviewLayout;
private RelativeLayout pictureLayout;
private EditText telET;
private TextView currentPicTV;
private RoundConerTextView submitBT;
private EditText feedbackET;
private TextWatcher watcher;
private TextView currentNumberTV;
private List<Bitmap> mGridViewDatas;
private List<Uri> mGridViewUris;
private GridView mGridView;
private GridViewAdapter mGridViewAdapter;
private Bitmap mBitmap;
private static int REQUEST_ADD_PIC = 1;
private static int REQUEST_SHOW_PIC = 2;
private static int MAX_UPLOAD_PIC = 4;
private static String SHOW_PIC_URI = "show_pic_full_screen";
private static String PIC_POSITION = "picture_position";
private WaitingDialog waitingDialog;
private static final String ftpUrl = xxxxx.xxxxx.xxxxx;
private static final String fptPort = xxxx;
private static final String ftpUserName = xxxx;
private static final String ftpPassword = xxxx;
private static final String ftpRemotePath = "/aaa/bbb";
private boolean uploadSucc = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//取消標題欄
setContentView(R.layout.activity_feedback);
initViews();
initLayoutParameters();
}
private void initViews(){
textviewLayout = (RelativeLayout) findViewById(R.id.textviewLayout);
pictureLayout = (RelativeLayout) findViewById(R.id.pictureLayout);
telET = (EditText) findViewById(R.id.telET);
submitBT = (RoundConerTextView) findViewById(R.id.submitBT);
feedbackET = (EditText) findViewById(R.id.feedbackET);
currentNumberTV = (TextView) findViewById(R.id.currentNumberTV);
//監控輸入字數
watcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
int len = feedbackET.getText().length();
ECMLog.i_ui(CLASS_TAG, "onTextChanged len:" + len);
if (len >= 200){
currentNumberTV.setText(String.valueOf(len));
currentNumberTV.setTextColor(getResources().getColor(R.color.deep_orange));
}else {
currentNumberTV.setTextColor(getResources().getColor(R.color.black));
currentNumberTV.setText(String.valueOf(len));
}
}
};
feedbackET.addTextChangedListener(watcher);
mGridView=(GridView) findViewById(R.id.gridview);
mGridViewDatas = new ArrayList<>();
mGridViewUris = new ArrayList<>();
Bitmap addBitmap = Utils.getInstance().readBitmap(getApplicationContext(), R.drawable.add_pic);
mGridViewDatas.add(0, addBitmap);
mGridViewUris.add(0, new Uri.Builder().build());
mGridViewAdapter = new GridViewAdapter(getApplication(), mGridViewDatas, MAX_UPLOAD_PIC);
mGridView.setAdapter(mGridViewAdapter);
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int pictureNumber = mGridViewDatas.size();
ECMLog.i_ui(CLASS_TAG,"position: " + position + " pictureNumber: " + pictureNumber);
if (position == pictureNumber - 1){
if (pictureNumber < MAX_UPLOAD_PIC + 1){
chosePictureFromPhone();
}
}else {
Uri uri = mGridViewUris.get(position);
Intent intent = new Intent(FeedbackActivity.this, PicShowerActivity.class);
intent.putExtra(SHOW_PIC_URI, uri.toString());
intent.putExtra(PIC_POSITION, position);
startActivityForResult(intent, REQUEST_SHOW_PIC);
}
}
});
submitBT.setOnTouchCallback(new RoundConerTextView.onTouchCallback() {
@Override
public void onRoundTextViewTouched() {
if (feedbackET.getText().length() == 0){
Toast.makeText(getApplicationContext(), "請輸入您的建議", Toast.LENGTH_SHORT).show();
return;
}
if (feedbackET.getText().length() > 200){
Toast.makeText(getApplicationContext(), "請輸入200字以內建議", Toast.LENGTH_SHORT).show();
return;
}
waitingDialog = new WaitingDialog();
waitingDialog.setCancelable(false);
waitingDialog.show(getFragmentManager(), getString(R.string.zhengzaishangchaunqingshaohou));
List<File> list = creatFilesThread();
if (list == null){
waitingDialog.dismissAllowingStateLoss();
Toast.makeText(getApplicationContext(), "網路不可用!", Toast.LENGTH_SHORT).show();
return;
}
ExecutorServiceThread(list);
}
});
}
private void initLayoutParameters(){
GlobalData globalDate = (GlobalData) getApplication();
RelativeLayout.LayoutParams layoutparam = (RelativeLayout.LayoutParams) textviewLayout.getLayoutParams();
layoutparam.height = 350 * globalDate.mScreenHeight / 1920;
textviewLayout.setLayoutParams(layoutparam);
//反饋和意見
TextView titleTV = (TextView) findViewById(R.id.titleTV);
titleTV.setTextSize(COMPLEX_UNIT_PX, 40 * globalDate.mScreenHeight / 1920);
//反饋文字
feedbackET = (EditText) findViewById(R.id.feedbackET);
feedbackET.setTextSize(COMPLEX_UNIT_PX, 50 * globalDate.mScreenHeight / 1920);
//200
TextView allowedTV = (TextView) findViewById(R.id.allowedTV);
allowedTV.setTextSize(COMPLEX_UNIT_PX, 40 * globalDate.mScreenHeight / 1920);
//字數
TextView currentNumberTV = (TextView) findViewById(R.id.currentNumberTV);
currentNumberTV.setTextSize(COMPLEX_UNIT_PX, 40 * globalDate.mScreenHeight / 1920);
layoutparam = (RelativeLayout.LayoutParams) pictureLayout.getLayoutParams();
layoutparam.height = 430 * globalDate.mScreenHeight / 1920;
layoutparam.topMargin = 60 * globalDate.mScreenHeight / 1920;
pictureLayout.setLayoutParams(layoutparam);
TextView pictureTV = (TextView) findViewById(R.id.pictureTV);
pictureTV.setTextSize(COMPLEX_UNIT_PX, 46 * globalDate.mScreenHeight / 1920);
TextView allowedPicTV = (TextView) findViewById(R.id.allowedPicTV);
allowedPicTV.setTextSize(COMPLEX_UNIT_PX, 40 * globalDate.mScreenHeight / 1920);
currentPicTV = (TextView) findViewById(R.id.currentPicTV);
currentPicTV.setTextSize(COMPLEX_UNIT_PX, 40 * globalDate.mScreenHeight / 1920);
TextView telTV = (TextView) findViewById(R.id.telTV);
telTV.setTextSize(COMPLEX_UNIT_PX, 40 * globalDate.mScreenHeight / 1920);
telET = (EditText) findViewById(R.id.telET);
telET.setTextSize(COMPLEX_UNIT_PX, 50 * globalDate.mScreenHeight / 1920);
layoutparam = (RelativeLayout.LayoutParams) telET.getLayoutParams();
layoutparam.height = 128 * globalDate.mScreenHeight / 1920;
telET.setLayoutParams(layoutparam);
if (globalDate.getChannelName().equals("westone")){
submitBT.setBackgroundColor(getResources().getColor(R.color.westonewanchengzhengchang));
submitBT.setPressedColor(getResources().getColor(R.color.westonewanchengdianji));
submitBT.setUnPressedColor(getResources().getColor(R.color.westonewanchengzhengchang));
}
submitBT.setWidth(990 * globalDate.mScreenWidth / 1080);
submitBT.setHeight(135 * globalDate.mScreenHeight / 1920);
submitBT.setTextSize(60 * globalDate.mScreenHeight / 1920);
submitBT.invalidate();
}
private void chosePictureFromPhone(){
Intent intent = new Intent();
/* 開啟Pictures畫面Type設定為image */
intent.setType("image/*");
/* 使用Intent.ACTION_GET_CONTENT這個Action */
intent.setAction(Intent.ACTION_GET_CONTENT);
/* 取得相片後返回本畫面 */
startActivityForResult(intent, REQUEST_ADD_PIC);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_ADD_PIC) {
Uri uri = data.getData();
String picPath = Utils.getFilePathFromUri(getApplicationContext(), uri);
if (picPath == null){
ContentResolver cr = this.getContentResolver();
try {
mBitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}else {
mBitmap = Utils.getSmallBitmap(picPath, 480, 800);
}
//加到第一個
mGridViewUris.add(0, uri);
mGridViewDatas.add(0, mBitmap);
mGridViewAdapter=new GridViewAdapter(getApplication(), mGridViewDatas, MAX_UPLOAD_PIC);
mGridView.setAdapter(mGridViewAdapter);
mGridViewAdapter.notifyDataSetChanged();
}else if (resultCode == RESULT_OK && requestCode == REQUEST_SHOW_PIC){
int position = data.getIntExtra(PIC_POSITION, 0);
mGridViewDatas.remove(position);
mGridViewUris.remove(position);
mGridViewAdapter=new GridViewAdapter(getApplication(), mGridViewDatas, MAX_UPLOAD_PIC);
mGridView.setAdapter(mGridViewAdapter);
mGridViewAdapter.notifyDataSetChanged();
}
//包含新增圖片
int totalPictures = mGridViewDatas.size();
currentPicTV.setText(String.valueOf(totalPictures - 1));
}
private List<File> creatUploadFiles(){
//包含文字、圖片
List<File> fileList = new ArrayList<>();
File suggestFile = creatSuggestionFile();
if (suggestFile != null){
String tel = telET.getText().toString();
if (tel.length() > 0){
tel = "\n" + "tel:" + tel;
appendStringToFile(getApplicationContext(), suggestFile.getName(), tel);
}
fileList.add(suggestFile);
}
//不包括新增圖片
int picCount = mGridViewDatas.size() - 1;
for (int i = 0;i < picCount;i++){
//phoneNumber_tfNumber_20170101010101_1
String bitmapFileName = getFileName() + "_" + i + ".webp";
Bitmap bitmap = mGridViewDatas.get(i);
File bitmapFile = saveBitmapToFile(bitmap, bitmapFileName);
fileList.add(bitmapFile);
}
return fileList;
}
/**
* phoneNumber_tfNumber_time
* 沒有後綴
* @return
*/
private String getFileName(){
String fileName;
String phoneNumber = "";
String tfNumber = "";
String time = "";
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault());
time = sdf.format(new Date());
..............
fileName = phoneNumber +"_" + tfNumber +"_" + time;
return fileName;
}
private File creatSuggestionFile(){
String fileName;
fileName = getFileName() + ".txt";
String path = getApplicationContext().getFilesDir().getAbsolutePath();
File file = new File(path, fileName);
//儲存String為檔案
writeStringToFile(getApplication(), feedbackET.getText().toString(), file.getName());
return file;
}
private File saveBitmapToFile(Bitmap bitmap, String fileName){
String path = getApplicationContext().getFilesDir().getAbsolutePath();
File file = new File(path, fileName);
if(file.exists()){
file.delete();
}
FileOutputStream out;
try{
out = new FileOutputStream(file);
if(bitmap.compress(Bitmap.CompressFormat.WEBP, 50, out))
{
out.flush();
out.close();
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
private List<File> creatFilesThread(){
List<File> fileList = null;
ExecutorService cacheThreadExecutor = Executors.newSingleThreadExecutor();
Future<List<File>> future = cacheThreadExecutor.submit(new preUploadTask());
try {
fileList = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return fileList;
}
private void ExecutorServiceThread(List<File> files) {
final String path = getApplicationContext().getFilesDir().getAbsolutePath();
int fileCount = files.size();
MyThreadPool myThreadPool = new MyThreadPool(2, 4, 1,
TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(fileCount), files);
for (int i = 0; i < fileCount; i++) {
final File file = files.get(i);
Runnable runnable = new Runnable(){
@Override
public void run() {
int ret = ftpUpload(ftpUrl, fptPort, ftpUserName, ftpPassword, ftpRemotePath, path, file.getName());
ECMLog.i_ui(CLASS_TAG, "ftpUpload ret: " + ret);
uploadSucc = ret == FTP_UPLOAD_SUCC;
}
};