* 重写 父类的方法 onTick() 、 onFinish()
*/
public class MyCountDownTimer extends CountDownTimer {
private EaseVoiceRecorderCallback recorderCallback;
private View view;
private MotionEvent event;
public MyCountDownTimer(long millisInFuture, long countDownInterval, View view, EaseVoiceRecorderCallback recorderCallback, MotionEvent event) {
super(millisInFuture, countDownInterval);
this.recorderCallback = recorderCallback;
this.view = view;
this.event = event;
}
@Override
public void onFinish() {
duration = 60;
Log.d("onFinish--->", "onFinish");
view.setPressed(false);
if (event.getY() < 0) {
// discard the recorded audio.
discardRecording();
} else {
// stop recording and send voice file
try {
int length = stopRecoding();
if (length > 0) {
if (recorderCallback != null) {
recorderCallback.onVoiceRecordComplete(getVoiceFilePath(), length);
}
} else if (length == 401) {
Toast.makeText(context, R.string.Recording_without_permission, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, R.string.The_recording_time_is_too_short, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, R.string.send_failure_please, Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void onTick(long millisUntilFinished) {
// Log.d("millisUntilFinished--->",millisUntilFinished+"");
if (millisUntilFinished / 1000 < 11) {
duration = (int) (millisUntilFinished / 1000);
recordingHint.setText("还可以录音" + millisUntilFinished / 1000 + "秒");
}
}
}
public interface EaseVoiceRecorderCallback {
/**
* on voice record complete
*
* @param voiceFilePath 录音完毕后的文件路径
* @param voiceTimeLength 录音时长
*/
void onVoiceRecordComplete(String voiceFilePath, int voiceTimeLength);
}
public void startRecording() {
if (!CommonUtils.isSdcardExist()) {
Toast.makeText(context, R.string.Send_voice_need_sdcard_support, Toast.LENGTH_SHORT).show();
return;
}
try {
wakeLock.acquire();
this.setVisibility(View.VISIBLE);
recordingHint.setText(context.getString(R.string.move_up_to_cancel));
recordingHint.setBackgroundColor(Color.TRANSPARENT);
voiceRecorder.startRecording(context);
} catch (Exception e) {
e.printStackTrace();
if (wakeLock.isHeld())
wakeLock.release();
if (voiceRecorder != null)
voiceRecorder.discardRecording();
this.setVisibility(View.INVISIBLE);
Toast.makeText(context, R.string.recoding_fail, Toast.LENGTH_SHORT).show();
return;
}
}
public void showReleaseToCancelHint() {
recordingHint.setText(context.getString(R.string.release_to_cancel));
recordingHint.setBackgroundResource(R.drawable.recording_text_hint_bg);
}
public void showMoveUpToCancelHint() {
recordingHint.setText(context.getString(R.string.move_up_to_cancel));
recordingHint.setBackgroundColor(Color.TRANSPARENT);
}
public void discardRecording() {
if (wakeLock.isHeld())
wakeLock.release();
try {
// stop recording
if (voiceRecorder.isRecording()) {
voiceRecorder.discardRecording();
this.setVisibility(View.INVISIBLE);
}
} catch (Exception e) {
}
}
public int stopRecoding() {
this.setVisibility(View.INVISIBLE);
if (wakeLock.isHeld())
wakeLock.release();
return voiceRecorder.stopRecoding();
}
public String getVoiceFilePath() {
return voiceRecorder.getVoiceFilePath();
}
public String getVoiceFileName() {
return voiceRecorder.getVoiceFileName();
}
public boolean isRecording() {
return voiceRecorder.isRecording();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/DefaultEmojiconDatas.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.emoji;
import com.htmessage.yichatopen.R;
public class DefaultEmojiconDatas {
private static String[] emojis = new String[]{
SmileUtils.ee_1,
SmileUtils.ee_2,
SmileUtils.ee_3,
SmileUtils.ee_4,
SmileUtils.ee_5,
SmileUtils.ee_6,
SmileUtils.ee_7,
SmileUtils.ee_8,
SmileUtils.ee_9,
SmileUtils.ee_10,
SmileUtils.ee_11,
SmileUtils.ee_12,
SmileUtils.ee_13,
SmileUtils.ee_14,
SmileUtils.ee_15,
SmileUtils.ee_16,
SmileUtils.ee_17,
SmileUtils.ee_18,
SmileUtils.ee_19,
SmileUtils.ee_20,
SmileUtils.ee_21,
SmileUtils.ee_22,
SmileUtils.ee_23,
SmileUtils.ee_24,
SmileUtils.ee_25,
SmileUtils.ee_26,
SmileUtils.ee_27,
SmileUtils.ee_28,
SmileUtils.ee_29,
SmileUtils.ee_30,
SmileUtils.ee_31,
SmileUtils.ee_32,
SmileUtils.ee_33,
SmileUtils.ee_34,
SmileUtils.ee_35,
};
private static int[] icons = new int[]{
R.drawable.ee_0,
R.drawable.ee_1,
R.drawable.ee_2,
R.drawable.ee_3,
R.drawable.ee_4,
R.drawable.ee_5,
R.drawable.ee_6,
R.drawable.ee_7,
R.drawable.ee_8,
R.drawable.ee_9,
R.drawable.ee_10,
R.drawable.ee_11,
R.drawable.ee_12,
R.drawable.ee_13,
R.drawable.ee_14,
R.drawable.ee_15,
R.drawable.ee_16,
R.drawable.ee_17,
R.drawable.ee_18,
R.drawable.ee_19,
R.drawable.ee_20,
R.drawable.ee_21,
R.drawable.ee_22,
R.drawable.ee_23,
R.drawable.ee_24,
R.drawable.ee_25,
R.drawable.ee_26,
R.drawable.ee_27,
R.drawable.ee_28,
R.drawable.ee_29,
R.drawable.ee_30,
R.drawable.ee_31,
R.drawable.ee_32,
R.drawable.ee_33,
R.drawable.ee_34,
};
private static final Emojicon[] DATA = createData();
private static Emojicon[] createData(){
Emojicon[] datas = new Emojicon[icons.length];
for(int i = 0; i < icons.length; i++){
datas[i] = new Emojicon(icons[i], emojis[i], Emojicon.Type.NORMAL);
}
return datas;
}
public static Emojicon[] getData(){
return DATA;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/EmojiFragment.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.emoji;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ImageButton;
import com.htmessage.yichatopen.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by huangfangyi on 2017/7/5.
* qq 84543217
*/
public class EmojiFragment extends Fragment {
private ViewPager viewPager;
private TabLayout tableLayout;
private List views;
private List emojicons;
private int emojiconColumns = 7;
private int emojiconRows = 3;
private OnEmojiListener onEmojiListener;
public EmojiFragment(List emojicons, int emojiconColumns, int emojiconRows, OnEmojiListener onEmojiListener) {
this.emojicons = emojicons;
this.emojiconColumns = emojiconColumns;
this.emojiconRows = emojiconRows;
this.onEmojiListener=onEmojiListener;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_emoji, container,false);
viewPager = (ViewPager) root.findViewById(R.id.viewpager_emoji);
tableLayout = (TabLayout) root.findViewById(R.id.tabLayout_dot);
return root;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final List views= getViews();
viewPager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return views.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public Object instantiateItem(ViewGroup arg0, int arg1) {
((ViewPager) arg0).addView(views.get(arg1));
return views.get(arg1);
}
@Override
public void destroyItem(ViewGroup arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView(views.get(arg1));
}
});
tableLayout.setupWithViewPager(viewPager);
TabLayout.Tab[] tabs = new TabLayout.Tab[views.size()];
for (int i = 0; i < views.size(); i++) {
tabs[i] = tableLayout.getTabAt(i);
ImageButton imageView=new ImageButton(getContext());
imageView.setBackground(null);
imageView.setImageResource(R.drawable.dot_emoji);
tabs[i].setCustomView(imageView);
}
}
private List getViews() {
int itemSize = emojiconColumns * emojiconRows -1;
int totalSize = emojicons.size();
Emojicon.Type emojiType = Emojicon.Type.NORMAL ;
if(totalSize!=0){
emojiType=emojicons.get(0).getType();
}
if(emojiType == Emojicon.Type.BIG_EXPRESSION){
itemSize = emojiconColumns * emojiconRows;
}
int pageSize = totalSize % itemSize == 0 ? totalSize/itemSize : totalSize/itemSize + 1;
List views = new ArrayList();
for(int i = 0; i < pageSize; i++){
View view = View.inflate(getContext(), R.layout.emoji_gridview, null);
GridView gv = (GridView) view.findViewById(R.id.gridview);
gv.setNumColumns(emojiconColumns);
List list = new ArrayList();
if(i != pageSize -1){
list.addAll(emojicons.subList(i * itemSize, (i+1) * itemSize));
}else{
list.addAll(emojicons.subList(i * itemSize, totalSize));
}
if(emojiType != Emojicon.Type.BIG_EXPRESSION){
Emojicon deleteIcon = new Emojicon();
deleteIcon.setEmojiText(SmileUtils.DELETE_KEY);
list.add(deleteIcon);
}
final EmojiconGridAdapter gridAdapter = new EmojiconGridAdapter(getContext(), 1, list, emojiType);
gv.setAdapter(gridAdapter);
gv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
Emojicon emojicon = gridAdapter.getItem(position);
if(onEmojiListener != null){
String emojiText = emojicon.getEmojiText();
if(emojiText != null && emojiText.equals(SmileUtils.DELETE_KEY)){
onEmojiListener.onDeleteImageClicked();
}else{
onEmojiListener.onExpressionClicked(emojicon);
}
}
}
});
views.add(view);
}
return views;
}
public interface OnEmojiListener{
void onDeleteImageClicked();
void onExpressionClicked(Emojicon emojicon);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/Emojicon.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.emoji;
public class Emojicon {
public Emojicon(){
}
/**
* constructor
* @param icon- resource id of the icon
* @param emojiText- text of emoji icon
*/
public Emojicon(int icon, String emojiText){
this.icon = icon;
this.emojiText = emojiText;
this.type = Type.NORMAL;
}
/**
* constructor
* @param icon - resource id of the icon
* @param emojiText - text of emoji icon
* @param type - normal or big
*/
public Emojicon(int icon, String emojiText, Type type){
this.icon = icon;
this.emojiText = emojiText;
this.type = type;
}
/**
* identity code
*/
private String identityCode;
/**
* static icon resource id
*/
private int icon;
/**
* dynamic icon resource id
*/
private int bigIcon;
/**
* text of emoji, could be null for big icon
*/
private String emojiText;
/**
* name of emoji icon
*/
private String name;
/**
* normal or big
*/
private Type type;
/**
* path of icon
*/
private String iconPath;
/**
* path of big icon
*/
private String bigIconPath;
/**
* get the resource id of the icon
* @return
*/
public int getIcon() {
return icon;
}
/**
* set the resource id of the icon
* @param icon
*/
public void setIcon(int icon) {
this.icon = icon;
}
/**
* get the resource id of the big icon
* @return
*/
public int getBigIcon() {
return bigIcon;
}
/**
* set the resource id of the big icon
* @return
*/
public void setBigIcon(int dynamicIcon) {
this.bigIcon = dynamicIcon;
}
/**
* get text of emoji icon
* @return
*/
public String getEmojiText() {
return emojiText;
}
/**
* set text of emoji icon
* @param emojiText
*/
public void setEmojiText(String emojiText) {
this.emojiText = emojiText;
}
/**
* get name of emoji icon
* @return
*/
public String getName() {
return name;
}
/**
* set name of emoji icon
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* get type
* @return
*/
public Type getType() {
return type;
}
/**
* set type
* @param type
*/
public void setType(Type type) {
this.type = type;
}
/**
* get icon path
* @return
*/
public String getIconPath() {
return iconPath;
}
/**
* set icon path
* @param iconPath
*/
public void setIconPath(String iconPath) {
this.iconPath = iconPath;
}
/**
* get path of big icon
* @return
*/
public String getBigIconPath() {
return bigIconPath;
}
/**
* set path of big icon
* @param bigIconPath
*/
public void setBigIconPath(String bigIconPath) {
this.bigIconPath = bigIconPath;
}
/**
* get identity code
* @return
*/
public String getIdentityCode() {
return identityCode;
}
/**
* set identity code
* @param
*/
public void setIdentityCode(String identityCode) {
this.identityCode = identityCode;
}
public static final String newEmojiText(int codePoint) {
if (Character.charCount(codePoint) == 1) {
return String.valueOf(codePoint);
} else {
return new String(Character.toChars(codePoint));
}
}
public enum Type{
/**
* normal icon, can be input one or more in edit view
*/
NORMAL,
/**
* big icon, send out directly when your press it
*/
BIG_EXPRESSION
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/EmojiconGridAdapter.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.emoji;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.htmessage.yichatopen.R;
import java.util.List;
public class EmojiconGridAdapter extends ArrayAdapter{
private Emojicon.Type emojiconType;
public EmojiconGridAdapter(Context context, int textViewResourceId, List objects, Emojicon.Type emojiconType) {
super(context, textViewResourceId, objects);
this.emojiconType = emojiconType;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
if(emojiconType == Emojicon.Type.BIG_EXPRESSION){
convertView = View.inflate(getContext(), R.layout.row_big_expression, null);
}else{
convertView = View.inflate(getContext(), R.layout.row_expression, null);
}
}
ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_expression);
Emojicon emojicon = getItem(position);
//if you want show a name for the icons, you can set text to R.id.tv_name
if(SmileUtils.DELETE_KEY.equals(emojicon.getEmojiText())){
imageView.setImageResource(R.drawable.delete_expression);
}else{
if(emojicon.getIcon() != 0){
imageView.setImageResource(emojicon.getIcon());
}else if(emojicon.getIconPath() != null){
Glide.with(getContext()).load(emojicon.getIconPath()).placeholder(R.drawable.default_expression).into(imageView);
}
}
return convertView;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/SmileUtils.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.activity.chat.weight.emoji;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spannable;
import android.text.Spannable.Factory;
import android.text.style.ImageSpan;
import com.htmessage.yichatopen.R;
public class SmileUtils {
public static final String DELETE_KEY = "em_delete_delete_expression";
public static final String ee_1 = "[):]";
public static final String ee_2 = "[:D]";
public static final String ee_3 = "[;)]";
public static final String ee_4 = "[:-o]";
public static final String ee_5 = "[:p]";
public static final String ee_6 = "[(H)]";
public static final String ee_7 = "[:@]";
public static final String ee_8 = "[:s]";
public static final String ee_9 = "[:$]";
public static final String ee_10 = "[:(]";
public static final String ee_11 = "[:-(]";
public static final String ee_12 = "[:|]";
public static final String ee_13 = "[(a)]";
public static final String ee_14 = "[8o|]";
public static final String ee_15 = "[8-|]";
public static final String ee_16 = "[+o(]";
public static final String ee_17 = "[ emoticons = new HashMap();
static {
Emojicon[] emojicons = DefaultEmojiconDatas.getData();
for(int i = 0; i < emojicons.length; i++){
addPattern(emojicons[i].getEmojiText(), emojicons[i].getIcon());
}
}
/**
* add text and icon to the map
* @param emojiText-- text of emoji
* @param icon -- resource id or local path
*/
public static void addPattern(String emojiText, Object icon){
emoticons.put(Pattern.compile(Pattern.quote(emojiText)), icon);
}
/**
* replace existing spannable with smiles
* @param context
* @param spannable
* @return
*/
public static boolean addSmiles(Context context, Spannable spannable) {
boolean hasChanges = false;
for (Entry entry : emoticons.entrySet()) {
Matcher matcher = entry.getKey().matcher(spannable);
while (matcher.find()) {
boolean set = true;
for (ImageSpan span : spannable.getSpans(matcher.start(),
matcher.end(), ImageSpan.class))
if (spannable.getSpanStart(span) >= matcher.start()
&& spannable.getSpanEnd(span) <= matcher.end())
spannable.removeSpan(span);
else {
set = false;
break;
}
if (set) {
hasChanges = true;
Object value = entry.getValue();
if(value instanceof String && !((String) value).startsWith("http")){
File file = new File((String) value);
if(!file.exists() || file.isDirectory()){
return false;
}
ImageSpan imageSpan=new ImageSpan(context, Uri.fromFile(file));
Drawable drawable=imageSpan.getDrawable();
drawable.setBounds(0,0,25,25);
imageSpan=new ImageSpan(drawable);
spannable.setSpan(imageSpan,
matcher.start(), matcher.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}else{
ImageSpan imageSpan=new ImageSpan(context, (Integer)value);
Drawable drawable=imageSpan.getDrawable();
int size=context.getResources().getDimensionPixelSize(R.dimen.emoji_size);
drawable.setBounds(0,0,size ,size);
imageSpan=new ImageSpan(drawable);
spannable.setSpan(imageSpan,
matcher.start(), matcher.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(imageSpan,
matcher.start(), matcher.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
}
return hasChanges;
}
public static Spannable getSmiledText(Context context, CharSequence text) {
Spannable spannable = spannableFactory.newSpannable(text);
addSmiles(context, spannable);
return spannable;
}
public static boolean containsKey(String key){
boolean b = false;
for (Entry entry : emoticons.entrySet()) {
Matcher matcher = entry.getKey().matcher(key);
if (matcher.find()) {
b = true;
break;
}
}
return b;
}
public static int getSmilesSize(){
return emoticons.size();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/DensityUtil.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.loadmore;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.ScrollView;
import android.widget.TextView;
import java.lang.reflect.Field;
public class DensityUtil {
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static float getScreenDensity(Context context) {
return context.getResources().getDisplayMetrics().density;
}
public static int getStatusBarHeight(Context ctx) {
Class> c = null;
Object obj = null;
Field field = null;
int x = 0, sbar = 0;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
sbar = ctx.getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
e1.printStackTrace();
}
return sbar;
}
public static int getScreenHeightWithoutTitlebar(Context ctx) {
int[] screenWidthAndHeight = getScreenWidthAndHeight(ctx);
return screenWidthAndHeight[1] -getStatusBarHeight(ctx)- dip2px(ctx, 48);
}
public static int[] getScreenWidthAndHeight(Context ctx) {
WindowManager mWm = (WindowManager) ctx
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
// 获取屏幕信息
mWm.getDefaultDisplay().getMetrics(dm);
int screenWidth = dm.widthPixels;
int screenHeigh = dm.heightPixels;
return new int[] { screenWidth, screenHeigh };
}
public static void addOnSoftKeyBoardVisibleListener(final Activity activity, final ScrollView scrollView) {
final View decorView = activity.getWindow().getDecorView();
decorView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect rect = new Rect();
decorView.getWindowVisibleDisplayFrame(rect);
int displayHight = rect.bottom - rect.top;
int hight = decorView.getHeight();
boolean visible = (double) displayHight / hight < 0.8;// 决断键盘是弹�?
System.out.println("===监听" + visible);
if (visible) {
Handler mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// scrollView
// .fullScroll(ScrollView.FOCUS_DOWN);// ScrollView滚动到底
scrollView.scrollTo(0, DensityUtil.dip2px(activity, 167));
}
}, 50);
}
}
});
}
public static String getEllipsisedText(TextView textView) {
try {
String text = textView.getText().toString();
int lines = textView.getLineCount();
int width = textView.getWidth();
int len = text.length();
Log.d("Test", "text-->" + text + "; lines-->" + lines + "; width-->" + width + ";len-->" + len);
TextUtils.TruncateAt where = TextUtils.TruncateAt.END;
TextPaint paint = textView.getPaint();
StringBuffer result = new StringBuffer();
int spos = 0, cnt, tmp, hasLines = 0;
while(hasLines < lines - 1) {
cnt = paint.breakText(text, spos, len, true, width, null);
if(cnt >= len - spos) {
result.append(text.substring(spos));
break;
}
tmp = text.lastIndexOf('\n', spos + cnt - 1);
if(tmp >= 0 && tmp < spos + cnt) {
result.append(text.substring(spos, tmp + 1));
spos += tmp + 1;
}
else {
tmp = text.lastIndexOf(' ', spos + cnt - 1);
if(tmp >= spos) {
result.append(text.substring(spos, tmp + 1));
spos += tmp + 1;
}
else {
result.append(text.substring(spos, cnt));
spos += cnt;
}
}
hasLines++;
}
if(spos < len) {
result.append(TextUtils.ellipsize(text.subSequence(spos, len), paint, (float) width, where));
}
return result.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/Pacman.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.loadmore;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.animation.LinearInterpolator;
import java.util.ArrayList;
import java.util.List;
/**
* Created by caizhiming on 2016/2/5.
*/
public class Pacman extends ProgressViewController {
private float translateX;
private int alpha;
private float degrees1,degrees2;
@Override
public void draw(Canvas canvas, Paint paint) {
drawPacman(canvas,paint);
drawCircle(canvas,paint);
}
private void drawPacman(Canvas canvas, Paint paint){
float x=getWidth()/2;
float y=getHeight()/2;
canvas.save();
canvas.translate(x, y);
canvas.rotate(degrees1);
paint.setAlpha(255);
RectF rectF1=new RectF(-x/1.7f,-y/1.7f,x/1.7f,y/1.7f);
canvas.drawArc(rectF1, 0, 270, true, paint);
canvas.restore();
canvas.save();
canvas.translate(x, y);
canvas.rotate(degrees2);
paint.setAlpha(255);
RectF rectF2=new RectF(-x/1.7f,-y/1.7f,x/1.7f,y/1.7f);
canvas.drawArc(rectF2,90,270,true,paint);
canvas.restore();
}
private void drawCircle(Canvas canvas, Paint paint) {
float radius=getWidth()/11;
paint.setAlpha(alpha);
canvas.drawCircle(translateX, getHeight() / 2, radius, paint);
}
@Override
public List createAnimation() {
List animators=new ArrayList<>();
float startT=getWidth()/11;
ValueAnimator translationAnim= ValueAnimator.ofFloat(getWidth()-startT,getWidth()/2);
translationAnim.setDuration(650);
translationAnim.setInterpolator(new LinearInterpolator());
translationAnim.setRepeatCount(-1);
translationAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
translateX = (float) animation.getAnimatedValue();
postInvalidate();
}
});
translationAnim.start();
ValueAnimator alphaAnim= ValueAnimator.ofInt(255,122);
alphaAnim.setDuration(650);
alphaAnim.setRepeatCount(-1);
alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
alpha = (int) animation.getAnimatedValue();
postInvalidate();
}
});
alphaAnim.start();
ValueAnimator rotateAnim1= ValueAnimator.ofFloat(0, 45, 0);
rotateAnim1.setDuration(650);
rotateAnim1.setRepeatCount(-1);
rotateAnim1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
degrees1 = (float) animation.getAnimatedValue();
postInvalidate();
}
});
rotateAnim1.start();
ValueAnimator rotateAnim2= ValueAnimator.ofFloat(0,-45,0);
rotateAnim2.setDuration(650);
rotateAnim2.setRepeatCount(-1);
rotateAnim2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
degrees2 = (float) animation.getAnimatedValue();
postInvalidate();
}
});
rotateAnim2.start();
animators.add(translationAnim);
animators.add(alphaAnim);
animators.add(rotateAnim1);
animators.add(rotateAnim2);
return animators;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/ProgressView.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.loadmore;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by caizhiming on 2016/2/5.
*/
public class ProgressView extends View {
public static final int DEFAULT_SIZE=25;//dp
int mStyleColor;
Paint mPaint;
ProgressViewController mIndicatorController;
private boolean mHasAnimation;
public ProgressView(Context context) {
super(context);
init(null, 0);
}
public ProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public ProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ProgressView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs, defStyleAttr);
}
private void init(AttributeSet attrs, int defStyle) {
mStyleColor = Color.WHITE;
mPaint=new Paint();
mPaint.setColor(mStyleColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
applyIndicator();
}
public void setStyleColor(int color){
mStyleColor = color;
mPaint.setColor(mStyleColor);
this.invalidate();
}
private void applyIndicator(){
mIndicatorController=new Pacman();
mIndicatorController.setTarget(this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureDimension(dp2px(DEFAULT_SIZE), widthMeasureSpec);
int height = measureDimension(dp2px(DEFAULT_SIZE), heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureDimension(int defaultSize,int measureSpec){
int result = defaultSize;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(defaultSize, specSize);
} else {
result = defaultSize;
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawIndicator(canvas);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (!mHasAnimation){
mHasAnimation=true;
applyAnimation();
}
}
@Override
public void setVisibility(int v) {
if (getVisibility() != v) {
super.setVisibility(v);
if (v == GONE || v == INVISIBLE) {
mIndicatorController.setAnimationStatus(ProgressViewController.AnimStatus.END);
} else {
mIndicatorController.setAnimationStatus(ProgressViewController.AnimStatus.START);
}
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mIndicatorController.setAnimationStatus(ProgressViewController.AnimStatus.CANCEL);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mIndicatorController.setAnimationStatus(ProgressViewController.AnimStatus.START);
}
void drawIndicator(Canvas canvas){
mIndicatorController.draw(canvas, mPaint);
}
void applyAnimation(){
mIndicatorController.initAnimation();
}
private int dp2px(int dpValue) {
return (int) getContext().getResources().getDisplayMetrics().density * dpValue;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/ProgressViewController.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.loadmore;
import android.animation.Animator;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
import java.util.List;
/**
* Created by caizhiming on 2016/2/5.
*/
public abstract class ProgressViewController {
private View mTarget;
private List mAnimators;
public void setTarget(View target){
this.mTarget=target;
}
public View getTarget(){
return mTarget;
}
public int getWidth(){
return mTarget.getWidth();
}
public int getHeight(){
return mTarget.getHeight();
}
public void postInvalidate(){
mTarget.postInvalidate();
}
/**
* draw indicator
* @param canvas
* @param paint
*/
public abstract void draw(Canvas canvas, Paint paint);
/**
* create animation or animations
*/
public abstract List createAnimation();
public void initAnimation(){
mAnimators=createAnimation();
}
/**
* make animation to start or end when target
* view was be Visible or Gone or Invisible.
* make animation to cancel when target view
* be onDetachedFromWindow.
* @param animStatus
*/
public void setAnimationStatus(AnimStatus animStatus){
if (mAnimators==null){
return;
}
int count=mAnimators.size();
for (int i = 0; i < count; i++) {
Animator animator=mAnimators.get(i);
boolean isRunning=animator.isRunning();
switch (animStatus){
case START:
if (!isRunning){
animator.start();
}
break;
case END:
if (isRunning){
animator.end();
}
break;
case CANCEL:
if (isRunning){
animator.cancel();
}
break;
}
}
}
public enum AnimStatus{
START,END,CANCEL
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/PullToLoadMoreListView.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.loadmore;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ListView;
/**
* Created by caizhiming on 2016/2/4.
* 下拉加载更多控件(仿QQ和微信的对话聊天记录页面)
*/
public class PullToLoadMoreListView extends FrameLayout {
public static final String TAG = PullToLoadMoreListView.class.getSimpleName();
private RefreshHeader mRefreshHeader;
private ListView mListView;
private int mHeight;
private DecelerateInterpolator mInterpolator = new DecelerateInterpolator(5);
private int mHeaderHeight;
private float mStartY;
private float mCurY;
private boolean mIsRefreshing;
private int mLastCount = 0;
private float mLastTranslationY = 0f;
public static final int REFRESH_STATUS_PULL_REFRESH = 0;//查看更早记录...;
public static final int REFRESH_STATUS_RELEASE_REFRESH = 1;//松开开始加载...
public static final int REFRESH_STATUS_REFRESHING = 2;// "正在加载...";
public static final int REFRESH_STATUS_REFRESH_FINISH = 3;//"加载完成";
private int mRefreshStatus = REFRESH_STATUS_PULL_REFRESH;
public PullToLoadMoreListView(Context context) {
this(context, null, 0);
}
public PullToLoadMoreListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PullToLoadMoreListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
public ListView getListView(){
return mListView;
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
mHeaderHeight = DensityUtil.dip2px(getContext(), 50);
addHeaderView(context);
addListView(context, attrs);
}
private void addHeaderView(Context context){
mRefreshHeader = new RefreshHeader(context);
mHeaderHeight = (int) mRefreshHeader.getHeaderHeight();
addView(mRefreshHeader, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mHeaderHeight));
}
private void addListView(Context context, AttributeSet attrs){
mListView = new ListView(context,attrs);
addView(mListView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(mHeight <= 0){
mHeight = getMeasuredHeight();
Log.d("czm", "Height =" + mHeight);
}
}
private boolean canChildScrollUp() {
if (mListView == null) {
return false;
}
return ViewCompat.canScrollVertically(mListView, -1);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mIsRefreshing) {
return true;
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartY = ev.getY();
mCurY = mStartY;
break;
case MotionEvent.ACTION_MOVE:
float curY = ev.getY();
float dy = curY - mStartY;
Log.d("czm", "dy=" + dy);
if (dy > 0 && !canChildScrollUp()) {
return true;
}
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mIsRefreshing) {
return super.onTouchEvent(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
mCurY = event.getY();
float dy = mCurY - mStartY;
Log.v("czm","dy====="+dy);
if(dy <0)
return true;
dy = Math.max(0, dy);
if (mListView != null) {
Log.d("czm", "dy/mHeight=" + (dy / mHeight));
float offsetY = mInterpolator.getInterpolation(dy / mHeight) * dy/3;
mListView.setTranslationY(offsetY);
mRefreshHeader.getLayoutParams().height = (int) (offsetY+0.5f);
mRefreshHeader.requestLayout();
if(mListView.getTranslationY() >= mHeaderHeight){
mRefreshStatus = REFRESH_STATUS_RELEASE_REFRESH;
mRefreshHeader.updateRefreshStatus(mRefreshStatus);
}else{
mRefreshStatus = REFRESH_STATUS_PULL_REFRESH;
mRefreshHeader.updateRefreshStatus(mRefreshStatus);
}
}
return true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if(mListView != null){
if(mListView.getTranslationY() >= mHeaderHeight){
mRefreshStatus = REFRESH_STATUS_REFRESHING;
mRefreshHeader.updateRefreshStatus(mRefreshStatus);
mIsRefreshing = true;
upToMiddleAnim();
}else{
upToTopAnim();
}
}
return true;
default:
return super.onTouchEvent(event);
}
}
private void upToMiddleAnim(){
float offsetY = mListView.getTranslationY();
final ValueAnimator backToMiddleAnim = ValueAnimator.ofFloat(offsetY, 0);
final float pullHeight = offsetY;
backToMiddleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float val = (float) animation.getAnimatedValue();
val = mInterpolator.getInterpolation(val / pullHeight) * val;
if (mListView != null) {
mListView.setTranslationY(val);
}
mRefreshHeader.getLayoutParams().height = (int) (val + 0.5f);
mRefreshHeader.requestLayout();
Log.d("czm", "offsetY=" + mListView.getTranslationY());
if (mListView.getTranslationY() <= mHeaderHeight) {
backToMiddleAnim.cancel();
}
}
});
backToMiddleAnim.setDuration((long) (offsetY * 600 / pullHeight));
backToMiddleAnim.start();
backToMiddleAnim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (mOnRefreshListener != null) {
mLastCount = mListView.getAdapter().getCount();
mOnRefreshListener.onPullDownLoadMore();
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
private void upToTopAnim(){
float offsetY = mListView.getTranslationY();
final ValueAnimator backToTopAnim = ValueAnimator.ofFloat(offsetY, 0);
final float pullHeight = offsetY;
backToTopAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float val = (float) animation.getAnimatedValue();
val = mInterpolator.getInterpolation(val / pullHeight) * val;
if (mListView != null) {
mListView.setTranslationY(val);
}
mRefreshHeader.getLayoutParams().height = (int) (val+0.5f);
mRefreshHeader.requestLayout();
Log.d("czm", "offsetY=" + mListView.getTranslationY());
}
});
backToTopAnim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
mRefreshStatus = REFRESH_STATUS_PULL_REFRESH;
mRefreshHeader.updateRefreshStatus(mRefreshStatus);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
backToTopAnim.setDuration((long) (offsetY * 600 / pullHeight));
backToTopAnim.start();
}
private void completeBackToTop(){
mListView.setTranslationY(0);
int num = mListView.getAdapter().getCount() - mLastCount;
Log.v("czm","num="+num);
if(num > 0){
mListView.setSelectionFromTop(num, (int) mLastTranslationY);
}
}
public void onRefreshComplete(){
mLastTranslationY = mListView.getTranslationY();
mIsRefreshing = false;
mRefreshStatus = REFRESH_STATUS_REFRESH_FINISH;
mRefreshHeader.updateRefreshStatus(mRefreshStatus);
completeBackToTop();
}
private OnRefreshListener mOnRefreshListener;
public void setOnRefreshListener(OnRefreshListener listener){
mOnRefreshListener = listener;
}
public interface OnRefreshListener{
void onPullDownLoadMore();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/RefreshHeader.java
================================================
package com.htmessage.yichatopen.activity.chat.weight.loadmore;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.htmessage.yichatopen.R;
/**
* Created by caizhiming on 2016/2/4.
*/
public class RefreshHeader extends LinearLayout {
private TextView mStatusTextView;
private ProgressView mProgressView;
private ImageView mStatusImageView;
private Animation mRotateUpAnim;
private Animation mRotateDownAnim;
private float mHeaderHeight = 0;
private String[] mTxtStatus = new String[]
{
"查看更早记录...", "松开开始加载...",
"正在加载...", "加载完成"
};
private int mStatus = PullToLoadMoreListView.REFRESH_STATUS_PULL_REFRESH;
private static final int ROTATE_ANIM_DURATION = 200;
public RefreshHeader(Context context) {
this(context, null);
}
public RefreshHeader(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RefreshHeader(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
public float getHeaderHeight() {
return this.mHeaderHeight;
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
mHeaderHeight = DensityUtil.dip2px(context, 50);
//初始化自己
LayoutParams lpRoot = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
this.setOrientation(LinearLayout.HORIZONTAL);
this.setGravity(Gravity.CENTER_HORIZONTAL);
this.setLayoutParams(lpRoot);
this.setBackgroundColor(Color.parseColor("#458B00"));
//add progress view
mProgressView = new ProgressView(context);
LayoutParams lp2 = new LayoutParams(
DensityUtil.dip2px(context, 25), DensityUtil.dip2px(context, 25));
lp2.gravity = Gravity.BOTTOM;
lp2.bottomMargin = (int) (mHeaderHeight / 7.5);
this.addView(mProgressView, lp2);
mProgressView.setVisibility(View.GONE);
//add arrow ImageView
mStatusImageView = new ImageView(context);
mStatusImageView.setImageResource(R.drawable.arrow_down);
LayoutParams lp = new LayoutParams(
DensityUtil.dip2px(context, 20), DensityUtil.dip2px(context, 20));
lp.gravity = Gravity.BOTTOM;
lp.bottomMargin = (int) (mHeaderHeight / 5);
this.addView(mStatusImageView, lp);
//add refresh text status TextView
mStatusTextView = new TextView(context);
mStatusTextView.setText(mTxtStatus[0]);
mStatusTextView.setTextColor(Color.WHITE);
lp = new LayoutParams(
DensityUtil.dip2px(context, 100), LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.BOTTOM;
lp.leftMargin = DensityUtil.dip2px(context, 5);
lp.bottomMargin = (int) (mHeaderHeight / 10);
mStatusTextView.setGravity(Gravity.CENTER);
this.addView(mStatusTextView, lp);
mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
mRotateUpAnim.setFillAfter(true);
mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
mRotateDownAnim.setFillAfter(true);
}
public void updateRefreshStatus(int status) {
mStatusTextView.setText(mTxtStatus[status]);
if(status == PullToLoadMoreListView.REFRESH_STATUS_RELEASE_REFRESH
&& mStatus == PullToLoadMoreListView.REFRESH_STATUS_PULL_REFRESH){
mStatusImageView.clearAnimation();
mStatusImageView.startAnimation(mRotateUpAnim);
}
if(status == PullToLoadMoreListView.REFRESH_STATUS_PULL_REFRESH
&& mStatus == PullToLoadMoreListView.REFRESH_STATUS_RELEASE_REFRESH){
mStatusImageView.clearAnimation();
mStatusImageView.startAnimation(mRotateDownAnim);
}
if(status == PullToLoadMoreListView.REFRESH_STATUS_REFRESHING){
mStatusImageView.clearAnimation();
mStatusImageView.setVisibility(View.GONE);
mProgressView.setVisibility(View.VISIBLE);
}
if(status == PullToLoadMoreListView.REFRESH_STATUS_REFRESH_FINISH){
mProgressView.setVisibility(View.GONE);
}
if(status == PullToLoadMoreListView.REFRESH_STATUS_PULL_REFRESH
&& mStatus == PullToLoadMoreListView.REFRESH_STATUS_REFRESH_FINISH){
mStatusImageView.setVisibility(View.VISIBLE);
mStatusImageView.startAnimation(mRotateDownAnim);
}
mStatus = status;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/country/CharacterParserUtil.java
================================================
/*
* Copyright 2010 Beijing Xinwei, Inc. All rights reserved.
*
* History:
* ------------------------------------------------------------------------------
* Date | Who | What
* 2015��3��18�� | duanbokan | create the file
*/
package com.htmessage.yichatopen.activity.country;
public class CharacterParserUtil {
private static int[] pyvalue = new int[]{-20319, -20317, -20304, -20295, -20292, -20283,
-20265, -20257, -20242, -20230, -20051, -20036, -20032, -20026, -20002, -19990, -19986,
-19982, -19976, -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741,
-19739, -19728, -19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479,
-19467, -19289, -19288, -19281, -19275, -19270, -19263, -19261, -19249, -19243, -19242,
-19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006, -19003,
-18996, -18977, -18961, -18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735,
-18731, -18722, -18710, -18697, -18696, -18526, -18518, -18501, -18490, -18478, -18463,
-18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211, -18201, -18184, -18183,
-18181, -18012, -17997, -17988, -17970, -17964, -17961, -17950, -17947, -17931, -17928,
-17922, -17759, -17752, -17733, -17730, -17721, -17703, -17701, -17697, -17692, -17683,
-17676, -17496, -17487, -17482, -17468, -17454, -17433, -17427, -17417, -17202, -17185,
-16983, -16970, -16942, -16915, -16733, -16708, -16706, -16689, -16664, -16657, -16647,
-16474, -16470, -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423, -16419,
-16412, -16407, -16403, -16401, -16393, -16220, -16216, -16212, -16205, -16202, -16187,
-16180, -16171, -16169, -16158, -16155, -15959, -15958, -15944, -15933, -15920, -15915,
-15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640,
-15631, -15625, -15454, -15448, -15436, -15435, -15419, -15416, -15408, -15394, -15385,
-15377, -15375, -15369, -15363, -15362, -15183, -15180, -15165, -15158, -15153, -15150,
-15149, -15144, -15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110,
-15109, -14941, -14937, -14933, -14930, -14929, -14928, -14926, -14922, -14921, -14914,
-14908, -14902, -14894, -14889, -14882, -14873, -14871, -14857, -14678, -14674, -14670,
-14668, -14663, -14654, -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379,
-14368, -14355, -14353, -14345, -14170, -14159, -14151, -14149, -14145, -14140, -14137,
-14135, -14125, -14123, -14122, -14112, -14109, -14099, -14097, -14094, -14092, -14090,
-14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894, -13878,
-13870, -13859, -13847, -13831, -13658, -13611, -13601, -13406, -13404, -13400, -13398,
-13395, -13391, -13387, -13383, -13367, -13359, -13356, -13343, -13340, -13329, -13326,
-13318, -13147, -13138, -13120, -13107, -13096, -13095, -13091, -13076, -13068, -13063,
-13060, -12888, -12875, -12871, -12860, -12858, -12852, -12849, -12838, -12831, -12829,
-12812, -12802, -12607, -12597, -12594, -12585, -12556, -12359, -12346, -12320, -12300,
-12120, -12099, -12089, -12074, -12067, -12058, -12039, -11867, -11861, -11847, -11831,
-11798, -11781, -11604, -11589, -11536, -11358, -11340, -11339, -11324, -11303, -11097,
-11077, -11067, -11055, -11052, -11045, -11041, -11038, -11024, -11020, -11019, -11018,
-11014, -10838, -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544, -10533,
-10519, -10331, -10329, -10328, -10322, -10315, -10309, -10307, -10296, -10281, -10274,
-10270, -10262, -10260, -10256, -10254};
public static String[] pystr = new String[]{"a", "ai", "an", "ang", "ao", "ba", "bai", "ban",
"bang", "bao", "bei", "ben", "beng", "bi", "bian", "biao", "bie", "bin", "bing", "bo",
"bu", "ca", "cai", "can", "cang", "cao", "ce", "ceng", "cha", "chai", "chan", "chang",
"chao", "che", "chen", "cheng", "chi", "chong", "chou", "chu", "chuai", "chuan",
"chuang", "chui", "chun", "chuo", "ci", "cong", "cou", "cu", "cuan", "cui", "cun",
"cuo", "da", "dai", "dan", "dang", "dao", "de", "deng", "di", "dian", "diao", "die",
"ding", "diu", "dong", "dou", "du", "duan", "dui", "dun", "duo", "e", "en", "er", "fa",
"fan", "fang", "fei", "fen", "feng", "fo", "fou", "fu", "ga", "gai", "gan", "gang",
"gao", "ge", "gei", "gen", "geng", "gong", "gou", "gu", "gua", "guai", "guan", "guang",
"gui", "gun", "guo", "ha", "hai", "han", "hang", "hao", "he", "hei", "hen", "heng",
"hong", "hou", "hu", "hua", "huai", "huan", "huang", "hui", "hun", "huo", "ji", "jia",
"jian", "jiang", "jiao", "jie", "jin", "jing", "jiong", "jiu", "ju", "juan", "jue",
"jun", "ka", "kai", "kan", "kang", "kao", "ke", "ken", "keng", "kong", "kou", "ku",
"kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo", "la", "lai", "lan", "lang", "lao",
"le", "lei", "leng", "li", "lia", "lian", "liang", "liao", "lie", "lin", "ling", "liu",
"long", "lou", "lu", "lv", "luan", "lue", "lun", "luo", "ma", "mai", "man", "mang",
"mao", "me", "mei", "men", "meng", "mi", "mian", "miao", "mie", "min", "ming", "miu",
"mo", "mou", "mu", "na", "nai", "nan", "nang", "nao", "ne", "nei", "nen", "neng", "ni",
"nian", "niang", "niao", "nie", "nin", "ning", "niu", "nong", "nu", "nv", "nuan",
"nue", "nuo", "o", "ou", "pa", "pai", "pan", "pang", "pao", "pei", "pen", "peng", "pi",
"pian", "piao", "pie", "pin", "ping", "po", "pu", "qi", "qia", "qian", "qiang", "qiao",
"qie", "qin", "qing", "qiong", "qiu", "qu", "quan", "que", "qun", "ran", "rang", "rao",
"re", "ren", "reng", "ri", "rong", "rou", "ru", "ruan", "rui", "run", "ruo", "sa",
"sai", "san", "sang", "sao", "se", "sen", "seng", "sha", "shai", "shan", "shang",
"shao", "she", "shen", "sheng", "shi", "shou", "shu", "shua", "shuai", "shuan",
"shuang", "shui", "shun", "shuo", "si", "song", "sou", "su", "suan", "sui", "sun",
"suo", "ta", "tai", "tan", "tang", "tao", "te", "teng", "ti", "tian", "tiao", "tie",
"ting", "tong", "tou", "tu", "tuan", "tui", "tun", "tuo", "wa", "wai", "wan", "wang",
"wei", "wen", "weng", "wo", "wu", "xi", "xia", "xian", "xiang", "xiao", "xie", "xin",
"xing", "xiong", "xiu", "xu", "xuan", "xue", "xun", "ya", "yan", "yang", "yao", "ye",
"yi", "yin", "ying", "yo", "yong", "you", "yu", "yuan", "yue", "yun", "za", "zai",
"zan", "zang", "zao", "ze", "zei", "zen", "zeng", "zha", "zhai", "zhan", "zhang",
"zhao", "zhe", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu", "zhua", "zhuai",
"zhuan", "zhuang", "zhui", "zhun", "zhuo", "zi", "zong", "zou", "zu", "zuan", "zui",
"zun", "zuo"};
private StringBuilder buffer;
private String resource;
private static CharacterParserUtil characterParser = new CharacterParserUtil();
public static CharacterParserUtil getInstance() {
return characterParser;
}
public String getResource() {
return resource;
}
public void setResource(String resource) {
this.resource = resource;
}
/**
* 汉字转成ASCII码
*
* @param chs
* @return
*/
private int getChsAscii(String chs) {
int asc = 0;
try {
byte[] bytes = chs.getBytes("gb2312");
if (bytes == null || bytes.length > 2 || bytes.length <= 0) {
throw new RuntimeException("illegal resource string");
}
if (bytes.length == 1) {
asc = bytes[0];
}
if (bytes.length == 2) {
int hightByte = 256 + bytes[0];
int lowByte = 256 + bytes[1];
asc = (256 * hightByte + lowByte) - 256 * 256;
}
} catch (Exception e) {
System.out.println("ERROR:ChineseSpelling.class-getChsAscii(String chs)" + e);
}
return asc;
}
/**
* 单个字进行解析
*
* @param str
* @return
*/
public String convert(String str) {
String result = null;
int ascii = getChsAscii(str);
if (ascii > 0 && ascii < 160) {
result = String.valueOf((char) ascii);
} else {
for (int i = (pyvalue.length - 1); i >= 0; i--) {
if (pyvalue[i] <= ascii) {
result = pystr[i];
break;
}
}
}
return result;
}
/***
* 词组解析
*
* @param chs
* @return
*/
public String getSelling(String chs) {
String key, value;
buffer = new StringBuilder();
for (int i = 0; i < chs.length(); i++) {
key = chs.substring(i, i + 1);
if (key.getBytes().length >= 2) {
value = (String) convert(key);
if (value == null) {
value = "unknown";
}
} else {
value = key;
}
buffer.append(value);
}
return buffer.toString();
}
public String getSpelling() {
return this.getSelling(this.getResource());
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/country/CountryCodeUtil.java
================================================
package com.htmessage.yichatopen.activity.country;
import android.content.Context;
import com.htmessage.yichatopen.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 项目名称:htmessage_sdk
* 类描述:CountryCodeUtil 描述:
* 创建人:songlijie
* 创建时间:2017/3/3 19:25
* 邮箱:814326663@qq.com
*/
public class CountryCodeUtil {
/**
* 获取国家列表
*/
public static List getCountryList(Context context, boolean isCn) {
List mAllCountryList = new ArrayList<>();
String[] countryList = context.getResources().getStringArray(R.array.country_code_list_ch);
if (!isCn){
countryList = context.getResources().getStringArray(R.array.country_code_list_en);
}
for (int i = 0, length = countryList.length; i < length; i++) {
String[] country = countryList[i].split("\\*");
String countryName = country[0];
String countryNumber = country[1];
String countrySortKey = new CharacterParserUtil().getSelling(countryName);
CountrySortModel countrySortModel = new CountrySortModel(countryName, countryNumber,
countrySortKey);
String sortLetter = new GetCountryNameSort().getSortLetterBySortKey(countrySortKey);
if (sortLetter == null) {
sortLetter = new GetCountryNameSort().getSortLetterBySortKey(countryName);
}
countrySortModel.sortLetters = sortLetter;
mAllCountryList.add(countrySortModel);
}
Collections.sort(mAllCountryList, new CountryComparator());
return mAllCountryList;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/country/CountryComparator.java
================================================
/*
* Copyright 2010 Beijing Xinwei, Inc. All rights reserved.
*
* History:
* ------------------------------------------------------------------------------
* Date | Who | What
* 2015��3��18�� | duanbokan | create the file
*/
package com.htmessage.yichatopen.activity.country;
import java.util.Comparator;
public class CountryComparator implements Comparator {
@Override
public int compare(CountrySortModel o1, CountrySortModel o2) {
if (o1.sortLetters.equals("@") || o2.sortLetters.equals("#")) {
return -1;
} else if (o1.sortLetters.equals("#") || o2.sortLetters.equals("@")) {
return 1;
} else {
return o1.sortLetters.compareTo(o2.sortLetters);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/country/CountryModel.java
================================================
/*
* Copyright 2010 Beijing Xinwei, Inc. All rights reserved.
*
* History:
* ------------------------------------------------------------------------------
* Date | Who | What
* 2015��3��30�� | duanbokan | create the file
*/
package com.htmessage.yichatopen.activity.country;
import android.graphics.drawable.Drawable;
public class CountryModel {
// 国家名称
public String countryName;
// 国家代码
public String countryNumber;
public String simpleCountryNumber;
// 国家名称缩写
public String countrySortKey;
// 国家图标
public Drawable contactPhoto;
public CountryModel(String countryName, String countryNumber, String countrySortKey) {
super();
this.countryName = countryName;
this.countryNumber = countryNumber;
this.countrySortKey = countrySortKey;
if (countryNumber != null) {
this.simpleCountryNumber = countryNumber.replaceAll("\\-|\\s", "");
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/country/CountrySortAdapter.java
================================================
/*
* Copyright 2010 Beijing Xinwei, Inc. All rights reserved.
*
* History:
* ------------------------------------------------------------------------------
* Date | Who | What
* 2015��3��21�� | duanbokan | create the file
*/
package com.htmessage.yichatopen.activity.country;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.SectionIndexer;
import android.widget.TextView;
import com.htmessage.yichatopen.R;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* 国家码选择
*/
public class CountrySortAdapter extends BaseAdapter implements SectionIndexer {
private List mList;
private Context mContext;
LayoutInflater mInflater;
/***
* 初始化
*
* @param mContext
* @param list
*/
public CountrySortAdapter(Context mContext, List list) {
this.mContext = mContext;
if (list == null) {
this.mList = new ArrayList();
} else {
this.mList = list;
}
}
@Override
public int getCount() {
return this.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 view, ViewGroup parent) {
ViewHolder viewHolder = null;
final CountrySortModel mContent = mList.get(position);
if (view == null) {
viewHolder = new ViewHolder();
view = LayoutInflater.from(mContext).inflate(R.layout.coogame_country_item, null);
viewHolder.country_sortName = (TextView) view.findViewById(R.id.country_catalog);
viewHolder.country_name = (TextView) view.findViewById(R.id.country_name);
viewHolder.country_number = (TextView) view.findViewById(R.id.country_number);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
// 根据position获取分类的首字母的Char ascii值
int section = getSectionForPosition(position);
// 如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
if (position == getPositionForSection(section)) {
viewHolder.country_sortName.setVisibility(View.VISIBLE);
viewHolder.country_sortName.setText(mContent.sortLetters);
} else {
viewHolder.country_sortName.setVisibility(View.GONE);
}
viewHolder.country_name.setText(this.mList.get(position).countryName);
viewHolder.country_number.setText(this.mList.get(position).countryNumber);
return view;
}
@Override
public int getPositionForSection(int section) {
if (section != 42) {
for (int i = 0; i < getCount(); i++) {
String sortStr = mList.get(i).sortLetters;
char firstChar = sortStr.toUpperCase(Locale.CHINESE).charAt(0);
if (firstChar == section) {
return i;
}
}
} else {
return 0;
}
return -1;
}
@Override
public int getSectionForPosition(int position) {
return mList.get(position).sortLetters.charAt(0);
}
@Override
public Object[] getSections() {
return null;
}
/**
* 当ListView数据发生变化时,调用此方法来更新ListView
*
* @param list
*/
public void updateListView(List list) {
if (list == null) {
this.mList = new ArrayList();
} else {
this.mList = list;
}
notifyDataSetChanged();
}
public static class ViewHolder {
// 国家码简拼所属的字母范围
public TextView country_sortName;
// 国家名
public TextView country_name;
// 代码
public TextView country_number;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/country/CountrySortModel.java
================================================
/*
* Copyright 2010 Beijing Xinwei, Inc. All rights reserved.
*
* History:
* ------------------------------------------------------------------------------
* Date | Who | What
* 2015��3��21�� | duanbokan | create the file
*/
package com.htmessage.yichatopen.activity.country;
public class CountrySortModel extends CountryModel {
// 显示数据拼音的首字母
public String sortLetters;
public CountrySortToken sortToken = new CountrySortToken();
public CountrySortModel(String name, String number, String countrySortKey) {
super(name, number, countrySortKey);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/country/CountrySortToken.java
================================================
/*
* Copyright 2010 Beijing Xinwei, Inc. All rights reserved.
*
* History:
* ------------------------------------------------------------------------------
* Date | Who | What
* 2015��3��21�� | duanbokan | create the file
*/
package com.htmessage.yichatopen.activity.country;
public class CountrySortToken
{
// 简拼
public String simpleSpell = "";
// 全拼
public String wholeSpell = "";
// 中文全名
public String chName = "";
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/country/GetCountryNameSort.java
================================================
/*
* Copyright 2010 Beijing Xinwei, Inc. All rights reserved.
*
* History:
* ------------------------------------------------------------------------------
* Date | Who | What
* 2015��3��20�� | duanbokan | create the file
*/
package com.htmessage.yichatopen.activity.country;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* 取姓名首字母及模糊匹配查询
*
*
* 类详细描述
*
*
* @author duanbokan
*/
public class GetCountryNameSort {
CharacterParserUtil characterParser = CharacterParserUtil.getInstance();
String chReg = "[\\u4E00-\\u9FA5]+";// 中文字符串匹配
/***
* 将名字转化为拼音并获得首字母
*
* @param name
* @return
*/
public String getSortLetter(String name) {
String letter = "#";
if (name == null) {
return letter;
}
// 汉字转换成拼音
String pinyin = characterParser.getSelling(name);
String sortString = pinyin.substring(0, 1).toUpperCase(Locale.CHINESE);
// 正则表达式,判断首字母是否是英文字母
if (sortString.matches("[A-Z]")) {
letter = sortString.toUpperCase(Locale.CHINESE);
}
return letter;
}
/***
* 取首字母
*
* @param sortKey
* @return
*/
public String getSortLetterBySortKey(String sortKey) {
if (sortKey == null || "".equals(sortKey.trim())) {
return null;
}
String letter = "#";
// 汉字转换成拼音
String sortString = sortKey.trim().substring(0, 1).toUpperCase(Locale.CHINESE);
// 正则表达式,判断首字母是否是英文字母
if (sortString.matches("[A-Z]")) {
letter = sortString.toUpperCase(Locale.CHINESE);
}
return letter;
}
/***
* 根据输入内容进行查询
*
* @param str 输入内容
* @param list 需要查询的List
* @return 查询结果
*/
public List search(String str, List list) {
List filterList = new ArrayList();// 过滤后的list
// if (str.matches("^([0-9]|[/+])*$")) {// 正则表达式 匹配号码
if (str.matches("^([0-9]|[/+]).*")) {// 正则表达式 匹配以数字或者加号开头的字符串(包括了带空格及-分割的号码)
String simpleStr = str.replaceAll("\\-|\\s", "");
for (CountrySortModel contact : list) {
if (contact.countryName != null && contact.countryName != null) {
if (contact.simpleCountryNumber.contains(simpleStr)
|| contact.countryName.contains(str)) {
if (!filterList.contains(contact)) {
filterList.add(contact);
}
}
}
}
} else {
for (CountrySortModel contact : list) {
if (contact.countryNumber != null && contact.countryName != null) {
// 姓名全匹配,姓名首字母简拼匹配,姓名全字母匹配
if (contact.countryName.toLowerCase(Locale.CHINESE).contains(
str.toLowerCase(Locale.CHINESE))
|| contact.countrySortKey.toLowerCase(Locale.CHINESE).replace(" ", "")
.contains(str.toLowerCase(Locale.CHINESE))
|| contact.sortToken.simpleSpell.toLowerCase(Locale.CHINESE).contains(
str.toLowerCase(Locale.CHINESE))
|| contact.sortToken.wholeSpell.toLowerCase(Locale.CHINESE).contains(
str.toLowerCase(Locale.CHINESE))) {
if (!filterList.contains(contact)) {
filterList.add(contact);
}
}
}
}
}
return filterList;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/country/SideBar.java
================================================
/*
* Copyright 2010 Beijing Xinwei, Inc. All rights reserved.
*
* History:
* ------------------------------------------------------------------------------
* Date | Who | What
* 2015年3月18日 | duanbokan | create the file
*/
package com.htmessage.yichatopen.activity.country;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import com.htmessage.yichatopen.R;
/**
* 类简要描述
*/
public class SideBar extends View {
// 字母变化监听事件
private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
// 字母数组
public static String[] b = {"*", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
"M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"};
// 选中
private int choose = -1;
private Paint paint = new Paint();
// 点击后提示当前选中字母
private TextView mTextDialog;
public void setTextView(TextView mTextDialog) {
this.mTextDialog = mTextDialog;
}
public SideBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SideBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SideBar(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 获取屏幕高度和宽度
int height = getHeight();
int width = getWidth();
// 设置字母高度
float letterHeight = (height * 1f) / b.length;
for (int i = 0; i < b.length; i++) {
paint.setColor(Color.rgb(23, 122, 126));
paint.setTypeface(Typeface.DEFAULT_BOLD);
// 抗锯齿
paint.setAntiAlias(true);
paint.setTextSize(20);
if (i == choose) {
paint.setColor(Color.BLUE);
// 设置为加粗字体
paint.setFakeBoldText(true);
}
// x坐标等于中间-字符串宽度的一半.
float xPos = width / 2 - paint.measureText(b[i]) / 2;
float yPos = letterHeight * i + letterHeight;
canvas.drawText(b[i], xPos, yPos, paint);
// 重置画笔
paint.reset();
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction();
final float touch_y = event.getY();
final int oldChoose = choose;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
final int c = (int) (touch_y / getHeight() * b.length);
switch (action) {
case MotionEvent.ACTION_UP:
setBackgroundColor(Color.TRANSPARENT);
choose = -1;
invalidate();
if (mTextDialog != null) {
mTextDialog.setVisibility(View.INVISIBLE);
}
break;
default:
setBackgroundResource(R.color.holo_green_light);
if (oldChoose != c) {
if (c >= 0 && c < b.length) {
if (listener != null) {
listener.onTouchingLetterChanged(b[c]);
}
if (mTextDialog != null) {
mTextDialog.setText(b[c]);
mTextDialog.setVisibility(View.VISIBLE);
}
choose = c;
invalidate();
}
}
break;
}
return true;
}
/**
* 向外公开的方法
*
* @param onTouchingLetterChangedListener
*/
public void setOnTouchingLetterChangedListener(
OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}
/**
* 接口
*
* @author coder
*/
public interface OnTouchingLetterChangedListener {
public void onTouchingLetterChanged(String s);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/login/LoginActivity.java
================================================
package com.htmessage.yichatopen.activity.login;
import android.annotation.TargetApi;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentTransaction;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.BaseActivity;
import com.htmessage.yichatopen.runtimepermissions.PermissionsManager;
import com.htmessage.yichatopen.runtimepermissions.PermissionsResultAction;
/**
* Login screen
*/
public class LoginActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
hideBackView();
setTitle(R.string.login_by_mobile);
requestPermissions();
LoginFragment loginFragment =
(LoginFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (loginFragment == null) {
// Create the fragment
loginFragment =new LoginFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame, loginFragment);
transaction.commit();
}
LoginPresenter presenter=new LoginPresenter(loginFragment);
}
@TargetApi(23)
private void requestPermissions() {
PermissionsManager.getInstance().requestAllManifestPermissionsIfNecessary(this, new PermissionsResultAction() {
@Override
public void onGranted() {
}
@Override
public void onDenied(String permission) {
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/login/LoginContract.java
================================================
package com.htmessage.yichatopen.activity.login;
import android.app.Activity;
import android.content.Context;
import android.widget.TextView;
import com.htmessage.yichatopen.activity.BasePresenter;
import com.htmessage.yichatopen.activity.BaseView;
/**
* Created by huangfangyi on 2017/6/21.
* qq 84543217
*/
public interface LoginContract {
interface View extends BaseView {
void showDialog();
void cancelDialog();
String getUsername();
String getPassword();
void setButtonEnable();
void setButtonDisabel();
void showToast(int toastMsg);
String getCountryName();
String getCountryCode();
Activity getBaseActivity();
Context getBaseContext();
}
interface Presenter extends BasePresenter {
void requestServer(String username, String password);
void chooseCuntry(Context context, TextView tvCountryName, TextView tvCountryCode);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/login/LoginFragment.java
================================================
package com.htmessage.yichatopen.activity.login;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.main.password.PasswordResetActivity;
import com.htmessage.yichatopen.activity.register.RegisterActivity;
import com.htmessage.yichatopen.utils.Validator;
/**
* Created by dell on 2017/6/21.
*/
public class LoginFragment extends Fragment implements LoginContract.View, View.OnClickListener {
private LoginContract.Presenter mPresenter;
private EditText et_usertel, et_password;
private TextView tv_find_password, tv_country, tv_country_code;
private Button btn_login, btn_qtlogin;
private RelativeLayout rl_country;
private Dialog dialog;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dialog = HTApp.getInstance().createLoadingDialog(getActivity(), getString(R.string.logining));
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_login, container, false);
et_usertel = (EditText) root.findViewById(R.id.et_usertel);
et_password = (EditText) root.findViewById(R.id.et_password);
btn_login = (Button) root.findViewById(R.id.btn_login);
tv_country = (TextView) root.findViewById(R.id.tv_country);
tv_country_code = (TextView) root.findViewById(R.id.tv_country_code);
tv_find_password = (TextView) root.findViewById(R.id.tv_find_password);
rl_country = (RelativeLayout) root.findViewById(R.id.rl_country);
btn_qtlogin = (Button) root.findViewById(R.id.btn_qtlogin);
setLisenter();
return root;
}
private void setLisenter() {
//输入监听
TextChange textChange = new TextChange();
et_usertel.addTextChangedListener(textChange);
et_password.addTextChangedListener(textChange);
//登陆按钮监听
btn_login.setOnClickListener(this);
//选取国家监听
rl_country.setOnClickListener(this);
//跳转注册监听
btn_qtlogin.setOnClickListener(this);
tv_find_password.setOnClickListener(this);
}
@Override
public void setPresenter(LoginContract.Presenter presenter) {
mPresenter = presenter;
}
@Override
public void showDialog() {
if (dialog != null)
dialog.show();
}
@Override
public void cancelDialog() {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
@Override
public String getUsername() {
return et_usertel.getText().toString().trim();
}
@Override
public String getPassword() {
return et_password.getText().toString().trim();
}
@Override
public void setButtonEnable() {
btn_login.setEnabled(true);
}
@Override
public void setButtonDisabel() {
btn_login.setEnabled(true);
}
@Override
public void showToast(int toastMsg) {
Toast.makeText(getActivity(), toastMsg, Toast.LENGTH_SHORT).show();
}
@Override
public String getCountryName() {
return tv_country.getText().toString().trim();
}
@Override
public String getCountryCode() {
return tv_country_code.getText().toString().trim();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_login:
if (TextUtils.isEmpty(getUsername())) {
showToast( R.string.tel_is_not_allow_null );
return;
}
//如果是中国地区,进行一个手机号验证
if (getCountryName().equals(getString(R.string.china)) && getCountryCode().equals(getString(R.string.country_code))) {
if (!Validator.isMobile(getUsername())) {
showToast( R.string.please_input_true_mobile );
return;
}
}
if (TextUtils.isEmpty(getPassword())) {
showToast( R.string.pwd_is_not_allow_null);
return;
}
mPresenter.requestServer(getUsername(), getPassword());
break;
case R.id.rl_country:
mPresenter.chooseCuntry(getContext(), tv_country, tv_country_code);
break;
case R.id.btn_qtlogin:
startActivity(new Intent(getActivity(), RegisterActivity.class));
break;
case R.id.tv_find_password:
startActivity(new Intent(getActivity(), PasswordResetActivity.class).putExtra("isReset", false));
break;
}
}
// EditText监听器
private class TextChange implements TextWatcher {
@Override
public void afterTextChanged(Editable arg0) {
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void onTextChanged(CharSequence cs, int start, int before,
int count) {
boolean sign1 = et_usertel.getText().length() > 0;
boolean sign2 = et_password.getText().length() > 0;
if (sign1 & sign2) {
setButtonEnable();
} else {
setButtonDisabel();
}
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/login/LoginPresenter.java
================================================
package com.htmessage.yichatopen.activity.login;
import android.content.Context;
import android.content.Intent;
import android.widget.TextView;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.sdk.client.HTClient;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.main.MainActivity;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.manager.ContactsManager;
import com.htmessage.yichatopen.utils.CommonUtils;
import com.htmessage.yichatopen.utils.OkHttpUtils;
import com.htmessage.yichatopen.utils.Param;
import com.htmessage.yichatopen.utils.UpdateLastLoginTimeUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by huangfangyi on 2017/6/21.
* qq 84543217
*/
public class LoginPresenter implements LoginContract.Presenter {
private LoginContract.View loginView;
public LoginPresenter(LoginContract.View loginView){
this.loginView=loginView;
this.loginView.setPresenter(this);
}
@Override
public void requestServer(String username, String password) {
loginView.showDialog();
List params = new ArrayList<>();
params.add(new Param("usertel", username));
params.add(new Param("password", password));
new OkHttpUtils(loginView.getBaseActivity() ).post(params, HTConstant.URL_LOGIN, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
int code = jsonObject.getInteger("code");
switch(code){
case 1:
JSONObject userJson = jsonObject.getJSONObject("user");
loginIm(userJson);
break;
case -1:
loginView.cancelDialog();
loginView.showToast(R.string.Account_does_not_exist);
break;
case -2:
loginView.cancelDialog();
loginView.showToast(R.string.Incorrect_password);
break;
case -3:
loginView.cancelDialog();
loginView.showToast(R.string.Account_has_been_disabled);
break;
default:
loginView.cancelDialog();
loginView.showToast(R.string.Server_busy);
break;
}
}
@Override
public void onFailure(String errorMsg) {
loginView.cancelDialog();
}
});
}
@Override
public void chooseCuntry(Context context, TextView tvCountryName, TextView tvCountryCode) {
CommonUtils.showPup(context,tvCountryName,tvCountryCode);
}
private void loginIm(final JSONObject userJson) {
HTClient.getInstance().login(userJson.getString(HTConstant.JSON_KEY_HXID), userJson.getString(HTConstant.JSON_KEY_PASSWORD), new HTClient.HTCallBack() {
@Override
public void onSuccess() {
if (userJson == null) {
return;
}
JSONArray friends = userJson.getJSONArray("friend");
if (userJson.containsKey("friend")) {
userJson.remove("friend");
}
HTApp.getInstance().setUserJson(userJson);
Map userlist = new HashMap();
if (friends != null) {
for (int i = 0; i < friends.size(); i++) {
JSONObject friend = friends.getJSONObject(i);
User user = CommonUtils.Json2User(friend);
userlist.put(user.getUsername(), user);
}
List users = new ArrayList(userlist.values());
ContactsManager.getInstance().saveContactList(users);
}
//上传最近登录时间
UpdateLastLoginTimeUtils.sendLocalTimeToService(loginView.getBaseContext());
loginView.getBaseActivity(). runOnUiThread(new Runnable() {
@Override
public void run() {
loginView.cancelDialog();
loginView.showToast(R.string.login_success);
Intent intent = new Intent(loginView.getBaseContext(),
MainActivity.class);
loginView.getBaseActivity().startActivity(intent);
loginView.getBaseActivity().finish();
}
});
}
@Override
public void onError() {
loginView.getBaseActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
loginView.cancelDialog();
loginView.showToast(R.string.Login_failed);
}
});
}
});
}
@Override
public void start() {
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/MainActivity.java
================================================
package com.htmessage.yichatopen.activity.main;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.view.menu.MenuBuilder;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.htmessage.sdk.client.HTClient;
import com.htmessage.yichatopen.IMAction;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.addfriends.add.pre.AddFriendsPreActivity;
import com.htmessage.yichatopen.activity.BaseActivity;
import com.htmessage.yichatopen.activity.ScanCaptureActivity;
import com.htmessage.yichatopen.activity.login.LoginActivity;
import com.htmessage.yichatopen.activity.main.contacts.FragmentContacts;
import com.htmessage.yichatopen.activity.main.conversation.ConversationFragment;
import com.htmessage.yichatopen.activity.main.find.FragmentFind;
import com.htmessage.yichatopen.activity.main.profile.FragmentProfile;
import com.htmessage.yichatopen.runtimepermissions.PermissionsManager;
import com.htmessage.yichatopen.runtimepermissions.PermissionsResultAction;
import java.lang.reflect.Method;
/**
* Created by huangfangyi on 2017/6/24.
* qq 84543217
*/
public class MainActivity extends BaseActivity implements MainView {
private TabLayout mTablayout;
private ViewPager mViewPager;
private String[] mTitles;
private int[] drawabls = new int[]{R.drawable.tab_chat_bg, R.drawable.tab_contact_list_bg, R.drawable.tab_find_bg, R.drawable.tab_profile_bg};
private TabLayout.Tab[] tabs;
private Fragment[] fragments;
//新消息角标
private TextView unreadLabel;
// 新好友申请消息角标
public TextView unreadInvitionLable;
// user logged into another device
public boolean isConflict = false;
private android.app.AlertDialog.Builder exceptionBuilder;
private boolean isConflictDialogShow;
private MainPrestener mainPrestener;
@Override
protected void onCreate(Bundle arg0) {
if (arg0 != null && arg0.getBoolean("isConflict", false)) {
finish();
startActivity(new Intent(this, LoginActivity.class));
return;
}
super.onCreate(arg0);
setContentView(R.layout.activity_base_main);
mainPrestener = new MainPrestener(this);
mTitles = new String[]{getString(R.string.app_chat), getString(R.string.address_book), getString(R.string.bottom_find), getString(R.string.me)};
Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitle(getString(R.string.app_name));
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_search:
Toast.makeText(getApplicationContext(), R.string.wait_do, Toast.LENGTH_SHORT).show();
break;
case R.id.item_add_friend:
startActivity(new Intent(MainActivity.this, AddFriendsPreActivity.class));
break;
case R.id.item_add_group:
Toast.makeText(getApplicationContext(), R.string.open_notice, Toast.LENGTH_SHORT).show();
break;
case R.id.item_scan:
startActivity(new Intent(MainActivity.this, ScanCaptureActivity.class));
break;
}
return true;
}
});
if (getIntent().getBooleanExtra(IMAction.ACTION_CONFLICT, false) && !isConflictDialogShow) {
showConflicDialog();
}
initViews();
requestPermissions();
mainPrestener.checkVersion();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
protected boolean onPrepareOptionsPanel(View view, Menu menu) {
//解决menu item设置的图标不显示
if (menu != null) {
if (menu.getClass() == MenuBuilder.class) {
try {
Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (Exception e) {
// Out.print(getClass().getSimpleName() + "onMenuOpened...unable to set icons for overflow menu" + e);
}
}
}
return super.onPrepareOptionsPanel(view, menu);
}
private void initViews() {
mTablayout = (TabLayout) findViewById(R.id.tabLayout);
mViewPager = (ViewPager) findViewById(R.id.viewPager);
fragments = new Fragment[]{new ConversationFragment(), new FragmentContacts(), new FragmentFind(), new FragmentProfile()};
mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return fragments[position];
}
@Override
public int getCount() {
return fragments.length;
}
});
mTablayout.setupWithViewPager(mViewPager);
tabs = new TabLayout.Tab[mTitles.length];
for (int i = 0; i < mTitles.length; i++) {
tabs[i] = mTablayout.getTabAt(i);
tabs[i].setCustomView(getBottomView(i, drawabls[i]));
}
}
@Override
protected void onStart() {
super.onStart();
mainPrestener.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (exceptionBuilder != null) {
exceptionBuilder.create().dismiss();
exceptionBuilder = null;
isConflictDialogShow = false;
}
}
private View getBottomView(final int index, int drawableRes) {
View view = getLayoutInflater().inflate(R.layout.widget_main_button, null);
Button button = (Button) view.findViewById(R.id.button);
button.setCompoundDrawablesWithIntrinsicBounds(0, drawableRes, 0, 0);
// button.setCompoundDrawables(null, dr, null, null);
button.setText(mTitles[index]);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (tabs[index] != null) {
tabs[index].select();
}
}
});
if (isCompatible(Build.VERSION_CODES.LOLLIPOP)) {
button.setStateListAnimator(null);
}
TextView textView = (TextView) view.findViewById(R.id.unread_msg_number);
if (index == 0) {
unreadLabel = textView;
} else if (index == 1) {
unreadInvitionLable = textView;
}
return view;
}
@Override
public void setPresenter(MainPrestener presenter) {
mainPrestener = presenter;
}
@Override
public Activity getBaseActivity() {
return this;
}
@Override
public void showConflicDialog() {
isConflictDialogShow = true;
//HTClientHelper.getInstance().logout(null);
String st = getResources().getString(R.string.Logoff_notification);
if (!MainActivity.this.isFinishing()) {
// clear up global variables
try {
if (exceptionBuilder == null)
exceptionBuilder = new android.app.AlertDialog.Builder(MainActivity.this);
exceptionBuilder.setTitle(st);
exceptionBuilder.setMessage(R.string.connect_conflict);
exceptionBuilder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
exceptionBuilder = null;
isConflictDialogShow = false;
HTApp.getInstance().setUserJson(null);
finish();
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
exceptionBuilder.setCancelable(false);
exceptionBuilder.show();
isConflict = true;
} catch (Exception e) {
Log.e(TAG, "---------color conflictBuilder error" + e.getMessage());
}
}
}
@Override
public void showUpdateDialog(String message, final String url, final String isForce) {
String title = getString(R.string.has_update);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View dialogView = View.inflate(MainActivity.this, R.layout.layout_alert_dialog_delete, null);
TextView tv_delete_people = (TextView) dialogView.findViewById(R.id.tv_delete_people);
View view_line_dialog = dialogView.findViewById(R.id.view_line_dialog);
TextView tv_delete_title = (TextView) dialogView.findViewById(R.id.tv_delete_title);
TextView tv_cancle = (TextView) dialogView.findViewById(R.id.tv_cancle);
TextView tv_ok = (TextView) dialogView.findViewById(R.id.tv_ok);
tv_delete_title.setText(title);
tv_delete_people.setText(message);
tv_cancle.setText(R.string.update_later);
tv_ok.setText(R.string.update_now);
builder.setView(dialogView);
final AlertDialog dialog = builder.show();
if (isForce.equals("1")) {
view_line_dialog.setVisibility(View.GONE);
tv_cancle.setVisibility(View.GONE);
tv_ok.setText(R.string.update_has);
dialog.setCancelable(false);//点击屏幕外不取消 返回键也没用
dialog.setCanceledOnTouchOutside(false); //点击屏幕外取消,返回键有用
} else {
dialog.setCancelable(true);//点击屏幕外取消 返回键也没用
dialog.setCanceledOnTouchOutside(true); //点击屏幕外取消,返回键有用
}
tv_cancle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
if (isForce.equals("1")) {
logout();
}
}
});
tv_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isForce.equals("1")) {
dialog.dismiss();
}
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.parse(url);
intent.setData(uri);
MainActivity.this.startActivity(intent);
}
});
}
@Override
public void onUnReadMsgs(int count) {
if (unreadLabel == null) {
return;
}
if (count > 0) {
unreadLabel.setText(String.valueOf(count));
unreadLabel.setVisibility(View.VISIBLE);
} else {
unreadLabel.setVisibility(View.INVISIBLE);
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent.getBooleanExtra(IMAction.ACTION_CONFLICT, false) && !isConflictDialogShow) {
showConflicDialog();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
moveTaskToBack(false);
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);
}
private void logout() {
HTClient.getInstance().logout(new HTClient.HTCallBack() {
@Override
public void onSuccess() {
HTApp.getInstance().setUserJson(null);
HTApp.getInstance().finishActivities();
finish();
}
@Override
public void onError() {
HTApp.getInstance().setUserJson(null);
HTApp.getInstance().finishActivities();
finish();
}
});
}
@TargetApi(23)
private void requestPermissions() {
PermissionsManager.getInstance().requestAllManifestPermissionsIfNecessary(this, new PermissionsResultAction() {
@Override
public void onGranted() {
// Toast.makeText(MainActivity.this, "All permissions have been granted", Toast.LENGTH_SHORT).show();
}
@Override
public void onDenied(String permission) {
//Toast.makeText(MainActivity.this, "Permission " + permission + " has been denied", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void showInvitionCount(int count) {
if (unreadInvitionLable == null){
return;
}
if (count > 0) {
// unreadInvitionLable.setText(String.valueOf(count));
unreadInvitionLable.setVisibility(View.VISIBLE);
} else {
unreadInvitionLable.setVisibility(View.INVISIBLE);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/MainBasePrester.java
================================================
package com.htmessage.yichatopen.activity.main;
import com.htmessage.yichatopen.activity.BasePresenter;
/**
* Created by huangfangyi on 2017/6/27.
* qq 84543217
*/
public interface MainBasePrester extends BasePresenter {
//检查更新
void checkVersion();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/MainPrestener.java
================================================
package com.htmessage.yichatopen.activity.main;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.utils.OkHttpUtils;
import com.htmessage.yichatopen.utils.Param;
import java.util.ArrayList;
import java.util.List;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
/**
* Created by huangfangyi on 2017/6/25.
* qq 84543217
*/
public class MainPrestener implements MainBasePrester {
private MainView mainView;
private Context context;
public MainPrestener(MainView _mainView){
this.mainView=_mainView;
mainView.setPresenter(this);
context=mainView.getBaseContext();
}
@Override
public void start() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
Intent intent = new Intent();
intent.setAction(android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("package:" + packageName));
context.startActivity(intent);
}
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
/**
* 获取VersionCode
*
* @return 当前应用的VersionCode
*/
public String getVersionCode() {
try {
PackageManager manager = context.getPackageManager();
PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
String version = String.valueOf(info.versionCode);
return version;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public void checkVersion() {
final String version = getVersionCode();
List params = new ArrayList<>();
params.add(new Param("system", "0"));
new OkHttpUtils(context).post(params, HTConstant.URL_CHECK_UPDATE, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
if (jsonObject != null) {
String serviceVersion = jsonObject.getString("newVersion");
String url = jsonObject.getString("url");
String info = jsonObject.getString("info");
String statue = jsonObject.getString("statue");
if (!version.equals(serviceVersion) && (Integer.valueOf(version) < Integer.valueOf(serviceVersion))) {
mainView.showUpdateDialog(info, url, statue);
}
}
}
@Override
public void onFailure(String errorMsg) {
}
});
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/MainView.java
================================================
package com.htmessage.yichatopen.activity.main;
import com.htmessage.yichatopen.activity.BaseView;
import com.htmessage.yichatopen.activity.main.contacts.FragmentContacts;
import com.htmessage.yichatopen.activity.main.conversation.ConversationFragment;
/**
* Created by huangfangyi on 2017/6/25.
* qq 84543217
*/
public interface MainView extends BaseView,ConversationFragment.NewMeesageListener,FragmentContacts.ContactsListener {
void showConflicDialog();
void showUpdateDialog( String message,String url,String isForce);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/BaseContactsPresenter.java
================================================
package com.htmessage.yichatopen.activity.main.contacts;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.activity.BasePresenter;
import java.util.List;
/**
* Created by huangfangyi on 2017/6/28.
* qq 84543217
*/
public interface BaseContactsPresenter extends BasePresenter{
List getContactsListInDb();
void deleteContacts(String userId);
void moveUserToBlack(String userId);
List sortList( List users);
void refreshContactsInServer();
int getInvitionCount();
int getContactsCount();
void clearInvitionCount();
void refreshContactsInLocal();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/ContactsAdapter.java
================================================
package com.htmessage.yichatopen.activity.main.contacts;
import android.content.Context;
import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.SectionIndexer;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.domain.User;
import java.util.ArrayList;
import java.util.List;
/**
* Created by huangfangyi on 2017/6/28.
* qq 84543217
*/
public class ContactsAdapter extends BaseAdapter implements SectionIndexer {
private Context context;
private List data;
public ContactsAdapter(Context context, List data) {
this.context = context;
this.data = data;
}
@Override
public int getCount() {
return data.size();
}
@Override
public User getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = View.inflate(context, R.layout.item_contact_list, null);
}
ViewHolder holder = (ViewHolder) convertView.getTag();
if (holder == null) {
holder = new ViewHolder();
holder.tvHeader = (TextView) convertView.findViewById(R.id.header);
holder.nameTextview = (TextView) convertView.findViewById(R.id.tv_name);
holder.iv_avatar = (ImageView) convertView.findViewById(R.id.iv_avatar);
convertView.setTag(holder);
}
User user = data.get(position);
holder.tvHeader.setVisibility(View.VISIBLE);
String nick = user.getNick();
String avatar = user.getAvatar();
String headerLetter = user.getInitialLetter();
String preHeaderLetter = getPreHeaderLeeter(position);
if (headerLetter.equals(preHeaderLetter)) {
holder.tvHeader.setVisibility(View.GONE);
} else {
holder.tvHeader.setVisibility(View.VISIBLE);
holder.tvHeader.setText(headerLetter);
}
holder.nameTextview.setText(nick);
Glide.with(context).load(avatar).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).error(R.drawable.default_avatar).into(holder.iv_avatar);
return convertView;
}
List list;
private SparseIntArray positionOfSection;
private SparseIntArray sectionOfPosition;
@Override
public Object[] getSections() {
positionOfSection = new SparseIntArray();
sectionOfPosition = new SparseIntArray();
int count = getCount();
list = new ArrayList();
list.add(context.getString(R.string.search_header));
positionOfSection.put(0, 0);
sectionOfPosition.put(0, 0);
for (int i = 1; i < count; i++) {
String letter = getItem(i).getInitialLetter();
System.err.println("contactadapter getsection getHeader:" + letter
+ " name:" + getItem(i).getUsername());
int section = list.size() - 1;
if (list.get(section) != null && !list.get(section).equals(letter)) {
list.add(letter);
section++;
positionOfSection.put(section, i);
}
sectionOfPosition.put(i, section);
}
return list.toArray(new String[list.size()]);
}
public int getPositionForSection(int section) {
return positionOfSection.get(section)+1;
}
public int getSectionForPosition(int position) {
return sectionOfPosition.get(position);
}
private class ViewHolder {
ImageView iv_avatar;
TextView nameTextview, tvHeader;
}
private String getPreHeaderLeeter(int position) {
if (position > 0) {
User user = getItem(position - 1);
return user.getInitialLetter();
}
return null;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/ContactsPresenter.java
================================================
package com.htmessage.yichatopen.activity.main.contacts;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.sdk.ChatType;
import com.htmessage.sdk.client.HTClient;
import com.htmessage.sdk.manager.HTChatManager;
import com.htmessage.sdk.model.CmdMessage;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.domain.InviteMessgeDao;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.domain.UserDao;
import com.htmessage.yichatopen.manager.ContactsManager;
import com.htmessage.yichatopen.utils.CommonUtils;
import com.htmessage.yichatopen.utils.OkHttpUtils;
import com.htmessage.yichatopen.utils.Param;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Created by huangfangyi on 2017/6/28.
* qq 84543217
*/
public class ContactsPresenter implements BaseContactsPresenter {
private ContactsView contactsView;
private List contacts;
private InviteMessgeDao inviteMessgeDao;
public ContactsPresenter (ContactsView view){
contactsView=view;
contactsView.setPresenter(this);
contacts=new ArrayList<>(ContactsManager.getInstance().getContactList().values());
inviteMessgeDao=new InviteMessgeDao(contactsView.getBaseContext());
}
@Override
public List getContactsListInDb() {
contacts= sortList(new ArrayList(ContactsManager.getInstance().getContactList().values()));
return contacts;
}
//删除好友
@Override
public void deleteContacts(String userId) {
Map users = ContactsManager.getInstance().getContactList();
User user = users.get(userId);
users.remove(user.getUsername());
contacts.remove(user);
deleteContact(user);
}
//移入黑名单
@Override
public void moveUserToBlack(final String userId) {
View diaglogView = View.inflate(contactsView.getBaseContext(), R.layout.layout_alert_dialog_delete, null);
TextView tv_delete_title = (TextView) diaglogView.findViewById(R.id.tv_delete_title);
TextView tv_delete_people = (TextView) diaglogView.findViewById(R.id.tv_delete_people);
TextView tv_cancle = (TextView) diaglogView.findViewById(R.id.tv_cancle);
TextView tv_ok = (TextView) diaglogView.findViewById(R.id.tv_ok);
tv_delete_title.setText(R.string.prompt);
tv_delete_people.setText(R.string.Into_the_blacklist);
AlertDialog.Builder builder = new AlertDialog.Builder(contactsView.getBaseActivity());
builder.setView(diaglogView);
final AlertDialog dialog = builder.show();
tv_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
showMoveToBlackDialog(userId);
}
});
tv_cancle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
//移除用户
public void deleteContactOnBroast(String id) {
Map users = ContactsManager.getInstance().getContactList();
User user = users.get(id);
users.remove(id);
InviteMessgeDao dao = new InviteMessgeDao(contactsView.getBaseActivity());
dao.deleteMessage(id);
UserDao userDao = new UserDao(contactsView.getBaseActivity());
userDao.deleteContact(id);
contacts.remove(user);
HTClient.getInstance().conversationManager().deleteConversationAndMessage(id);
}
/**
* 删除用户
*
* @param user
*/
private void deleteContact(final User user) {
final ProgressDialog pd = new ProgressDialog(contactsView.getBaseActivity());
pd.setMessage(contactsView.getBaseContext().getResources().getString(R.string.deleting));
pd.setCanceledOnTouchOutside(false);
pd.show();
List params = new ArrayList<>();
params.add(new Param(HTConstant.JSON_KEY_HXID, user.getUsername()));
new OkHttpUtils(contactsView.getBaseActivity()).post(params, HTConstant.URL_DELETE_FRIEND, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
pd.dismiss();
int code = jsonObject.getIntValue("code");
switch (code) {
case 1:
InviteMessgeDao dao = new InviteMessgeDao(contactsView.getBaseActivity());
dao.deleteMessage(user.getUsername());
UserDao userDao = new UserDao(contactsView.getBaseActivity());
userDao.deleteContact(user.getUsername());
HTClient.getInstance().conversationManager().deleteConversationAndMessage(user.getUsername());
sendDeleteCmd(user);
Toast.makeText(contactsView.getBaseActivity(), R.string.delete_sucess, Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(contactsView.getBaseActivity(), R.string.Delete_failed, Toast.LENGTH_SHORT).show();
break;
}
}
@Override
public void onFailure(String errorMsg) {
pd.dismiss();
Toast.makeText(contactsView.getBaseActivity(), R.string.Delete_failed, Toast.LENGTH_SHORT).show();
}
});
}
private void sendDeleteCmd(User user) {
JSONObject userJson = HTApp.getInstance().getUserJson();
CmdMessage customMessage = new CmdMessage();
JSONObject jsonObject = new JSONObject();
jsonObject.put("action", 1003);
JSONObject data = new JSONObject();
data.put("userId", userJson.getString("userId"));
data.put("nick", userJson.getString("nick"));
data.put("avatar", userJson.getString("avatar"));
data.put("role", userJson.getString(HTConstant.JSON_KEY_ROLE));
data.put("teamId", userJson.getString("teamId"));
jsonObject.put("data", data);
customMessage.setMsgId(UUID.randomUUID().toString());
customMessage.setFrom(HTApp.getInstance().getUsername());
customMessage.setTime(System.currentTimeMillis());
customMessage.setTo(user.getUsername());
customMessage.setBody(jsonObject.toJSONString());
customMessage.setChatType(ChatType.singleChat);
HTClient.getInstance().chatManager().sendCmdMessage(customMessage, new HTChatManager.HTMessageCallBack() {
@Override
public void onProgress() {
}
@Override
public void onSuccess() {
}
@Override
public void onFailure() {
}
});
}
@Override
public List sortList(List users) {
PinyinComparator comparator = new PinyinComparator();
Collections.sort(users, comparator);
return users;
}
public class PinyinComparator implements Comparator {
@Override
public int compare(User o1, User o2) {
String py1 = o1.getInitialLetter();
String py2 = o2.getInitialLetter();
if (py1.equals(py2)) {
return o1.getNick().compareTo(o2.getNick());
} else {
if ("#".equals(py1)) {
return 1;
} else if ("#".equals(py2)) {
return -1;
}
return py1.compareTo(py2);
}
}
}
@Override
public void refreshContactsInServer() {
List params = new ArrayList();
new OkHttpUtils(contactsView.getBaseContext()).post(params, HTConstant.URL_FriendList, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
int code = jsonObject.getIntValue("code");
switch (code) {
case 1:
JSONArray friends = jsonObject.getJSONArray("user");
if (friends != null || friends.size() != 0) {
List users = new ArrayList();
for (int i = 0; i < friends.size(); i++) {
JSONObject friend = friends.getJSONObject(i);
User user = CommonUtils.Json2User(friend);
users.add(user);
}
ContactsManager.getInstance().saveContactList(users);
contacts.clear();
contacts.addAll(sortList(users));
contactsView.refresh();
}
break;
}
}
@Override
public void onFailure(String errorMsg) {
}
});
}
@Override
public int getInvitionCount() {
int unreadAddressCountTotal = 0;
unreadAddressCountTotal = inviteMessgeDao.getUnreadMessagesCount();
return unreadAddressCountTotal;
}
@Override
public int getContactsCount() {
return contacts.size();
}
@Override
public void clearInvitionCount() {
inviteMessgeDao.saveUnreadMessageCount(0);
contactsView.showInvitionCount(0);
}
@Override
public void refreshContactsInLocal() {
contacts.clear();
contacts.addAll(sortList(new ArrayList(ContactsManager.getInstance().getContactList().values())));
contactsView.refresh();
}
@Override
public void start() {
}
/**
* 移入黑名单
* @param userId
*/
private void showMoveToBlackDialog(final String userId) {
Map users = ContactsManager.getInstance().getContactList();
final User user = users.get(userId);
users.remove(userId);
getContactsListInDb().remove(user);
final ProgressDialog dialog = new ProgressDialog(contactsView.getBaseContext());
dialog.setMessage(contactsView.getBaseContext().getString(R.string.Is_moved_into_blacklist));
dialog.show();
List params = new ArrayList<>();
params.add(new Param(HTConstant.JSON_KEY_HXID,userId));
new OkHttpUtils(contactsView.getBaseContext()).post(params, HTConstant.URL_ADD_BLACKLIST, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
dialog.dismiss();
int code = jsonObject.getIntValue("code");
switch (code){
case 1:
InviteMessgeDao dao = new InviteMessgeDao(contactsView.getBaseActivity());
dao.deleteMessage(userId);
UserDao userDao = new UserDao(contactsView.getBaseActivity());
userDao.deleteContact(userId);
HTClient.getInstance().conversationManager().deleteConversationAndMessage(userId);
Toast.makeText(contactsView.getBaseContext(), R.string.Move_into_blacklist_success, Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(contactsView.getBaseContext(), R.string.Move_into_blacklist_failure, Toast.LENGTH_SHORT).show();
break;
}
}
@Override
public void onFailure(String errorMsg) {
dialog.dismiss();
Toast.makeText(contactsView.getBaseContext(), R.string.Move_into_blacklist_failure, Toast.LENGTH_SHORT).show();
}
});
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/ContactsView.java
================================================
package com.htmessage.yichatopen.activity.main.contacts;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.activity.BaseView;
/**
* Created by huangfangyi on 2017/6/28.
* qq 84543217
*/
public interface ContactsView extends BaseView {
void showItemDialog(User user);
void showSiderBar();
void showInvitionCount(int count);
void showContactsCount(int count);
void refresh();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/FragmentContacts.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.activity.main.contacts;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.htmessage.yichatopen.IMAction;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.addfriends.newfriend.NewFriendsActivity;
import com.htmessage.yichatopen.activity.main.details.UserDetailsActivity;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.widget.HTAlertDialog;
/**
* contact list
*/
public class FragmentContacts extends Fragment implements View.OnClickListener, ContactsView {
private ContactsAdapter adapter;
private ListView listView;
private Sidebar sidebar;
private TextView tv_unread;
private TextView tv_total;
private ContactsPresenter contactsPresenter;
public interface ContactsListener {
void showInvitionCount(int count);
}
private ContactsListener contactsListener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
contactsPresenter = new ContactsPresenter(this);
if (context instanceof ContactsListener) {
contactsListener = (ContactsListener) context;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_contactlist, container, false);
listView = (ListView) root.findViewById(R.id.list);
View footerView = LayoutInflater.from(getActivity()).inflate(R.layout.item_contact_list_footer,
null);
View headView = LayoutInflater.from(getActivity()).inflate(R.layout.item_contact_list_header,
null);
listView.addHeaderView(headView);
listView.addFooterView(footerView);
sidebar = (Sidebar) root.findViewById(R.id.sidebar);
tv_unread = (TextView) headView.findViewById(R.id.tv_unread);
tv_total = (TextView) footerView.findViewById(R.id.tv_total);
showSiderBar();
headView.findViewById(R.id.re_newfriends).setOnClickListener(this);
headView.findViewById(R.id.re_chatroom).setOnClickListener(this);
headView.findViewById(R.id.re_tag).setOnClickListener(this);
headView.findViewById(R.id.re_public).setOnClickListener(this);
return root;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
adapter = new ContactsAdapter(getActivity(), contactsPresenter.getContactsListInDb());
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
if (position != 0 && position != adapter.getCount() + 1) {
User user = adapter.getItem(position - 1);
startActivity(new Intent(getActivity(), UserDetailsActivity.class)
.putExtra(HTConstant.KEY_USER_INFO, user.getUserInfo()));
}
}
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
if (position != 0 && position != adapter.getCount() + 1) {
User user = adapter.getItem(position - 1);
showItemDialog(user);
}
return true;
}
});
contactsPresenter.refreshContactsInServer();
registerBroadReciever();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.re_newfriends:
startActivityForResult(new Intent(getActivity(), NewFriendsActivity.class),10086);
contactsPresenter.clearInvitionCount();
break;
case R.id.re_chatroom:
Toast.makeText(getActivity(), R.string.open_notice, Toast.LENGTH_SHORT).show();
break;
case R.id.re_tag:
break;
case R.id.re_public:
break;
}
}
@Override
public void setPresenter(ContactsPresenter presenter) {
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
@Override
public void showItemDialog(final User user) {
HTAlertDialog fxAlertDialog = new HTAlertDialog(getContext(), null, new String[]{getResources().getString(R.string.delete)});
fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {
@Override
public void onClick(int position) {
switch (position) {
case 0:
contactsPresenter.deleteContacts(user.getUsername());
break;
case 1:
contactsPresenter.moveUserToBlack(user.getUsername());
break;
}
refresh();
}
});
}
@Override
public void showSiderBar() {
sidebar.setVisibility(View.VISIBLE);
sidebar.setListView(listView);
}
@Override
public void showInvitionCount(int count) {
if (count != 0) {
tv_unread.setVisibility(View.VISIBLE);
// tv_unread.setText( count+"");
} else {
tv_unread.setVisibility(View.GONE);
}
contactsListener.showInvitionCount(count);
}
@Override
public void showContactsCount(int count) {
tv_total.setText(count + getString(R.string.more_people));
}
@Override
public void refresh() {
adapter.notifyDataSetChanged();
showContactsCount(contactsPresenter.getContactsCount());
}
private class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (IMAction.ACTION_CONTACT_CHANAGED.equals(action)) {
contactsPresenter.refreshContactsInLocal();
} else if (IMAction.ACTION_INVITE_MESSAGE.equals(action)) {
showInvitionCount(1);
} else if (IMAction.CMD_DELETE_FRIEND.equals(action)) {
String userId = intent.getStringExtra(HTConstant.JSON_KEY_HXID);
contactsPresenter.deleteContactOnBroast(userId);
refresh();
}
}
}
private MyBroadcastReceiver myBroadcastReceiver;
private void registerBroadReciever() {
myBroadcastReceiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(IMAction.ACTION_CONTACT_CHANAGED);
intentFilter.addAction(IMAction.ACTION_INVITE_MESSAGE);
intentFilter.addAction(IMAction.CMD_DELETE_FRIEND);
LocalBroadcastManager.getInstance(getContext()).registerReceiver(myBroadcastReceiver, intentFilter);
}
@Override
public void onDestroy() {
try {
LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(myBroadcastReceiver);
} catch (Exception e) {
e.printStackTrace();
}
super.onDestroy();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK){
showInvitionCount(0);
}
super.onActivityResult(requestCode, resultCode, data);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/Sidebar.java
================================================
/**
* Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.activity.main.contacts;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HeaderViewListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.htmessage.yichatopen.R;
public class Sidebar extends View{
private Paint paint;
private TextView header;
private float height;
private ListView mListView;
private Context context;
public void setListView(ListView listView){
mListView = listView;
}
public Sidebar(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
private String[] sections = new String[]{"↑","☆","A","B","C","D","E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z","#"};
private void init(){
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.DKGRAY);
paint.setTextAlign(Align.CENTER);
paint.setTextSize(getResources().getDimensionPixelSize(R.dimen.sider_bar_textsize));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float center = getWidth() / 2;
height = getHeight() / sections.length;
for (int i = sections.length - 1; i > -1; i--) {
canvas.drawText(sections[i], center, height * (i+1), paint);
}
}
private int sectionForPoint(float y) {
int index = (int) (y / height);
if(index < 0) {
index = 0;
}
if(index > sections.length - 1){
index = sections.length - 1;
}
return index;
}
private void setHeaderTextAndscroll(MotionEvent event){
if (mListView == null) {
//check the mListView to avoid NPE. but the mListView shouldn't be null
//need to check the call stack later
return;
}
String headerString = sections[sectionForPoint(event.getY())];
header.setText(headerString);
HeaderViewListAdapter ha = (HeaderViewListAdapter) mListView.getAdapter();
ContactsAdapter adapter = (ContactsAdapter) ha.getWrappedAdapter();
// ContactAdapter adapter = (ContactAdapter) mListView.getAdapter();
String[] adapterSections = (String[]) adapter.getSections();
try {
for (int i = adapterSections.length - 1; i > -1; i--) {
if(adapterSections[i].equals(headerString)){
mListView.setSelection(adapter.getPositionForSection(i));
break;
}
}
} catch (Exception e) {
Log.e("setHeaderTextAndscroll", e.getMessage());
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:{
if(header == null){
header = (TextView) ((View)getParent()).findViewById(R.id.floating_header);
}
setHeaderTextAndscroll(event);
header.setVisibility(View.VISIBLE);
setBackgroundResource(R.drawable.sidebar_background_pressed);
return true;
}
case MotionEvent.ACTION_MOVE:{
setHeaderTextAndscroll(event);
return true;
}
case MotionEvent.ACTION_UP:
header.setVisibility(View.INVISIBLE);
setBackgroundColor(Color.TRANSPARENT);
return true;
case MotionEvent.ACTION_CANCEL:
header.setVisibility(View.INVISIBLE);
setBackgroundColor(Color.TRANSPARENT);
return true;
}
return super.onTouchEvent(event);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/BaseConversationPresenter.java
================================================
package com.htmessage.yichatopen.activity.main.conversation;
import com.htmessage.sdk.model.HTConversation;
import com.htmessage.sdk.model.HTMessage;
import com.htmessage.yichatopen.activity.BasePresenter;
import java.util.List;
/**
* Created by huangfangyi on 2017/6/27.
* qq 84543217
*/
public interface BaseConversationPresenter extends BasePresenter
{
List getAllConversations();
void deleteConversation(HTConversation conversation);
void setTopConversation(HTConversation conversation);
void cancelTopConversation(HTConversation conversation);
void refreshConversations();
void onNewMsgReceived(HTMessage htmessage);
int getUnreadMsgCount();
void markAllMessageRead(HTConversation conversation);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/ConversationAdapter.java
================================================
package com.htmessage.yichatopen.activity.main.conversation;
import android.content.Context;
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 android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.activity.chat.weight.emoji.SmileUtils;
import com.htmessage.yichatopen.manager.ContactsManager;
import com.htmessage.yichatopen.utils.DateUtils;
import com.htmessage.sdk.model.HTConversation;
import com.htmessage.sdk.model.HTMessage;
import com.htmessage.sdk.model.HTMessageTextBody;
import java.util.Date;
import java.util.List;
public class ConversationAdapter extends BaseAdapter {
private List htConversations;
private Context context;
public ConversationAdapter(Context context, List htConversations) {
this.context = context;
this.htConversations = htConversations;
}
@Override
public int getCount() {
return htConversations.size();
}
@Override
public HTConversation getItem(int position) {
return htConversations.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_conversation_single, parent, false);
}
ViewHolder holder = (ViewHolder) convertView.getTag();
if (holder == null) {
holder = new ViewHolder();
holder.tv_name = (TextView) convertView.findViewById(R.id.name);
holder.tv_content = (TextView) convertView.findViewById(R.id.message);
holder.tv_time = (TextView) convertView.findViewById(R.id.time);
holder.tv_unread = (TextView) convertView.findViewById(R.id.unread_msg_number);
holder.ivAvatar = (ImageView) convertView.findViewById(R.id.avatar);
holder.tv_group_tag=(TextView) convertView.findViewById(R.id.tv_group_tag);
holder.re_main=(RelativeLayout) convertView.findViewById(R.id.re_main);
convertView.setTag(holder);
}
HTConversation htConversation = getItem(position);
HTMessage htMessage = null;
List messages = htConversation.getAllMessages();
if (messages.size() > 0) {
htMessage = htConversation.getLastMessage();
}
String userId = htConversation.getUserId();
User user = ContactsManager.getInstance().getContactList().get(userId);
holder.tv_group_tag.setVisibility(View.INVISIBLE);
if (user != null) {
holder.tv_name.setText(user.getNick());
Glide.with(context).load(user.getAvatar()).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(holder.ivAvatar);
} else {
holder.tv_name.setText(userId);
Glide.with(context).load(R.drawable.default_avatar).into(holder.ivAvatar);
}
if (htConversation.getUnReadCount() > 0) {
// show unread message count
holder.tv_unread.setText(String.valueOf(htConversation.getUnReadCount()));
holder.tv_unread.setVisibility(View.VISIBLE);
} else {
holder.tv_unread.setVisibility(View.INVISIBLE);
}
if (htMessage != null) {
holder.tv_content.setText(SmileUtils.getSmiledText(context, getContent(htMessage)),
TextView.BufferType.SPANNABLE);
holder.tv_time.setText(DateUtils.getTimestampString(new Date(htMessage.getTime())));
}else{
holder.tv_content.setText("");
holder.tv_time.setText(DateUtils.getTimestampString(new Date(htConversation.getTime())));
}
if(htConversation.getTopTimestamp()!=0){
holder.re_main.setBackgroundResource(R.drawable.list_item_bg_gray);
}else{
holder.re_main.setBackgroundResource(R.drawable.list_item_bg_white);
}
return convertView;
}
private static class ViewHolder {
/**
* 和谁的聊天记录
*/
TextView tv_name;
/**
* 消息未读数
*/
TextView tv_unread;
/**
* 最后一条消息的内容
*/
TextView tv_content;
/**
* 最后一条消息的时间
*/
TextView tv_time;
ImageView ivAvatar;
//群组的标识
TextView tv_group_tag;
RelativeLayout re_main;
}
protected final static String[] msgs = { "[图片消息]", "[语音消息]"};
private String getContent(HTMessage message) {
String notifyText = "";
if (message.getType() == null) {
return "";
}
switch (message.getType()) {
case TEXT:
HTMessageTextBody textBody = (HTMessageTextBody) message.getBody();
String content = textBody.getContent();
if (content != null) {
notifyText += content;
} else {
notifyText += msgs[0];
}
break;
case IMAGE:
notifyText += msgs[0];
break;
case VOICE:
notifyText += msgs[1];
break;
}
return notifyText;
}
// /**
// * 根据消息内容和消息类型获取消息内容提示
// *
// * @param message
// * @param context
// * @return
// */
// private String getMessageDigest(HTMessage message, Context context) {
// String digest = "";
// switch (message.getType()) {
// case LOCATION: // 位置消息
// if (message.getDirect() == HTMessage.Direct.RECEIVE) {
//
// digest = getStrng(context, R.string.location_recv);
// digest = String.format(digest, message.getFrom());
// return digest;
// } else {
// // digest = EasyUtils.getAppResourceString(context,
// // "location_prefix");
// digest = getStrng(context, R.string.location_prefix);
// }
// break;
// case IMAGE: // 图片消息
//
// digest = getStrng(context, R.string.picture);
//
// break;
// case VOICE:// 语音消息
// digest = getStrng(context, R.string.voice);
// break;
// case VIDEO: // 视频消息
// digest = getStrng(context, R.string.video);
// break;
// case TXT: // 文本消息
// if (!message.getBooleanAttribute(
// Constant.MESSAGE_ATTR_IS_VOICE_CALL, false)) {
// TextMessageBody txtBody = (TextMessageBody) message.getBody();
// digest = txtBody.getMessage();
// } else {
// TextMessageBody txtBody = (TextMessageBody) message.getBody();
// digest = getStrng(context, R.string.voice_call)
// + txtBody.getMessage();
// }
// break;
// case FILE: // 普通文件消息
// digest = getStrng(context, R.string.file);
// break;
// default:
// System.err.println("error, unknow type");
// return "";
// }
//
// return digest;
// }
String getStrng(Context context, int resId) {
return context.getResources().getString(resId);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/ConversationFragment.java
================================================
package com.htmessage.yichatopen.activity.main.conversation;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.htmessage.sdk.ChatType;
import com.htmessage.sdk.model.HTConversation;
import com.htmessage.sdk.utils.MessageUtils;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.IMAction;
import com.htmessage.yichatopen.activity.chat.ChatActivity;
import com.htmessage.yichatopen.utils.CommonUtils;
import com.htmessage.yichatopen.widget.HTAlertDialog;
public class ConversationFragment extends Fragment implements ConversationView {
private ListView listView;
private ConversationAdapter adapter;
public RelativeLayout errorItem;
public TextView errorText;
public NewMeesageListener mListener;
private ConversationPresenter conPresenter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_home, container, false);
errorItem = (RelativeLayout) root.findViewById(R.id.rl_error_item);
errorText = (TextView) errorItem.findViewById(R.id.tv_connect_errormsg);
listView = (ListView) root.findViewById(R.id.list);
return root;
}
@Override
public void setPresenter(ConversationPresenter presenter) {
// conPresenter = presenter;
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
@Override
public void showItemDialog(final HTConversation htConversation) {
String topTitle = getString(R.string.stick_conversation);
if (htConversation.getTopTimestamp() != 0) {
//已经置顶的会话,显示取消置顶
topTitle = getString(R.string.cancle_stick_conversation);
}
HTAlertDialog fxAlertDialog = new HTAlertDialog(getActivity(), null, new String[]{getString(R.string.delete), topTitle});
fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {
@Override
public void onClick(int position) {
if (position == 0) {
conPresenter.deleteConversation(htConversation);
} else if (position == 1) {
if (htConversation.getTopTimestamp() != 0) {//如果是置顶过的 就取消置顶
conPresenter.cancelTopConversation(htConversation);
} else { //如果是没有置顶的就置顶
conPresenter.setTopConversation(htConversation);
}
}
}
});
}
@Override
public void refresh() {
conPresenter.refreshConversations();
adapter.notifyDataSetChanged();
onUnreadMsgChange();
}
public interface NewMeesageListener {
//返回多少条未读消息
void onUnReadMsgs(int count);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
conPresenter = new ConversationPresenter(this);
if (context instanceof NewMeesageListener) {
mListener = ((NewMeesageListener) context);
onUnreadMsgChange();
}
}
private void onUnreadMsgChange() {
mListener.onUnReadMsgs(conPresenter.getUnreadMsgCount());
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
adapter = new ConversationAdapter(getActivity(), conPresenter.getAllConversations());
// 设置adapter
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
HTConversation htConversation = adapter.getItem(position);
conPresenter.markAllMessageRead(htConversation);
Intent intent = new Intent(getActivity(), ChatActivity.class).putExtra("userId", htConversation.getUserId());
if (htConversation.getChatType() == ChatType.groupChat) {
intent.putExtra("chatType", MessageUtils.CHAT_GROUP);
}
startActivity(intent);
}
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView> adapterView, View view, int i, long l) {
HTConversation htConversation = adapter.getItem(i);
showItemDialog(htConversation);
return true;
}
});
registerConnectionBroadCast();
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (IMAction.ACTION_CONNECTION_CHANAGED.equals(intent.getAction())) {
boolean isConnected = intent.getBooleanExtra("state", true);
if (isConnected) {
errorItem.setVisibility(View.GONE);
} else {
errorItem.setVisibility(View.VISIBLE);
if (CommonUtils.isNetWorkConnected(getContext())) {
errorText.setText(R.string.can_not_connect_chat_server_connection);
} else {
errorText.setText(R.string.the_current_network);
}
}
} else if (IMAction.ACTION_NEW_MESSAGE.equals(intent.getAction()) || IMAction.ACTION_MESSAGE_WITHDROW.equals(intent.getAction())
|| IMAction.ACTION_REMOVED_FROM_GROUP.equals(intent.getAction()) || IMAction.CMD_DELETE_FRIEND.equals(intent.getAction())) {
// 收到新消息,收到撤回消息,收到群相关消息-被提出群聊
refresh();
}
}
};
private void registerConnectionBroadCast() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(IMAction.ACTION_CONNECTION_CHANAGED);
intentFilter.addAction(IMAction.ACTION_NEW_MESSAGE);
intentFilter.addAction(IMAction.ACTION_MESSAGE_WITHDROW);
intentFilter.addAction(IMAction.CMD_DELETE_FRIEND);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(broadcastReceiver, intentFilter);
}
@Override
public void onDestroy() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(broadcastReceiver);
super.onDestroy();
}
@Override
public void onResume() {
super.onResume();
refresh();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/ConversationPresenter.java
================================================
package com.htmessage.yichatopen.activity.main.conversation;
import android.content.Context;
import com.htmessage.sdk.client.HTClient;
import com.htmessage.sdk.model.HTConversation;
import com.htmessage.sdk.model.HTMessage;
import java.util.List;
/**
* Created by huangfangyi on 2017/6/27.
* qq 84543217
*/
public class ConversationPresenter implements BaseConversationPresenter {
private ConversationView conversationView;
private Context context;
private List allConversations;
public ConversationPresenter(ConversationView view) {
conversationView = view;
conversationView.setPresenter(this);
context = conversationView.getBaseContext();
allConversations = HTClient.getInstance().conversationManager().getAllConversations();
}
@Override
public void start() {
}
@Override
public List getAllConversations() {
return allConversations;
}
@Override
public void deleteConversation(HTConversation htConversation) {
allConversations.remove(htConversation);
HTClient.getInstance().messageManager().deleteUserMessage(htConversation.getUserId(), true);
conversationView.refresh();
}
@Override
public void setTopConversation(HTConversation htConversation) {
HTClient.getInstance().conversationManager().setConversationTop(htConversation,System.currentTimeMillis());
conversationView.refresh();
}
@Override
public void cancelTopConversation(HTConversation htConversation) {
HTClient.getInstance().conversationManager().setConversationTop(htConversation,0);
conversationView.refresh();
}
@Override
public void refreshConversations() {
allConversations.clear();
allConversations.addAll(HTClient.getInstance().conversationManager().getAllConversations());
}
@Override
public void onNewMsgReceived(HTMessage htMessage) {
}
@Override
public int getUnreadMsgCount() {
int unreadMsgCountTotal = 0;
if (allConversations.size() != 0 && allConversations != null) {
for (int i = 0; i < allConversations.size(); i++) {
unreadMsgCountTotal += allConversations.get(i).getUnReadCount();
}
}
return unreadMsgCountTotal;
}
@Override
public void markAllMessageRead(HTConversation conversation) {
HTClient.getInstance().conversationManager().markAllMessageRead(conversation.getUserId());
conversationView.refresh();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/ConversationView.java
================================================
package com.htmessage.yichatopen.activity.main.conversation;
import com.htmessage.sdk.model.HTConversation;
import com.htmessage.yichatopen.activity.BaseView;
/**
* Created by huangfangyi on 2017/6/27.
* qq 84543217
*/
public interface ConversationView extends BaseView{
void showItemDialog(HTConversation htConversation);
void refresh();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailesFragment.java
================================================
package com.htmessage.yichatopen.activity.main.details;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.alibaba.fastjson.JSONObject;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.addfriends.add.end.AddFriendsFinalActivity;
import com.htmessage.yichatopen.activity.chat.ChatActivity;
/**
* 项目名称:yichat0504
* 类描述:UserDetailesFragment 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 11:52
* 邮箱:814326663@qq.com
*/
public class UserDetailesFragment extends Fragment implements UserDetailsView ,View.OnClickListener{
private UserDetailsPrester prester;
private Button btnMsg,btnAdd;
private ImageView iv_avatar,iv_sex;
private TextView tv_name,tv_yichat_number,tv_mobile,tv_region,tv_mixin;
private RelativeLayout rl_region,rl_yichat_id,re_mobile;
private Dialog dialog;
private JSONObject userJson;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dialog = HTApp.getInstance().createLoadingDialog(getBaseActivity(),getString(R.string.now_refresh_msg));
dialog.setCancelable(true);
dialog.setCanceledOnTouchOutside(true);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View infoView = inflater.inflate(R.layout.activity_userinfo, container, false);
initView(infoView);
getData();
setLstenter();
return infoView;
}
private void getData() {
if (!TextUtils.isEmpty(getFxid())){
prester.refreshInfo(getFxid(),true);
return;
}
if (getUserJson() == null){
getBaseActivity().finish();
return;
}
showUi(getUserJson());
if (prester.isFriend(getUserJson().getString(HTConstant.JSON_KEY_HXID))){
prester.refreshInfo(getUserJson().getString(HTConstant.JSON_KEY_HXID),false);
}else{
prester.refreshInfo(getUserJson().getString(HTConstant.JSON_KEY_HXID),true);
}
}
private void setLstenter() {
btnAdd.setOnClickListener(this);
btnMsg.setOnClickListener(this);
}
private void initView(View infoView) {
btnMsg = (Button) infoView.findViewById(R.id.btn_msg);
btnAdd= (Button) infoView.findViewById(R.id.btn_add);
iv_avatar = (ImageView) infoView.findViewById(R.id.iv_avatar);
iv_sex = (ImageView) infoView.findViewById(R.id.iv_sex);
tv_name = (TextView) infoView.findViewById(R.id.tv_name);
tv_yichat_number = (TextView) infoView.findViewById(R.id.tv_yichat_number);
tv_mobile = (TextView) infoView.findViewById(R.id.tv_mobile);
tv_region = (TextView) infoView.findViewById(R.id.tv_region);
tv_mixin = (TextView) infoView.findViewById(R.id.tv_mixin);
rl_region = (RelativeLayout) infoView.findViewById(R.id.rl_region);
rl_yichat_id = (RelativeLayout) infoView.findViewById(R.id.rl_yichat_id);
re_mobile = (RelativeLayout) infoView.findViewById(R.id.re_mobile);
}
@Override
public void onRefreshSuccess(String msg) {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onRefreshFailed(String error) {
Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();
}
@Override
public String getFxid() {
return getBaseActivity().getIntent().getStringExtra(HTConstant.JSON_KEY_HXID);
}
@Override
public JSONObject getUserJson() {
String extra = getBaseActivity().getIntent().getStringExtra(HTConstant.KEY_USER_INFO);
JSONObject object = JSONObject.parseObject(extra);
return object;
}
@Override
public void showDialog() {
if (dialog!=null){
dialog.show();
}
}
@Override
public void hintDialog() {
if (dialog!=null){
dialog.dismiss();
}
}
@Override
public void showUi(JSONObject object) {
this.userJson = object;
String hxid = object.getString(HTConstant.JSON_KEY_HXID);
String yichatId = object.getString(HTConstant.JSON_KEY_FXID);
String Tel = object.getString(HTConstant.JSON_KEY_TEL);
String province = object.getString(HTConstant.JSON_KEY_PROVINCE);
String city = object.getString(HTConstant.JSON_KEY_CITY);
String sign = object.getString(HTConstant.JSON_KEY_SIGN);
if (!TextUtils.isEmpty(yichatId)){
tv_mixin.setText(getString(R.string.app_id)+yichatId);
}else{
tv_mixin.setText(getString(R.string.app_id)+getString(R.string.not_set));
}
if (!TextUtils.isEmpty(sign)) {
tv_yichat_number.setText(sign);
} else {
tv_yichat_number.setText(R.string.not_set);
}
if (!TextUtils.isEmpty(Tel)){
tv_mobile.setText(Tel);
}else{
tv_mobile.setText(R.string.not_set);
}
if (!TextUtils.isEmpty(province) && !TextUtils.isEmpty(city)){
tv_region.setText(province+" "+city);
if (province.equals(city)) {
tv_region.setText(city);
}
}else{
tv_region.setText(R.string.not_set);
}
String nick = object.getString(HTConstant.JSON_KEY_NICK);
String avatarUrl =object.getString(HTConstant.JSON_KEY_AVATAR);
if(!TextUtils.isEmpty(avatarUrl)){
if (!avatarUrl.contains("http:")){
avatarUrl = HTConstant.URL_AVATAR+avatarUrl;
}
}
Glide.with(this).load(avatarUrl).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(iv_avatar);
tv_name.setText(nick);
String sex = object.getString(HTConstant.JSON_KEY_SEX);
if (!TextUtils.isEmpty(sex)){
if ("1".equals(sex) || sex.equals(getString(R.string.male))) {
iv_sex.setImageResource(R.drawable.icon_male);
} else if ("0".equals(sex) || sex.equals(getString(R.string.female))){
iv_sex.setImageResource(R.drawable.icon_female);
}
}else{
iv_sex.setImageResource(R.drawable.icon_male);
}
//资料是自己
if (prester.isMe(hxid)) {
btnMsg.setVisibility(View.GONE);
btnAdd.setVisibility(View.GONE);
return;
}
//不是好友的
if (!prester.isFriend(hxid)) {
btnMsg.setVisibility(View.GONE);
btnAdd.setVisibility(View.VISIBLE);
return;
}
}
@Override
public void setPresenter(UserDetailsPrester presenter) {
this.prester = presenter;
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_add:
startActivity(new Intent(getBaseActivity(), AddFriendsFinalActivity.class).putExtra(HTConstant.KEY_USER_INFO, userJson.toJSONString()));
break;
case R.id.btn_msg:
startActivity(new Intent(getBaseActivity(), ChatActivity.class).putExtra("userId",userJson.getString(HTConstant.JSON_KEY_HXID)));
break;
}
}
@Override
public void onDestroy() {
prester.onDestory();
super.onDestroy();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailsActivity.java
================================================
package com.htmessage.yichatopen.activity.main.details;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import com.htmessage.yichatopen.activity.BaseActivity;
import com.htmessage.yichatopen.R;
/**
* Created by huangfangyi on 2016/7/6.\
* QQ:84543217
*/
public class UserDetailsActivity extends BaseActivity {
/**
*
* 用户详情页接收两种传值
* 1:用户完整资料的JSON字符串-userInfo-这种情况如果是好友进行刷新
* 2:只传用户的hxid,这种情况直接从网络取数据显示-如果是好友,刷新资料
*
*/
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.activity_base);
setTitle(R.string.Detailed_information);
UserDetailesFragment fragment = (UserDetailesFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (fragment == null){
fragment = new UserDetailesFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame,fragment);
transaction.commit();
}
new UserDetailsPrester(fragment);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailsBasePrester.java
================================================
package com.htmessage.yichatopen.activity.main.details;
import com.htmessage.yichatopen.activity.BasePresenter;
/**
* 项目名称:yichat0504
* 类描述:UserDetailsBasePrester 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 11:35
* 邮箱:814326663@qq.com
*/
public interface UserDetailsBasePrester extends BasePresenter {
void onDestory();
void refreshInfo(String userId, boolean backTask);
boolean isMe(String userId);
boolean isFriend(String userId);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailsPrester.java
================================================
package com.htmessage.yichatopen.activity.main.details;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.domain.UserDao;
import com.htmessage.yichatopen.manager.ContactsManager;
import com.htmessage.yichatopen.utils.CommonUtils;
import com.htmessage.yichatopen.utils.OkHttpUtils;
import com.htmessage.yichatopen.utils.Param;
import java.util.ArrayList;
import java.util.List;
/**
* 项目名称:yichat0504
* 类描述:UserDetailsPrester 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 11:40
* 邮箱:814326663@qq.com
*/
public class UserDetailsPrester implements UserDetailsBasePrester {
private UserDetailsView detailsView;
public UserDetailsPrester(UserDetailsView detailsView) {
this.detailsView = detailsView;
this.detailsView.setPresenter(this);
}
@Override
public void onDestory() {
detailsView = null;
}
@Override
public void refreshInfo(final String userId, final boolean backTask) {
if (!backTask){
detailsView.showDialog();
}
List parms = new ArrayList<>();
parms.add(new Param("userId", userId));
new OkHttpUtils(detailsView.getBaseContext()).post(parms, HTConstant.URL_Get_UserInfo, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
int code = jsonObject.getInteger("code");
if (!backTask){
detailsView.hintDialog();
}
switch (code){
case 1:
JSONObject json = jsonObject.getJSONObject("user");
//刷新ui
if (isFriend(userId)) {
User user = CommonUtils.Json2User(json);
UserDao dao = new UserDao(detailsView.getBaseContext());
dao.saveContact(user);
ContactsManager.getInstance().getContactList().put(user.getUsername(), user);
}
detailsView.showUi(json);
break;
default:
detailsView.hintDialog();
break;
}
}
@Override
public void onFailure(String errorMsg) {
detailsView.onRefreshFailed(errorMsg);
if (!backTask){
detailsView.hintDialog();
}
}
});
}
@Override
public boolean isMe(String userId) {
return HTApp.getInstance().getUsername().equals(userId);
}
@Override
public boolean isFriend(String userId) {
return ContactsManager.getInstance().getContactList().containsKey(userId);
}
@Override
public void start() {
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailsView.java
================================================
package com.htmessage.yichatopen.activity.main.details;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.activity.BaseView;
/**
* 项目名称:yichat0504
* 类描述:UserDetailsView 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 11:45
* 邮箱:814326663@qq.com
*/
public interface UserDetailsView extends BaseView {
void onRefreshSuccess(String msg);
void onRefreshFailed(String error);
String getFxid();
JSONObject getUserJson();
void showDialog();
void hintDialog();
void showUi(JSONObject object);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/find/FragmentFind.java
================================================
package com.htmessage.yichatopen.activity.main.find;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.ScanCaptureActivity;
import com.htmessage.yichatopen.activity.main.find.recentlypeople.PeopleRecentlyActivity;
public class FragmentFind extends Fragment implements View.OnClickListener {
private RelativeLayout rl_friends, re_qrcode, rl_near;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_find, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
if (savedInstanceState != null
&& savedInstanceState.getBoolean("isConflict", false))
return;
super.onActivityCreated(savedInstanceState);
initView();
initData();
setListener();
}
private void setListener() {
rl_friends.setOnClickListener(this);
re_qrcode.setOnClickListener(this);
rl_near.setOnClickListener(this);
}
private void initData() {
}
private void initView() {
rl_friends = (RelativeLayout) getView().findViewById(R.id.rl_friends);
re_qrcode = (RelativeLayout) getView().findViewById(R.id.re_qrcode);
rl_near = (RelativeLayout) getView().findViewById(R.id.rl_near);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.rl_friends://志工圈
break;
case R.id.re_qrcode: //扫一扫
startActivity(new Intent(getActivity(), ScanCaptureActivity.class));
break;
case R.id.rl_near://最近在线
startActivity(new Intent(getActivity(), PeopleRecentlyActivity.class));
break;
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyActivity.java
================================================
package com.htmessage.yichatopen.activity.main.find.recentlypeople;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.BaseActivity;
/**
* 项目名称:yichat0504
* 类描述:PeopleRecentlyActivity 描述:
* 创建人:songlijie
* 创建时间:2017/7/5 16:53
* 邮箱:814326663@qq.com
*/
public class PeopleRecentlyActivity extends BaseActivity {
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.activity_base);
setTitle(R.string.people_time);
PeopleRecentlyFragment peopleRecentlyFragment =
(PeopleRecentlyFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (peopleRecentlyFragment == null) {
// Create the fragment
peopleRecentlyFragment = new PeopleRecentlyFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame, peopleRecentlyFragment);
transaction.commit();
}
PeopleRecentlyPrestener prestener = new PeopleRecentlyPrestener(peopleRecentlyFragment);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyAdapter.java
================================================
package com.htmessage.yichatopen.activity.main.find.recentlypeople;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.alibaba.fastjson.JSONObject;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.utils.DateUtils;
import java.util.ArrayList;
import java.util.List;
/**
* 项目名称:yichat0504
* 类描述:PeopleRecentlyAdapter 描述:
* 创建人:songlijie
* 创建时间:2017/7/5 17:17
* 邮箱:814326663@qq.com
*/
public class PeopleRecentlyAdapter extends BaseAdapter {
private Context context;
private List peoples = new ArrayList<>();
public PeopleRecentlyAdapter(Context context, List peoples) {
this.context = context;
this.peoples = peoples;
}
@Override
public int getCount() {
return peoples.size();
}
@Override
public JSONObject getItem(int position) {
return peoples.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(parent.getContext(), R.layout.item_people_recently, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
JSONObject jsonObject = peoples.get(position);
String nick = jsonObject.getString(HTConstant.JSON_KEY_NICK);
if (TextUtils.isEmpty(nick)) {
nick = jsonObject.getString(HTConstant.JSON_KEY_HXID);
}
String recentlytime = jsonObject.getString("recentlyTime");
String serviceTime = jsonObject.getString("serviceTime");
long l = Long.valueOf(recentlytime) * 1000;
long l2 = Long.valueOf(serviceTime) * 1000;
String difference = DateUtils.getTimeDifference(parent.getContext(),l, l2);
String avatar = null;
if (jsonObject.containsKey(HTConstant.JSON_KEY_AVATAR)) {
avatar = jsonObject.getString(HTConstant.JSON_KEY_AVATAR);
if (!TextUtils.isEmpty(avatar)) {
if (!avatar.contains("http")) {
avatar = HTConstant.baseOssUrl + avatar;
}
}
}
String sex = jsonObject.getString(HTConstant.JSON_KEY_SEX);
if (!TextUtils.isEmpty(sex)) {
if ("1".equals(sex) || sex.equals(parent.getContext().getString(R.string.male))) {
holder.iv_sex.setImageResource(R.drawable.icon_male);
} else if ("0".equals(sex) || sex.equals(parent.getContext().getString(R.string.female))) {
holder.iv_sex.setImageResource(R.drawable.icon_female);
}
} else {
holder.iv_sex.setImageResource(R.drawable.icon_male);
}
String sign = jsonObject.getString(HTConstant.JSON_KEY_SIGN);
if (!TextUtils.isEmpty(sign)) {
holder.ll_sign.setVisibility(View.VISIBLE);
holder.tv_sign.setText(sign);
} else {
holder.ll_sign.setVisibility(View.GONE);
}
holder.tv_name.setText(nick);
holder.tv_time.setText(difference);//DateUtils.getStringTime(Long.valueOf(recentlytime) * 1000)
Glide.with(parent.getContext()).load(avatar).placeholder(R.drawable.default_avatar).error(R.drawable.default_avatar).diskCacheStrategy(DiskCacheStrategy.ALL).into(holder.iv_avatar);
return convertView;
}
private class ViewHolder {
private TextView tv_name, tv_time, tv_sign;
private ImageView iv_avatar, iv_sex;
private LinearLayout ll_sign;
public ViewHolder(View view) {
tv_name = (TextView) view.findViewById(R.id.tv_name);
tv_time = (TextView) view.findViewById(R.id.tv_time);
tv_sign = (TextView) view.findViewById(R.id.tv_sign);
iv_avatar = (ImageView) view.findViewById(R.id.iv_avatar);
iv_sex = (ImageView) view.findViewById(R.id.iv_sex);
ll_sign = (LinearLayout) view.findViewById(R.id.ll_sign);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyBasePrestener.java
================================================
package com.htmessage.yichatopen.activity.main.find.recentlypeople;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.activity.BasePresenter;
/**
* 项目名称:yichat0504
* 类描述:PeopleRecentlyBasePrestener 描述:
* 创建人:songlijie
* 创建时间:2017/7/5 16:28
* 邮箱:814326663@qq.com
*/
public interface PeopleRecentlyBasePrestener extends BasePresenter {
void requestData(int page,int pageSize,boolean loadMore);
void onListClickListener(JSONObject object);
void onDestory();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyFragment.java
================================================
package com.htmessage.yichatopen.activity.main.find.recentlypeople;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.widget.swipyrefresh.SwipyRefreshLayout;
import java.util.ArrayList;
import java.util.List;
/**
* 项目名称:yichat0504
* 类描述:PeopleRecentlyFragment 描述:
* 创建人:songlijie
* 创建时间:2017/7/5 16:54
* 邮箱:814326663@qq.com
*/
public class PeopleRecentlyFragment extends Fragment implements PeopleRecentlyView,AdapterView.OnItemClickListener ,SwipyRefreshLayout.OnRefreshListener{
private PeopleRecentlyPrestener prestener;
private Dialog diallog;
private SwipyRefreshLayout swipyrefresh;
private ListView listview_people_recently;
private List peoples = new ArrayList<>();
private PeopleRecentlyAdapter adapter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
diallog = HTApp.getInstance().createLoadingDialog(getBaseContext(),getString(R.string.loading));
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View timeview = inflater.inflate(R.layout.activity_people_recently, container, false);
initView(timeview);
initData();
setListener();
return timeview;
}
private void setListener() {
listview_people_recently.setOnItemClickListener(this);
swipyrefresh.setOnRefreshListener(this);
}
private void initData() {
adapter = new PeopleRecentlyAdapter(getBaseContext(), peoples);
listview_people_recently.setAdapter(adapter);
onRefresh(1);
}
private void initView(View timeview) {
swipyrefresh = (SwipyRefreshLayout)timeview.findViewById(R.id.swipyrefresh);
listview_people_recently = (ListView) timeview.findViewById(R.id.listview_people_recently);
}
@Override
public void showLoadingDialog() {
if (diallog!=null){
diallog.show();
}
}
@Override
public void hideLoadingDialog() {
if (diallog!=null){
diallog.dismiss();
}
swipyrefresh.setRefreshing(false);
}
@Override
public void onRequestSuccess(List peopleList) {
swipyrefresh.setRefreshing(false);
peoples.addAll(peopleList);
adapter.notifyDataSetChanged();
}
@Override
public void onRequestFailed(String errorMsg) {
swipyrefresh.setRefreshing(false);
Toast.makeText(getBaseContext(), errorMsg, Toast.LENGTH_SHORT).show();
}
@Override
public void setPresenter(PeopleRecentlyPrestener presenter) {
this.prestener = presenter;
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
JSONObject item = adapter.getItem(position);
prestener.onListClickListener(item);
}
@Override
public void onRefresh(int index) {
peoples.clear();
index = 1;
prestener.requestData(index,20,false);
}
@Override
public void onLoad(int index) {
index++;
prestener.requestData(index,20,true);
}
@Override
public void onDestroy() {
prestener.onDestory();
super.onDestroy();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyPrestener.java
================================================
package com.htmessage.yichatopen.activity.main.find.recentlypeople;
import android.content.Intent;
import android.util.Log;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.main.details.UserDetailsActivity;
import com.htmessage.yichatopen.utils.OkHttpUtils;
import com.htmessage.yichatopen.utils.Param;
import java.util.ArrayList;
import java.util.List;
/**
* 项目名称:yichat0504
* 类描述:PeopleRecentlyPrestener 描述:
* 创建人:songlijie
* 创建时间:2017/7/5 16:34
* 邮箱:814326663@qq.com
*/
public class PeopleRecentlyPrestener implements PeopleRecentlyBasePrestener {
private PeopleRecentlyView timeView;
public PeopleRecentlyPrestener(PeopleRecentlyView timeView) {
this.timeView = timeView;
this.timeView.setPresenter(this);
}
@Override
public void requestData(int page, int pageSize, final boolean loadMore) {
timeView.showLoadingDialog();
List params = new ArrayList<>();
params.add(new Param("currentPage",String.valueOf(page)));
params.add(new Param("pageSize",String.valueOf(pageSize)));
new OkHttpUtils(timeView.getBaseContext()).post(params, HTConstant.URL_GET_RECENTLY_PEOPLE, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
timeView.hideLoadingDialog();
int code = jsonObject.getIntValue("code");
switch (code){
case 1:
List peoples = new ArrayList();
JSONArray data = jsonObject.getJSONArray("data");
if (data!=null && data.size()!=0){
for (int i = 0; i {
void showLoadingDialog();
void hideLoadingDialog();
void onRequestSuccess(List peoples);
void onRequestFailed(String errorMsg);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordBasePrester.java
================================================
package com.htmessage.yichatopen.activity.main.password;
import com.htmessage.yichatopen.activity.BasePresenter;
/**
* 项目名称:HTOpen
* 类描述:PasswordBasePrester 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 14:59
* 邮箱:814326663@qq.com
*/
public interface PasswordBasePrester extends BasePresenter {
void sendSMSCode(String mobile,String countryName,String countryCode);
void resetPassword(String cacheCode,String smsCode,String password,String confimPwd,String mobile);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordPrester.java
================================================
package com.htmessage.yichatopen.activity.main.password;
import android.app.ProgressDialog;
import android.content.Intent;
import android.text.TextUtils;
import android.widget.Toast;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.sdk.client.HTClient;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.activity.login.LoginActivity;
import com.htmessage.yichatopen.utils.OkHttpUtils;
import com.htmessage.yichatopen.utils.Param;
import com.htmessage.yichatopen.utils.Validator;
import java.util.ArrayList;
import java.util.List;
/**
* 项目名称:HTOpen
* 类描述:PasswordPrester 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 15:07
* 邮箱:814326663@qq.com
*/
public class PasswordPrester implements PasswordBasePrester {
private String TAG = PasswordPrester.class.getSimpleName();
private PasswordView passwordView;
public PasswordPrester(PasswordView passwordView) {
this.passwordView = passwordView;
this.passwordView.setPresenter(this);
}
@Override
public void sendSMSCode(String mobile, String countryName, String countryCode) {
if (TextUtils.isEmpty(mobile)) {
Toast.makeText(passwordView.getBaseContext(), R.string.mobile_not_be_null, Toast.LENGTH_SHORT).show();
return;
}
if (countryName.equals(passwordView.getBaseContext().getString(R.string.china)) && countryCode.equals(passwordView.getBaseContext().getString(R.string.country_code))){
if (!Validator.isMobile(mobile)) {
Toast.makeText(passwordView.getBaseContext(), R.string.please_input_true_mobile, Toast.LENGTH_SHORT).show();
return;
}
passwordView.startTimeDown();
}else{
passwordView.onSendSMSCodeSuccess("1234");
}
}
@Override
public void resetPassword(String cacheCode, String smsCode, String password, String confimPwd, String mobile) {
if (TextUtils.isEmpty(mobile)) {
Toast.makeText(passwordView.getBaseContext(), R.string.mobile_not_be_null, Toast.LENGTH_SHORT).show();
return;
}
// if (TextUtils.isEmpty(smsCode) || TextUtils.isEmpty(cacheCode)) {
// Toast.makeText(passwordView.getBaseContext(), R.string.please_input_code, Toast.LENGTH_SHORT).show();
// return;
// }
if (TextUtils.isEmpty(password) || TextUtils.isEmpty(confimPwd)) {
Toast.makeText(passwordView.getBaseContext(), R.string.new_password_cannot_be_empty, Toast.LENGTH_SHORT).show();
return;
}
// if (!cacheCode.equals(smsCode)){
// Toast.makeText(passwordView.getBaseContext(), R.string.code_is_wrong, Toast.LENGTH_SHORT).show();
// return;
// }
if (!password.equals(confimPwd)) {
Toast.makeText(passwordView.getBaseContext(), R.string.Two_input_password, Toast.LENGTH_SHORT).show();
return;
}
final ProgressDialog progressDialog = new ProgressDialog(passwordView.getBaseContext());
progressDialog.setMessage(passwordView.getBaseContext().getString(R.string.are_reset_password));
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show();
List params = new ArrayList();
params.add(new Param("newPassword", password));
params.add(new Param("tel", mobile));
new OkHttpUtils(passwordView.getBaseContext()).post(params, HTConstant.URL_RESETPASSWORD, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
progressDialog.dismiss();
int code = jsonObject.getIntValue("code");
switch(code){
case 1:
passwordView.clearCacheCode();
passwordView.onResetSuccess(passwordView.getBaseContext().getString(R.string.password_reset_success));
logOut(passwordView.getIsReset());
break;
default:
passwordView.onResetFailed(passwordView.getBaseContext().getString(R.string.password_reset_failed));
break;
}
}
@Override
public void onFailure(String errorMsg) {
progressDialog.dismiss();
passwordView.onResetFailed(passwordView.getBaseContext().getString(R.string.password_reset_failed));
}
});
}
private void logOut(boolean isReset) {
if (isReset){
HTClient.getInstance().logout(new HTClient.HTCallBack() {
@Override
public void onSuccess() {
passwordView.getBaseActivity().runOnUiThread(new Runnable() {
public void run() {
// show login scree
HTApp.getInstance().setUserJson(null);
HTApp.getInstance().finishActivities();
passwordView.getBaseActivity().startActivity(new Intent(passwordView.getBaseActivity(), LoginActivity.class));
passwordView.getBaseActivity().finish();
}
});
}
@Override
public void onError() {
passwordView.getBaseActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
passwordView.onLogOutFailed(passwordView.getBaseContext().getString(R.string.logout_failed));
}
});
}
});
}else{
passwordView.getBaseActivity().finish();
}
}
@Override
public void start() {
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordResetActivity.java
================================================
package com.htmessage.yichatopen.activity.main.password;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.BaseActivity;
/**
* Created by huangfangyi on 2016/10/7.
* qq 84543217
*/
public class PasswordResetActivity extends BaseActivity{
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.activity_base);
getData();
initView();
}
private void initView() {
PasswordResetFragment fragment = (PasswordResetFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (fragment == null){
fragment = new PasswordResetFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame, fragment);
transaction.commit();
}
PasswordPrester prester = new PasswordPrester(fragment);
}
private void getData() {
boolean isReset = getIntent().getBooleanExtra("isReset", false);
if (isReset){
setTitle(R.string.resetPassword);
}else{
setTitle(R.string.find_pwd);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordResetFragment.java
================================================
package com.htmessage.yichatopen.activity.main.password;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.utils.ACache;
import com.htmessage.yichatopen.utils.CommonUtils;
/**
* 项目名称:HTOpen
* 类描述:PasswordResetFragment 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 15:33
* 邮箱:814326663@qq.com
*/
public class PasswordResetFragment extends Fragment implements PasswordView ,OnClickListener{
private Button btn_ok, btn_code;
private EditText et_code,et_usertel,et_password,et_password_confire;
private String mobile;
private TextView tv_title;
private ACache aCache;
private TextView tv_country,tv_country_code;
private RelativeLayout rl_country,rl_smscode;
private PasswordPrester prester;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View pswView = inflater.inflate(R.layout.activity_psw_reset, container, false);
getData();
initView(pswView);
initData();
setListener();
return pswView;
}
private void setListener() {
tv_country.setOnClickListener(this);
tv_country_code.setOnClickListener(this);
rl_country.setOnClickListener(this);
btn_ok.setOnClickListener(this);
btn_code.setOnClickListener(this);
}
private void initData() {
rl_smscode.setVisibility(View.GONE);
if (getIsReset()) {
tv_title.setText(R.string.resetPassword);
btn_ok.setText(R.string.resetPassword);
mobile = HTApp.getInstance().getUserJson().getString(HTConstant.JSON_KEY_TEL);
et_usertel.setText(mobile);
et_usertel.setEnabled(false);
et_usertel.clearFocus();
} else {
tv_title.setText(R.string.find_pwd);
btn_ok.setText(R.string.find_pwd);
et_usertel.setHint(R.string.input_bind_mobile);
et_usertel.setEnabled(true);
et_usertel.requestFocus();
}
}
private void initView(View pswView) {
//获取国家code
tv_country = (TextView) pswView.findViewById(R.id.tv_country);
tv_country_code = (TextView) pswView.findViewById(R.id.tv_country_code);
rl_country = (RelativeLayout) pswView.findViewById(R.id.rl_country);
rl_smscode = (RelativeLayout) pswView.findViewById(R.id.rl_smscode);
et_usertel = (EditText) pswView.findViewById(R.id.et_usertel);
et_password = (EditText) pswView.findViewById(R.id.et_password);
et_password_confire = (EditText) pswView.findViewById(R.id.et_password_confire);
et_code = (EditText) pswView.findViewById(R.id.et_code);
btn_ok = (Button) pswView.findViewById(R.id.btn_ok);
btn_code = (Button) pswView.findViewById(R.id.btn_code);
tv_title= (TextView) pswView.findViewById(R.id.tv_title);
}
private void getData() {
aCache = ACache.get(getActivity());
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.rl_country:
CommonUtils.showPup(getBaseActivity(),tv_country,tv_country_code);
break;
case R.id.btn_code:
prester.sendSMSCode(getMobile(),getCountryName(),getCountryCode());
break;
case R.id.btn_ok:
prester.resetPassword(getCacheCode(),getSMSCode(),getPwd(),getConfimPwd(),getMobile());
break;
}
}
@Override
public String getCountryName() {
return tv_country.getText().toString().trim();
}
@Override
public String getCountryCode() {
return tv_country_code.getText().toString().trim();
}
@Override
public String getCacheCode() {
return aCache.getAsString("code");
}
@Override
public String getSMSCode() {
return et_code.getText().toString().trim();
}
@Override
public boolean getIsReset() {
return getActivity().getIntent().getBooleanExtra("isReset", false);
}
@Override
public String getMobile() {
return et_usertel.getText().toString().trim();
}
@Override
public String getPwd() {
return et_password.getText().toString().trim();
}
@Override
public String getConfimPwd() {
return et_password_confire.getText().toString().trim();
}
@Override
public void clearCacheCode() {
aCache.put("code","");
}
@Override
public void onSendSMSCodeSuccess(String msg) {
if ("1234".equals(msg)){
et_code.setText(msg);
}
aCache.put("code",msg);
Toast.makeText(getBaseContext(), R.string.code_is_send, Toast.LENGTH_SHORT).show();
}
@Override
public void onSendSMSCodeFailed(String error) {
Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();
}
@Override
public void onResetSuccess(String msg) {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onResetFailed(String error) {
Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();
}
@Override
public void startTimeDown() {
}
@Override
public void finishTimeDown() {
}
@Override
public void onLogOutFailed(String msg) {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void setPresenter(PasswordPrester presenter) {
this.prester = presenter;
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordView.java
================================================
package com.htmessage.yichatopen.activity.main.password;
import com.htmessage.yichatopen.activity.BaseView;
/**
* 项目名称:HTOpen
* 类描述:PasswordView 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 15:08
* 邮箱:814326663@qq.com
*/
public interface PasswordView extends BaseView{
String getCountryName();
String getCountryCode();
String getCacheCode();
String getSMSCode();
boolean getIsReset();
String getMobile();
String getPwd();
String getConfimPwd();
void clearCacheCode();
void onSendSMSCodeSuccess(String msg);
void onSendSMSCodeFailed(String error);
void onResetSuccess(String msg);
void onResetFailed(String error);
void startTimeDown();
void finishTimeDown();
void onLogOutFailed(String msg);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/FragmentProfile.java
================================================
package com.htmessage.yichatopen.activity.main.profile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.alibaba.fastjson.JSONObject;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.IMAction;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.main.qrcode.QrCodeActivity;
import com.htmessage.yichatopen.activity.main.profile.info.profile.ProfileActivity;
import com.htmessage.yichatopen.activity.SettingsActivity;
public class FragmentProfile extends Fragment implements View.OnClickListener {
private InfoChangedListener listener;
private ImageView ivAvatar;
private TextView tvNick;
private TextView tvFxid;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_profile, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getData();
setListener();
initView(HTApp.getInstance().getUserJson());
}
private void getData() {
IntentFilter intent = new IntentFilter(IMAction.ACTION_UPDATE_INFO);
listener = new InfoChangedListener();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(listener, intent);
}
private void initView(JSONObject jsonObject) {
ivAvatar = (ImageView) getView().findViewById(R.id.iv_avatar);
tvNick = (TextView) getView().findViewById(R.id.tv_name);
tvFxid = (TextView) getView().findViewById(R.id.tv_fxid);
String avatarUrl = jsonObject.getString(HTConstant.JSON_KEY_AVATAR);
Glide.with(getActivity()).load(avatarUrl).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(ivAvatar);
tvNick.setText(jsonObject.getString(HTConstant.JSON_KEY_NICK));
String fxid = jsonObject.getString(HTConstant.JSON_KEY_FXID);
if (!TextUtils.isEmpty(fxid)) {
tvFxid.setText(getString(R.string.app_id) + fxid);
} else {
tvFxid.setText(getString(R.string.app_id) + getString(R.string.not_set));
}
}
private void setListener() {
getView().findViewById(R.id.re_myinfo).setOnClickListener(this);
getView().findViewById(R.id.re_setting).setOnClickListener(this);
getView().findViewById(R.id.re_xiangce).setOnClickListener(this);
getView().findViewById(R.id.rl_qrcode).setOnClickListener(this);
getView().findViewById(R.id.re_pro_test).setOnClickListener(this);
getView().findViewById(R.id.re_github).setOnClickListener(this);
getView().findViewById(R.id.re_oschina).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.re_myinfo:
startActivity(new Intent(getActivity(), ProfileActivity.class));
break;
case R.id.re_setting:
startActivity(new Intent(getActivity(), SettingsActivity.class));
break;
case R.id.re_xiangce:
break;
case R.id.rl_qrcode: //我的二维码
startActivity(new Intent(getActivity(), QrCodeActivity.class));
break;
case R.id.re_pro_test://pro版本
toStartBrowser(HTConstant.YICHATPROURL);
break;
case R.id.re_github:
toStartBrowser(HTConstant.GITHUBURL);
break;
case R.id.re_oschina:
toStartBrowser(HTConstant.OSCHINAURL);
break;
}
}
private void toStartBrowser(String url) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.parse(url);
intent.setData(uri);
intent.setClassName("com.android.browser", "com.android.browser.BrowserActivity");
startActivity(intent);
}
private class InfoChangedListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (IMAction.ACTION_UPDATE_INFO.equals(intent.getAction())) {
String type = intent.getStringExtra(HTConstant.KEY_CHANGE_TYPE);
if (HTConstant.JSON_KEY_AVATAR.equals(type)) {
String avatar = intent.getStringExtra(HTConstant.JSON_KEY_AVATAR);
Glide.with(getActivity()).load(avatar).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(ivAvatar);
} else if (HTConstant.JSON_KEY_FXID.equals(type)) {
String fxid = intent.getStringExtra(HTConstant.JSON_KEY_FXID);
tvFxid.setText(getString(R.string.app_id) + fxid);
} else if (HTConstant.JSON_KEY_NICK.equals(type)) {
String nick = intent.getStringExtra(HTConstant.JSON_KEY_NICK);
tvNick.setText(nick);
}
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (listener != null) {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(listener);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfileActivity.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.profile;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import com.htmessage.yichatopen.activity.BaseActivity;
import com.htmessage.yichatopen.R;
public class ProfileActivity extends BaseActivity {
private ProfilePrester prester;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
setTitle(R.string.title_user_profile);
ProfileFragment fragment = (ProfileFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (fragment == null){
fragment = new ProfileFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame, fragment);
transaction.commit();
}
prester = new ProfilePrester(fragment);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
prester.result(requestCode,resultCode,data);
super.onActivityResult(requestCode, resultCode, data);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfileBasePrester.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.profile;
import android.content.Intent;
import com.htmessage.yichatopen.activity.BasePresenter;
/**
* 项目名称:HTOpen
* 类描述:ProfileBasePrester 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 10:50
* 邮箱:814326663@qq.com
*/
public interface ProfileBasePrester extends BasePresenter {
void resgisteRecivier();
void showPhotoDialog();
void showSexDialog();
void result(int requestCode, int resultCode, Intent intent);
void onDestory();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfileFragment.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.profile;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.alibaba.fastjson.JSONObject;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.main.qrcode.QrCodeActivity;
import com.htmessage.yichatopen.activity.main.region.RegionActivity;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.activity.main.profile.info.update.ProfileUpdateActivity;
/**
* 项目名称:HTOpen
* 类描述:ProfileFragment 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 11:47
* 邮箱:814326663@qq.com
*/
public class ProfileFragment extends Fragment implements ProfileView, View.OnClickListener{
private RelativeLayout re_avatar,re_name,re_fxid,re_sex,re_region,re_sign,re_qrcode;
private ImageView iv_avatar;
private TextView tv_name;
private TextView tv_fxid;
private TextView tv_sex;
private TextView tv_sign, tv_region;
private String sex;
private ProfilePrester prester;
private JSONObject userJson;
private static final int UPDATE_REGION = 7;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_profile_info, container, false);
initView(view);
initData();
setListener();
return view;
}
private void setListener() {
//设置监听
re_avatar.setOnClickListener(this);
re_name.setOnClickListener(this);
re_fxid.setOnClickListener(this);
re_sex.setOnClickListener(this);
re_region.setOnClickListener(this);
re_sign.setOnClickListener(this);
re_qrcode.setOnClickListener(this);
}
private void initData() {
prester.resgisteRecivier();
userJson = getUserJson();
String nick = userJson.getString(HTConstant.JSON_KEY_NICK);
String fxid = userJson.getString(HTConstant.JSON_KEY_FXID);
sex = userJson.getString(HTConstant.JSON_KEY_SEX);
String sign = userJson.getString(HTConstant.JSON_KEY_SIGN);
String province = userJson.getString(HTConstant.JSON_KEY_PROVINCE);
String city = userJson.getString(HTConstant.JSON_KEY_CITY);
String avatarUrl = userJson.getString(HTConstant.JSON_KEY_AVATAR);
if (!TextUtils.isEmpty(avatarUrl)) {
if (!avatarUrl.contains("http:")) {
avatarUrl = HTConstant.URL_AVATAR + avatarUrl;
}
}
Glide.with(getBaseContext()).load(avatarUrl).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(iv_avatar);
tv_name.setText(nick);
if (TextUtils.isEmpty(fxid)) {
tv_fxid.setText(R.string.not_set);
} else {
tv_fxid.setText(fxid);
}
if (!TextUtils.isEmpty(sex)) {
switch (sex) {
case "1":
case "男":
tv_sex.setText(R.string.male);
break;
case "0":
case "女":
tv_sex.setText(R.string.female);
break;
default:
tv_sex.setText(R.string.not_set);
break;
}
} else {
tv_sex.setText(R.string.not_set);
}
if (TextUtils.isEmpty(sign)) {
tv_sign.setText(R.string.not_input);
} else {
tv_sign.setText(sign);
}
if (!TextUtils.isEmpty(province) && !TextUtils.isEmpty(city)) {
tv_region.setText(province + " " + city);
} else {
tv_region.setText(R.string.not_set);
}
}
private void initView(View view) {
iv_avatar = (ImageView) view.findViewById(R.id.iv_avatar);
tv_name = (TextView) view.findViewById(R.id.tv_name);
tv_fxid = (TextView) view.findViewById(R.id.tv_fxid);
tv_sex = (TextView) view.findViewById(R.id.tv_sex);
tv_sign = (TextView) view.findViewById(R.id.tv_sign);
tv_region = (TextView) view.findViewById(R.id.tv_region);
re_avatar = (RelativeLayout) view.findViewById(R.id.re_avatar);
re_name= (RelativeLayout) view.findViewById(R.id.re_name);
re_fxid = (RelativeLayout) view.findViewById(R.id.re_fxid);
re_sex = (RelativeLayout) view.findViewById(R.id.re_sex);
re_region= (RelativeLayout) view.findViewById(R.id.re_region);
re_sign = (RelativeLayout) view.findViewById(R.id.re_sign);
re_qrcode = (RelativeLayout) view.findViewById(R.id.re_qrcode);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.re_avatar:
prester.showPhotoDialog();
break;
case R.id.re_name:
startActivity(new Intent(getActivity(), ProfileUpdateActivity.class)
.putExtra("type", ProfileUpdateActivity.TYPE_NICK)
.putExtra("default", userJson.getString(HTConstant.JSON_KEY_NICK)));
break;
case R.id.re_fxid:
if (TextUtils.isEmpty(userJson.getString(HTConstant.JSON_KEY_FXID))) {
startActivity(new Intent(getActivity(), ProfileUpdateActivity.class)
.putExtra("type", ProfileUpdateActivity.TYPE_FXID));
}
break;
case R.id.re_sex:
prester.showSexDialog();
break;
case R.id.re_region:
getBaseActivity().startActivityForResult(new Intent(getBaseActivity(), RegionActivity.class), UPDATE_REGION);
break;
case R.id.re_sign:
startActivity(new Intent(getActivity(), ProfileUpdateActivity.class)
.putExtra("type", ProfileUpdateActivity.TYPE_SIGN)
.putExtra("default", userJson.getString(HTConstant.JSON_KEY_SIGN)));
break;
case R.id.re_qrcode:
startActivity(new Intent(getActivity(), QrCodeActivity.class));
break;
}
}
@Override
public void onNickUpdate(String nick, boolean isHang) {
tv_name.setText(nick);
}
@Override
public void onSexUpdate(int sex, boolean isHang) {
tv_sex.setText(sex);
}
@Override
public void onSignUpdate(String sign, boolean isHang) {
tv_sign.setText(sign);
}
@Override
public void onAvatarUpdate(String avatar, boolean isHang) {
Glide.with(getBaseContext()).load(avatar).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).error(R.drawable.default_avatar).into(iv_avatar);
}
@Override
public void onRegionUpdate(String region, boolean isHang) {
tv_region.setText(region);
}
@Override
public void onFxidUpdate(String fxid, boolean isHang) {
tv_fxid.setText(fxid);
}
@Override
public void onUpdateSuccess(String msg) {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onUpdateFailed(String error) {
Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();
}
@Override
public JSONObject getUserJson() {
return HTApp.getInstance().getUserJson();
}
@Override
public void setPresenter(ProfilePrester presenter) {
this.prester = presenter;
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
@Override
public void onDestroy() {
prester.onDestory();
super.onDestroy();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfilePrester.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.profile;
import android.app.Activity;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.htmessage.sdk.utils.UploadFileUtils;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.IMAction;
import com.htmessage.yichatopen.utils.OkHttpUtils;
import com.htmessage.yichatopen.utils.Param;
import com.htmessage.yichatopen.widget.HTAlertDialog;
import com.soundcloud.android.crop.Crop;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 项目名称:HTOpen
* 类描述:ProfilePrester 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 10:49
* 邮箱:814326663@qq.com
*/
public class ProfilePrester implements ProfileBasePrester {
private static final int PHOTO_REQUEST_TAKEPHOTO = 1;// 拍照
private static final int PHOTO_REQUEST_GALLERY = 2;// 从相册中选择
private static final int PHOTO_REQUEST_CUT = 3;// 结果
private static final int UPDATE_REGION = 7;
private String imageName;
private String dirPath;
private JSONObject userJson;
private ProfileView profileView;
private InfoChangedListener listener;
public ProfilePrester(ProfileView profileView) {
this.profileView = profileView;
this.profileView.setPresenter(this);
dirPath = HTApp.getInstance().getDirFilePath();
userJson = profileView.getUserJson();
}
@Override
public void resgisteRecivier() {
IntentFilter intent = new IntentFilter(IMAction.ACTION_UPDATE_INFO);
listener = new InfoChangedListener();
LocalBroadcastManager.getInstance(profileView.getBaseContext()).registerReceiver(listener, intent);
}
private void updateInfo(final String key, final String value) {
if (TextUtils.isEmpty(key) && TextUtils.isEmpty(value)){
return;
}
final Dialog progressDialog = HTApp.getInstance().createLoadingDialog(profileView.getBaseContext(), profileView.getBaseContext().getString(R.string.are_uploading));
progressDialog.show();
List params = new ArrayList();
params.add(new Param(key, value));
params.add(new Param("userId", HTApp.getInstance().getUsername()));
new OkHttpUtils(profileView.getBaseContext()).post(params, HTConstant.URL_UPDATE, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
progressDialog.dismiss();
int code = jsonObject.getIntValue("code");
if (code == 1) {
//update ui
if (key.equals(HTConstant.JSON_KEY_SEX)) {
switch (value) {
case "1":
profileView.onSexUpdate(R.string.male,true);
break;
case "0":
profileView.onSexUpdate(R.string.female,true);
break;
}
}
userJson.put(key, value);
HTApp.getInstance().setUserJson(userJson);
profileView.onUpdateSuccess(profileView.getBaseContext().getString(R.string.update_success));
} else {
profileView.onUpdateFailed(profileView.getBaseContext().getString(R.string.upload_failed)+code);
}
}
@Override
public void onFailure(String errorMsg) {
profileView.onUpdateFailed(errorMsg);
progressDialog.dismiss();
}
});
}
private void updateRegion(final String province,final String city) {
if (TextUtils.isEmpty(province) && TextUtils.isEmpty(city)){
return;
}
final Dialog progressDialog = HTApp.getInstance().createLoadingDialog(profileView.getBaseContext(), profileView.getBaseContext().getString(R.string.are_uploading));
progressDialog.show();
final List params = new ArrayList();
params.add(new Param(HTConstant.JSON_KEY_PROVINCE, province));
params.add(new Param(HTConstant.JSON_KEY_CITY, city));
params.add(new Param("userId", HTApp.getInstance().getUsername()));
new OkHttpUtils(profileView.getBaseContext()).post(params, HTConstant.URL_UPDATE, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
progressDialog.dismiss();
int code = jsonObject.getIntValue("code");
if (code == 1) {
//update ui
userJson.put(HTConstant.JSON_KEY_PROVINCE, province);
userJson.put(HTConstant.JSON_KEY_CITY, city);
HTApp.getInstance().setUserJson(userJson);
profileView.onRegionUpdate(province +" "+city,true);
profileView.onUpdateSuccess(profileView.getBaseContext().getString(R.string.update_success));
} else {
profileView.onUpdateFailed(profileView.getBaseContext().getString(R.string.upload_failed) + code);
}
}
@Override
public void onFailure(String errorMsg) {
profileView.onUpdateFailed(errorMsg);
progressDialog.dismiss();
}
});
}
private void updateAvatar(final String key,final String value){
if (TextUtils.isEmpty(key) && TextUtils.isEmpty(value)){
return;
}
final Dialog progressDialog = HTApp.getInstance().createLoadingDialog(profileView.getBaseContext(), profileView.getBaseContext().getString(R.string.are_uploading));
progressDialog.show();
final String fileName = value.substring(value.lastIndexOf("/") + 1);
new UploadFileUtils(profileView.getBaseContext(), fileName, value).asyncUploadFile(new UploadFileUtils.a() {
@Override
public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
}
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
final String url = HTConstant.baseOssUrl + fileName;
profileView.getBaseActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
UpLoadAvator(value, key, url, progressDialog);
}
});
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
profileView.getBaseActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
}
});
}
});
}
private void UpLoadAvator(final String filePath, final String key, final String value, final Dialog progressDialog) {
List params = new ArrayList();
params.add(new Param(key, value));
new OkHttpUtils(profileView.getBaseContext()).post(params, HTConstant.URL_UPDATE, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
progressDialog.dismiss();
int code = jsonObject.getIntValue("code");
switch (code) {
case 1:
if (key.equals(HTConstant.JSON_KEY_AVATAR)) {
userJson.put(HTConstant.JSON_KEY_AVATAR, value);
HTApp.getInstance().setUserJson(userJson);
profileView.onAvatarUpdate(filePath,true);
LocalBroadcastManager.getInstance(profileView.getBaseContext()).sendBroadcast(new Intent(IMAction.ACTION_UPDATE_INFO).putExtra(HTConstant.JSON_KEY_AVATAR, value).putExtra(HTConstant.KEY_CHANGE_TYPE, HTConstant.JSON_KEY_AVATAR));
}
profileView.onUpdateSuccess(profileView.getBaseContext().getString(R.string.update_success));
break;
default:
String info = jsonObject.getString("info");
profileView.onUpdateFailed(info);
break;
}
}
@Override
public void onFailure(String errorMsg) {
profileView.onUpdateFailed(errorMsg);
progressDialog.dismiss();
}
});
}
@Override
public void showPhotoDialog() {
HTAlertDialog fxAlertDialog = new HTAlertDialog(profileView.getBaseContext(), null, new String[]{profileView.getBaseContext().getString(R.string.attach_take_pic), profileView.getBaseContext().getString(R.string.image_manager)});
fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {
@Override
public void onClick(int position) {
switch (position) {
case 0:
imageName = getNowTime() + ".png";
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 指定调用相机拍照后照片的储存路径
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File(dirPath, imageName)));
profileView.getBaseActivity().startActivityForResult(intent, PHOTO_REQUEST_TAKEPHOTO);
break;
case 1:
imageName = getNowTime() + ".png";
Crop.pickImage(profileView.getBaseActivity(), PHOTO_REQUEST_GALLERY);
break;
}
}
});
}
@Override
public void showSexDialog() {
String title = profileView.getBaseContext().getString(R.string.sex);
HTAlertDialog fxAlertDialog = new HTAlertDialog(profileView.getBaseContext(), title, new String[]{profileView.getBaseContext().getString(R.string.male), profileView.getBaseContext().getString(R.string.female)});
fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {
@Override
public void onClick(int position) {
switch (position) {
case 0:
updateInfo(HTConstant.JSON_KEY_SEX, "1");
break;
case 1:
updateInfo(HTConstant.JSON_KEY_SEX, "0");
break;
}
}
});
}
@Override
public void result(int requestCode, int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case PHOTO_REQUEST_TAKEPHOTO:
beginCrop(Uri.fromFile(new File(dirPath, imageName)));
break;
case PHOTO_REQUEST_GALLERY:
if (intent != null)
beginCrop(intent.getData());
break;
case PHOTO_REQUEST_CUT:
Uri output = Crop.getOutput(intent);
updateAvatar(HTConstant.JSON_KEY_AVATAR, output.getPath());
break;
case UPDATE_REGION:
Log.d("slj","-----更新地区:"+UPDATE_REGION);
if (intent != null) {
String province = intent.getStringExtra("province");
String city = intent.getStringExtra("city");
updateRegion(province, city);
}
break;
}
}
}
private void unRegisterReciver(){
if (listener != null){
LocalBroadcastManager.getInstance(profileView.getBaseContext()).unregisterReceiver(listener);
}
}
@Override
public void onDestory() {
unRegisterReciver();
profileView = null;
}
@Override
public void start() {
}
private class InfoChangedListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (IMAction.ACTION_UPDATE_INFO.equals(intent.getAction())) {
String type = intent.getStringExtra(HTConstant.KEY_CHANGE_TYPE);
if (HTConstant.JSON_KEY_SIGN.equals(type)) {
String sign = intent.getStringExtra(HTConstant.JSON_KEY_SIGN);
profileView.onSignUpdate(sign,true);
} else if (HTConstant.JSON_KEY_FXID.equals(type)) {
String fxid = intent.getStringExtra(HTConstant.JSON_KEY_FXID);
profileView.onFxidUpdate(fxid,true);
} else if (HTConstant.JSON_KEY_NICK.equals(type)) {
String nick = intent.getStringExtra(HTConstant.JSON_KEY_NICK);
profileView.onNickUpdate(nick,true);
}
}
}
}
private void beginCrop(Uri source) {
Uri destination = Uri.fromFile(new File(dirPath, imageName));
Crop.of(source, destination).asSquare().start(profileView.getBaseActivity(), PHOTO_REQUEST_CUT);
}
private String getNowTime() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddHHmmssSS");
return dateFormat.format(date);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfileView.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.profile;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.activity.BaseView;
/**
* 项目名称:HTOpen
* 类描述:ProfileView 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 11:00
* 邮箱:814326663@qq.com
*/
public interface ProfileView extends BaseView{
void onNickUpdate(String nick,boolean isHang);
void onSexUpdate(int sex,boolean isHang);
void onSignUpdate(String sign,boolean isHang);
void onAvatarUpdate(String avatar,boolean isHang);
void onRegionUpdate(String region,boolean isHang);
void onFxidUpdate(String fxid,boolean isHang);
void onUpdateSuccess(String msg);
void onUpdateFailed(String error);
JSONObject getUserJson();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/ProfileUpdateActivity.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.update;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import com.htmessage.yichatopen.activity.BaseActivity;
import com.htmessage.yichatopen.R;
/**
* Created by huangfangyi on 2016/7/3.\
* QQ:84543217
*/
public class ProfileUpdateActivity extends BaseActivity {
public static final int TYPE_NICK = 0;
public static final int TYPE_FXID = 1;
public static final int TYPE_SIGN = 2;
private UpdateProfilePrestener prestener;
private String title;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
int type = getIntent().getIntExtra("type", 0);
switch (type){
case 0:
title = getString(R.string.change_nick);
break;
case 1:
title = getString(R.string.change_mixin);
break;
case 2:
title = getString(R.string.change_personalized_signature);
break;
}
setTitle(title);
ProfileUpdateFragment fragment = (ProfileUpdateFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (fragment == null){
fragment = new ProfileUpdateFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame,fragment);
transaction.commit();
}
prestener = new UpdateProfilePrestener(fragment);
showRightTextView(R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
prestener.update();
}
});
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/ProfileUpdateFragment.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.update;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.htmessage.yichatopen.R;
/**
* 项目名称:HTOpen
* 类描述:ProfileUpdateFragment 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 16:20
* 邮箱:814326663@qq.com
*/
public class ProfileUpdateFragment extends Fragment implements UpdateProfileView,View.OnClickListener{
private String defaultStr;
private TextView saveTV;
private EditText infoET;
private TextView titleTV;
private int type;
private UpdateProfilePrestener prestener;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View updateView = inflater.inflate(R.layout.activity_update_info, container, false);
getData();
initView(updateView);
initData();
setListener();
return updateView;
}
private void setListener() {
saveTV.setOnClickListener(this);
}
private void initData() {
String title = prestener.getTitle(type);
titleTV.setText(title);
if (defaultStr != null) {
infoET.setText(defaultStr);
infoET.setSelection(infoET.getText().length());
}
}
private void initView(View updateView) {
titleTV = (TextView) updateView.findViewById(R.id.tv_title);
saveTV = (TextView) updateView.findViewById(R.id.tv_save);
infoET = (EditText) updateView.findViewById(R.id.et_info);
}
private void getData() {
defaultStr = getDefultString();
type = getType();
}
@Override
public String getDefultString() {
return getBaseActivity().getIntent().getStringExtra("default");
}
@Override
public int getType() {
return getBaseActivity().getIntent().getIntExtra("type", 0);
}
@Override
public String getInputString() {
return infoET.getText().toString().trim();
}
@Override
public void onUpdateSuccess(String msg) {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
getBaseActivity().finish();
}
@Override
public void onUpdateFailed(String msg) {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void setPresenter(UpdateProfilePrestener presenter) {
this.prestener = presenter;
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.tv_save:
prestener.updateInfo(prestener.getKey(type),getInputString(),getDefultString());
break;
}
}
@Override
public void onDestroy() {
prestener.onDestory();
super.onDestroy();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/UpdateProfileBasePrester.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.update;
import com.htmessage.yichatopen.activity.BasePresenter;
/**
* 项目名称:HTOpen
* 类描述:UpdateProfileBasePrester 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 13:32
* 邮箱:814326663@qq.com
*/
public interface UpdateProfileBasePrester extends BasePresenter {
void update();
void updateInfo(String key,String value,String defaultStr);
String getTitle(int type);
String getKey(int type);
void onDestory();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/UpdateProfilePrestener.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.update;
import android.app.Dialog;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.IMAction;
import com.htmessage.yichatopen.utils.OkHttpUtils;
import com.htmessage.yichatopen.utils.Param;
import com.htmessage.yichatopen.utils.Validator;
import java.util.ArrayList;
import java.util.List;
/**
* 项目名称:HTOpen
* 类描述:UpdateProfilePrestener 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 13:38
* 邮箱:814326663@qq.com
*/
public class UpdateProfilePrestener implements UpdateProfileBasePrester {
private UpdateProfileView updateProfileView;
private static final int TYPE_NICK = 0;
private static final int TYPE_FXID = 1;
private static final int TYPE_SIGN = 2;
public UpdateProfilePrestener(UpdateProfileView updateProfileView) {
this.updateProfileView = updateProfileView;
this.updateProfileView.setPresenter(this);
}
@Override
public void update() {
updateInfo(getKey(updateProfileView.getType()),updateProfileView.getInputString(),updateProfileView.getDefultString());
}
@Override
public void updateInfo(final String key, final String value , String defaultStr) {
if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value) || ((defaultStr != null) && value.equals(defaultStr))) {
return;
}
if(HTConstant.JSON_KEY_FXID.equals(key)){
if(Validator.isChinese(value)){
updateProfileView.onUpdateFailed(updateProfileView.getBaseActivity().getString(R.string.mixin_can_not_has_chinese));
return;
}
}
if (value.length() > 30) {
updateProfileView.onUpdateFailed(updateProfileView.getBaseActivity().getString(R.string.string_not_30));
return;
}
final Dialog progressDialog = HTApp.getInstance().createLoadingDialog(updateProfileView.getBaseActivity(),updateProfileView.getBaseActivity().getString(R.string.are_uploading));
progressDialog.show();
//本地用户资料
final JSONObject userJson = HTApp.getInstance().getUserJson();
List params = new ArrayList();
params.add(new Param(key, value));
new OkHttpUtils(updateProfileView.getBaseActivity()).post(params, HTConstant.URL_UPDATE, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
progressDialog.dismiss();
int code = jsonObject.getIntValue("code");
if (code == 1) {
userJson.put(key, value);
HTApp.getInstance().setUserJson(userJson);
LocalBroadcastManager.getInstance(updateProfileView.getBaseActivity()).sendBroadcast(new Intent(IMAction.ACTION_UPDATE_INFO).putExtra(HTConstant.KEY_CHANGE_TYPE,key).putExtra(key,value));
updateProfileView.onUpdateSuccess(updateProfileView.getBaseActivity().getString(R.string.update_success));
} else {
updateProfileView.onUpdateFailed(updateProfileView.getBaseActivity().getString(R.string.upload_failed)+code);
}
}
@Override
public void onFailure(String errorMsg) {
updateProfileView.onUpdateFailed(errorMsg);
progressDialog.dismiss();
}
});
}
@Override
public String getTitle(int type) {
String title = "";
switch (type) {
case TYPE_NICK:
title = updateProfileView.getBaseActivity().getString(R.string.change_nick);
break;
case TYPE_FXID:
title = updateProfileView.getBaseActivity().getString(R.string.change_mixin);
break;
case TYPE_SIGN:
title = updateProfileView.getBaseActivity().getString(R.string.change_personalized_signature);
break;
}
return title;
}
@Override
public String getKey(int type) {
String key = "";
switch (type) {
case TYPE_NICK:
key = HTConstant.JSON_KEY_NICK;
break;
case TYPE_FXID:
key = HTConstant.JSON_KEY_FXID;
break;
case TYPE_SIGN:
key = HTConstant.JSON_KEY_SIGN;
break;
}
return key;
}
@Override
public void onDestory() {
updateProfileView = null;
}
@Override
public void start() {
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/UpdateProfileView.java
================================================
package com.htmessage.yichatopen.activity.main.profile.info.update;
import com.htmessage.yichatopen.activity.BaseView;
/**
* 项目名称:HTOpen
* 类描述:UpdateProfileView 描述:
* 创建人:songlijie
* 创建时间:2017/7/7 13:41
* 邮箱:814326663@qq.com
*/
public interface UpdateProfileView extends BaseView{
String getDefultString();
int getType();
String getInputString();
void onUpdateSuccess(String msg);
void onUpdateFailed(String msg);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodeActivity.java
================================================
package com.htmessage.yichatopen.activity.main.qrcode;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.BaseActivity;
public class QrCodeActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
setTitle(R.string.me_qrcode);
QrCodeFragment fragment = (QrCodeFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (fragment == null){
fragment = new QrCodeFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame,fragment);
transaction.commit();
}
new QrCodePrester(fragment);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodeBasePrester.java
================================================
package com.htmessage.yichatopen.activity.main.qrcode;
import com.htmessage.yichatopen.activity.BasePresenter;
/**
* 项目名称:yichat0504
* 类描述:QrCodeBasePrester 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 10:36
* 邮箱:814326663@qq.com
*/
public interface QrCodeBasePrester extends BasePresenter {
void onDestory();
void CreateQrCode();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodeFragment.java
================================================
package com.htmessage.yichatopen.activity.main.qrcode;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
import com.htmessage.yichatopen.R;
/**
* 项目名称:yichat0504
* 类描述:QrCodeFragment 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 10:52
* 邮箱:814326663@qq.com
*/
public class QrCodeFragment extends Fragment implements QrCodeView {
private ImageView imageView;
private QrCodePrester prester;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_qrcode_generate, container, false);
initView(view);
getData();
return view;
}
private void getData() {
prester.CreateQrCode();
}
private void initView(View view) {
imageView = (ImageView) view.findViewById(R.id.code_image);
}
@Override
public void showQrCode(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
}
@Override
public void showError(String error) {
Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();
}
@Override
public void setPresenter(QrCodePrester presenter) {
this.prester = presenter;
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
@Override
public void onDestroy() {
prester.onDestory();
super.onDestroy();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodePrester.java
================================================
package com.htmessage.yichatopen.activity.main.qrcode;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.Log;
import com.alibaba.fastjson.JSONObject;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.HTConstant;
/**
* 项目名称:yichat0504
* 类描述:QrCodePrester 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 10:44
* 邮箱:814326663@qq.com
*/
public class QrCodePrester implements QrCodeBasePrester {
private String TAG = QrCodePrester.class.getSimpleName();
private QrCodeView codeView;
public QrCodePrester(QrCodeView codeView) {
this.codeView = codeView;
this.codeView.setPresenter(this);
}
@Override
public void onDestory() {
codeView = null;
}
@Override
public void CreateQrCode() {
JSONObject userJson = HTApp.getInstance().getUserJson();
String key = "userInfo:";
JSONObject object =new JSONObject();
object.put(HTConstant.JSON_KEY_HXID,HTApp.getInstance().getUsername());
object.put(HTConstant.JSON_KEY_NICK,userJson.getString(HTConstant.JSON_KEY_NICK));
object.put(HTConstant.JSON_KEY_TEL,userJson.getString(HTConstant.JSON_KEY_TEL));
object.put(HTConstant.JSON_KEY_FXID,userJson.getString(HTConstant.JSON_KEY_FXID));
object.put(HTConstant.JSON_KEY_SEX,userJson.getString(HTConstant.JSON_KEY_SEX));
object.put(HTConstant.JSON_KEY_AVATAR,userJson.getString(HTConstant.JSON_KEY_AVATAR));
object.put(HTConstant.JSON_KEY_PROVINCE,userJson.getString(HTConstant.JSON_KEY_PROVINCE));
object.put(HTConstant.JSON_KEY_CITY,userJson.getString(HTConstant.JSON_KEY_CITY));
object.put(HTConstant.JSON_KEY_SIGN,userJson.getString(HTConstant.JSON_KEY_SIGN));
try {
Bitmap bitmap = generateQRCode(key + object.toJSONString());
codeView.showQrCode(bitmap);
} catch (WriterException e) {
codeView.showError(e.getMessage());
e.printStackTrace();
}
}
@Override
public void start() {
}
private Bitmap bitMatrix2Bitmap(BitMatrix matrix) {
int w = matrix.getWidth();
int h = matrix.getHeight();
int[] rawData = new int[w * h];
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
int color = Color.WHITE;
if (matrix.get(i, j)) {
color = Color.BLACK;
}
rawData[i + (j * w)] = color;
}
}
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
bitmap.setPixels(rawData, 0, w, 0, 0, w, h);
return bitmap;
}
private Bitmap generateQRCode(String content) throws WriterException {
Log.d(TAG,"二维码:"+content);
QRCodeWriter writer = new QRCodeWriter();
BitMatrix matrix = writer.encode(content, BarcodeFormat.QR_CODE,
500, 500);
return bitMatrix2Bitmap(matrix);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodeView.java
================================================
package com.htmessage.yichatopen.activity.main.qrcode;
import android.graphics.Bitmap;
import com.htmessage.yichatopen.activity.BaseView;
/**
* 项目名称:yichat0504
* 类描述:QrCodeView 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 10:44
* 邮箱:814326663@qq.com
*/
public interface QrCodeView extends BaseView {
void showQrCode(Bitmap bitmap);
void showError(String error);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionActivity.java
================================================
package com.htmessage.yichatopen.activity.main.region;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.BaseActivity;
public class RegionActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
setTitle(R.string.region);
RegionFragment fragment = (RegionFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (fragment == null){
fragment = new RegionFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame,fragment);
transaction.commit();
}
new RegionPresenter(fragment);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionBasePrestener.java
================================================
package com.htmessage.yichatopen.activity.main.region;
import com.htmessage.yichatopen.activity.BasePresenter;
import java.util.List;
/**
* 项目名称:yichat0504
* 类描述:RegionBasePrestener 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 13:53
* 邮箱:814326663@qq.com
*/
public interface RegionBasePrestener extends BasePresenter {
List getProvinceList();
List getCityList(int position);
void onDestory();
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionFragment.java
================================================
package com.htmessage.yichatopen.activity.main.region;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.htmessage.yichatopen.R;
import java.util.ArrayList;
import java.util.List;
/**
* 项目名称:yichat0504
* 类描述:RegionFragment 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 14:21
* 邮箱:814326663@qq.com
*/
public class RegionFragment extends Fragment implements RegionView{
private ListView list_province;
private ListView list_city;
// 一个城市的数据列表
private List citys = new ArrayList();
private RegionAdapter cAdapter;
private RegionAdapter pAdapter;
private String province;
private RegionPresenter presenter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View regionView = inflater.inflate(R.layout.activity_region, container, false);
initView(regionView);
initData();
setListener();
return regionView;
}
private void setListener() {
list_province.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
presenter.onItemClickListener(position,1);
}
});
list_city.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
presenter.onItemClickListener(position,2);
}
});
}
private void initData() {
pAdapter = new RegionAdapter(getBaseContext(), presenter.getProvinceList());
cAdapter = new RegionAdapter(getBaseContext(), citys);
list_province.setAdapter(pAdapter);
list_city.setAdapter(cAdapter);
}
private void initView(View regionView) {
list_province = (ListView) regionView.findViewById(R.id.list_province);
list_city = (ListView) regionView.findViewById(R.id.list_city);
}
@Override
public void showCityList(List cityList) {
cAdapter.setData(cityList);
cAdapter.notifyDataSetChanged();
}
@Override
public void showProvince(String province) {
this.province = province;
}
@Override
public void showCity(String city) {
Intent intent=new Intent();
intent.putExtra("city", city);
intent.putExtra("province", province);
getBaseActivity().setResult(Activity.RESULT_OK,intent);
getBaseActivity().finish();
}
@Override
public void setPresenter(RegionPresenter presenter) {
this.presenter = presenter;
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
private class RegionAdapter extends BaseAdapter {
private Context context;
private List data;
private LayoutInflater inflater;
public RegionAdapter(Context _context, List data) {
this.context = _context;
this.data = data;
inflater = LayoutInflater.from(context);
}
public void setData(List _data) {
data = _data;
}
@Override
public int getCount() {
return data.size();
}
@Override
public String getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_region, parent, false);
}
ViewHolder holder = (ViewHolder) convertView.getTag();
if (holder == null) {
holder = new ViewHolder();
holder.tv_name = (TextView) convertView
.findViewById(R.id.tv_name);
convertView.setTag(holder);
}
String regionName = getItem(position);
holder.tv_name.setText(regionName);
return convertView;
}
}
static class ViewHolder {
TextView tv_name;
}
@Override
public void onDestroy() {
presenter.onDestory();
super.onDestroy();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionPresenter.java
================================================
package com.htmessage.yichatopen.activity.main.region;
import com.htmessage.yichatopen.R;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 项目名称:yichat0504
* 类描述:RegionPresenter 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 14:04
* 邮箱:814326663@qq.com
*/
public class RegionPresenter implements RegionBasePrestener {
// 一个省份的数据列表
private List provinces = new ArrayList();
// 一个城市的数据列表
private List citys = new ArrayList();
// 所有省份下的城市列表
private final int[] ARRAY_CITY = new int[] { R.array.beijin_province_item,
R.array.heibei_province_item, R.array.shandong_province_item,
R.array.shanghai_province_item, R.array.guangdong_province_item,
R.array.anhui_province_item, R.array.fujian_province_item,
R.array.gansu_province_item, R.array.guangxi_province_item,
R.array.guizhou_province_item, R.array.hainan_province_item,
R.array.henan_province_item, R.array.heilongjiang_province_item,
R.array.hubei_province_item, R.array.hunan_province_item,
R.array.jilin_province_item, R.array.jiangsu_province_item,
R.array.jiangxi_province_item, R.array.liaoning_province_item,
R.array.neimenggu_province_item, R.array.ningxia_province_item,
R.array.qinghai_province_item, R.array.shanxi1_province_item,
R.array.shanxi2_province_item, R.array.sichuan_province_item,
R.array.tianjin_province_item, R.array.xizang_province_item,
R.array.xinjiang_province_item, R.array.yunnan_province_item,
R.array.zhejiang_province_item, R.array.chongqing_province_item,
R.array.taiwan_province_item, R.array.hongkong_province_item,
R.array.aomen_province_item };
private RegionView regionView;
public RegionPresenter(RegionView regionView) {
this.regionView = regionView;
this.regionView.setPresenter(this);
}
@Override
public List getProvinceList() {
provinces = Arrays.asList(regionView.getBaseActivity().getResources().getStringArray(R.array.province_item));
return provinces;
}
@Override
public List getCityList(int position) {
citys = Arrays.asList(regionView.getBaseActivity().getResources().getStringArray(ARRAY_CITY[position]));
return citys;
}
@Override
public void onDestory() {
regionView = null;
}
@Override
public void start() {
}
public void onItemClickListener(int position,int type){
if (type ==1){
String province = provinces.get(position);
regionView.showProvince(province);
regionView.showCityList(getCityList(position));
}else{
String city = citys.get(position);
regionView.showCity(city);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionView.java
================================================
package com.htmessage.yichatopen.activity.main.region;
import com.htmessage.yichatopen.activity.BaseView;
import java.util.List;
/**
* 项目名称:yichat0504
* 类描述:RegionView 描述:
* 创建人:songlijie
* 创建时间:2017/7/10 14:05
* 邮箱:814326663@qq.com
*/
public interface RegionView extends BaseView {
void showCityList(List cityList);
void showProvince(String province);
void showCity(String city);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/register/RegisterActivity.java
================================================
package com.htmessage.yichatopen.activity.register;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.BaseActivity;
/**
* 注册页
*/
public class RegisterActivity extends BaseActivity {
private RegisterPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
setTitle(R.string.register);
RegisterFragment registerFragment =
(RegisterFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (registerFragment == null) {
// Create the fragment
registerFragment =new RegisterFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame, registerFragment);
transaction.commit();
}
presenter=new RegisterPresenter(registerFragment);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
presenter.result(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/register/RegisterContract.java
================================================
package com.htmessage.yichatopen.activity.register;
import android.app.Activity;
import android.content.Intent;
import com.htmessage.yichatopen.activity.BasePresenter;
import com.htmessage.yichatopen.activity.BaseView;
/**
* Created by huangfangyi on 2017/6/23.
* qq 84543217
*/
public interface RegisterContract {
public int PHOTO_REQUEST_TAKEPHOTO = 1;// 拍照
public int PHOTO_REQUEST_GALLERY = 2;// 从相册中选择
public int PHOTO_REQUEST_CUT = 3;// 结果
public interface View extends BaseView{
void showAvatar(String imagePath);
void showDialog();
void cancelDialog();
void showPassword();
void hidePassword();
void enableButton();
void disableButton();
void showToast(int msgRes);
String getOriginImagePath();
Activity getBaseActivity();
}
public interface Presenter extends BasePresenter{
void registerInServer(String nickName,String mobile,String password);
void result(int requsetCode, int resultCode, Intent intent);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/activity/register/RegisterFragment.java
================================================
package com.htmessage.yichatopen.activity.register;
import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.Html;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.utils.CommonUtils;
import com.htmessage.yichatopen.utils.Validator;
import com.htmessage.yichatopen.widget.HTAlertDialog;
import com.soundcloud.android.crop.Crop;
import java.io.File;
/**
* Created by huangfangyi on 2017/6/23.
* qq 84543217
*/
public class RegisterFragment extends Fragment implements View.OnClickListener, RegisterContract.View {
private EditText et_usernick, et_usertel, et_password;
private Button btn_register;
private ImageView iv_hide, iv_show, iv_photo;
private TextView tv_xieyi, tv_country, tv_country_code;
private RelativeLayout rl_country;
private RegisterContract.Presenter mPresenter;
//选取的原始图片
private String imagePathOrigin = null;
private Dialog dialog;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dialog = HTApp.getInstance().createLoadingDialog(getActivity(), getString(R.string.Is_the_registered));
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_register, container, false);
et_usernick = (EditText) root.findViewById(R.id.et_usernick);
et_usertel = (EditText) root.findViewById(R.id.et_usertel);
et_password = (EditText) root.findViewById(R.id.et_password);
//获取国家code
tv_country = (TextView) root.findViewById(R.id.tv_country);
tv_country_code = (TextView) root.findViewById(R.id.tv_country_code);
rl_country = (RelativeLayout) root.findViewById(R.id.rl_country);
btn_register = (Button) root.findViewById(R.id.btn_register);
tv_xieyi = (TextView) root.findViewById(R.id.tv_xieyi);
iv_hide = (ImageView) root.findViewById(R.id.iv_hide);
iv_show = (ImageView) root.findViewById(R.id.iv_show);
iv_photo = (ImageView) root.findViewById(R.id.iv_photo);
initView();
setLisenter();
return root;
}
private void initView() {
String xieyi = "" + getString(R.string.press_top)
+ " " + "\"" + getString(R.string.register) + "\"" + " " + getString(R.string.btn_means_agree) + "" + ""
+ "" + getString(R.string.Secret_agreement)
+ "" + "";
tv_xieyi.setText(Html.fromHtml(xieyi));
}
private void setLisenter() {
// 监听多个输入框
TextChange textChange = new TextChange();
et_usernick.addTextChangedListener(textChange);
et_usertel.addTextChangedListener(textChange);
et_password.addTextChangedListener(textChange);
tv_country.setOnClickListener(this);
tv_country_code.setOnClickListener(this);
rl_country.setOnClickListener(this);
iv_hide.setOnClickListener(this);
iv_show.setOnClickListener(this);
iv_photo.setOnClickListener(this);
btn_register.setOnClickListener(this);
}
@Override
public void setPresenter(RegisterContract.Presenter presenter) {
mPresenter = presenter;
}
@Override
public Context getBaseContext() {
return getContext();
}
@Override
public void showAvatar(String imagePath) {
Glide.with(getActivity()).load(imagePath).diskCacheStrategy(DiskCacheStrategy.ALL).error(R.drawable.default_image).into(iv_photo);
}
@Override
public void showDialog() {
if (dialog != null)
dialog.show();
}
@Override
public void cancelDialog() {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
@Override
public void showPassword() {
iv_show.setVisibility(View.GONE);
iv_hide.setVisibility(View.VISIBLE);
et_password
.setTransformationMethod(PasswordTransformationMethod
.getInstance());
}
// 切换后将密码EditText光标置于末尾
private void editTextEnd() {
CharSequence charSequence = et_password.getText();
if (charSequence instanceof Spannable) {
Spannable spanText = (Spannable) charSequence;
Selection.setSelection(spanText, charSequence.length());
}
}
@Override
public void hidePassword() {
iv_hide.setVisibility(View.GONE);
iv_show.setVisibility(View.VISIBLE);
et_password
.setTransformationMethod(HideReturnsTransformationMethod
.getInstance());
}
@Override
public void enableButton() {
btn_register.setEnabled(true);
}
@Override
public void disableButton() {
btn_register.setEnabled(false);
}
@Override
public void showToast(int msgRes) {
Toast.makeText(getActivity(), msgRes, Toast.LENGTH_SHORT).show();
}
@Override
public String getOriginImagePath() {
return imagePathOrigin;
}
@Override
public Activity getBaseActivity() {
return getActivity();
}
// EditText监听器
class TextChange implements TextWatcher {
@Override
public void afterTextChanged(Editable arg0) {
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void onTextChanged(CharSequence cs, int start, int before,
int count) {
boolean sign1 = et_usernick.getText().length() > 0;
boolean sign2 = et_usertel.getText().length() > 0;
boolean sign3 = et_password.getText().length() > 0;
if (sign1 & sign2 & sign3) {
enableButton();
} else {
disableButton();
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_hide:
hidePassword();
editTextEnd();
break;
case R.id.iv_show:
showPassword();
editTextEnd();
break;
case R.id.btn_register:
String usernick = et_usernick.getText().toString().trim();
String password = et_password.getText().toString().trim();
String usertel = et_usertel.getText().toString().trim();
String country = tv_country.getText().toString().trim();
String countryCode = tv_country_code.getText().toString().trim();
if (TextUtils.isEmpty(usertel)) {
showToast(R.string.mobile_not_be_null);
return;
}
if (country.equals(getString(R.string.china)) && countryCode.equals(getString(R.string.country_code))) {
if (!Validator.isMobile(usertel)) {
showToast(R.string.please_input_true_mobile);
return;
}
}
if (TextUtils.isEmpty(password)) {
showToast(R.string.pwd_is_not_allow_null);
return;
}
mPresenter.registerInServer(usernick, usertel,password);
break;
case R.id.rl_country:
CommonUtils.showPup(getContext(), tv_country, tv_country_code);
break;
case R.id.iv_photo:
showCamera();
break;
}
}
private String getAvatarName() {
return HTApp.getInstance().getDirFilePath() + "org_" + System.currentTimeMillis() + ".png";
}
// 拍照部分
private void showCamera() {
HTAlertDialog fxAlertDialog = new HTAlertDialog(getActivity(), null, new String[]{getString(R.string.attach_take_pic), getString(R.string.image_manager)});
fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {
@Override
public void onClick(int position) {
imagePathOrigin = getAvatarName();
switch (position) {
case 0:
if(!checkPermission(Manifest.permission.CAMERA)){
return;
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 指定调用相机拍照后照片的储存路径
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File(imagePathOrigin)));
getActivity().startActivityForResult(intent, RegisterContract.PHOTO_REQUEST_TAKEPHOTO);
break;
case 1:
if( !checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ){
return;
}
Crop.pickImage(getActivity(), RegisterContract.PHOTO_REQUEST_GALLERY);
break;
}
}
});
}
private boolean checkPermission(String permissionName) {
PackageManager pm = getActivity().getPackageManager();
boolean permission = (PackageManager.PERMISSION_GRANTED ==
pm.checkPermission(permissionName, getActivity().getPackageName()));
if (permission) {
return true;
}else {
showToast(R.string.no_permission_camera);
requestPermissions(new String[]{permissionName},
REQUEST_CODE);
return false;
}
}
private static final int REQUEST_CODE=100;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if(requestCode==REQUEST_CODE){
for(int i=0;i params = new ArrayList();
params.add(new Param("usertel", usertel));
params.add(new Param("password", password));
params.add(new Param("usernick", usernick));
if (!TextUtils.isEmpty(imageName)) {
params.add(new Param("avatar", imageName));
}
new OkHttpUtils(registerView.getBaseActivity()).post(params, HTConstant.URL_REGISTER, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
int status = jsonObject.getInteger("code");
switch (status) {
case 1:
JSONObject user = jsonObject.getJSONObject("user");
if (user != null) {
HTClient.getInstance().register(user.getString(HTConstant.JSON_KEY_HXID), user.getString(HTConstant.JSON_KEY_PASSWORD), new HTClient.HTCallBack() {
@Override
public void onSuccess() {
registerView.getBaseActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
registerView.cancelDialog();
registerView.showToast(R.string.Registered_successfully);
registerView.getBaseActivity().finish();
}
});
}
@Override
public void onError() {
registerView.getBaseActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
registerView.cancelDialog();
registerView.showToast(R.string.Registration_failed);
}
});
}
});
}
break;
case -1:
registerView.cancelDialog();
registerView.showToast(R.string.mobile_is_register);
break;
case -2:
registerView.cancelDialog();
registerView.showToast(R.string.Incorrect_phone_number_format);
break;
default:
registerView.cancelDialog();
registerView.showToast(R.string.Server_busy);
break;
}
}
@Override
public void onFailure(String errorMsg) {
registerView.cancelDialog();
registerView.showToast(R.string.Server_busy);
}
});
}
private void uploadAvatar(final String usernick, final String password, final String usertel, String filePath) {
final String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
new UploadFileUtils(registerView.getBaseActivity(), fileName, filePath).asyncUploadFile(new UploadFileUtils.a() {
@Override
public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
}
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
final String url = HTConstant.baseOssUrl + fileName;
registerView.getBaseActivity(). runOnUiThread(new Runnable() {
@Override
public void run() {
register(usernick, password, usertel, url);
}
});
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
registerView.getBaseActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
registerView.cancelDialog();
}
});
}
});
}
@Override
public void result(int requestCode, int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case RegisterContract.PHOTO_REQUEST_GALLERY:
if (intent != null)
beginCrop(intent.getData());
break;
case RegisterContract.PHOTO_REQUEST_TAKEPHOTO:
beginCrop(Uri.fromFile(new File(registerView.getOriginImagePath())));
break;
case RegisterContract.PHOTO_REQUEST_CUT:
Uri output = Crop.getOutput(intent);
Log.d("output---->",output.getPath());
registerView.showAvatar(output.getPath());
break;
}
} else {
//裁剪失败
if(requestCode==RegisterContract.PHOTO_REQUEST_CUT){
cropImagePath=null;
registerView.showAvatar(null);
}
}
}
private void beginCrop(Uri inputUri) {
cropImagePath= HTApp.getInstance().getDirFilePath() + "crop_" + System.currentTimeMillis() + ".png";
Uri outputUri = Uri.fromFile(new File(cropImagePath));
Crop.of(inputUri, outputUri).asSquare().start(registerView.getBaseActivity(), RegisterContract.PHOTO_REQUEST_CUT);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/domain/InviteMessage.java
================================================
package com.htmessage.yichatopen.domain;
public class InviteMessage {
private String from;
private long time;
private String reason;
private Status status;
private int id;
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public enum Status {
BEINVITEED,
BEREFUSED,
BEAGREED,
AGREED,
REFUSED
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/domain/InviteMessgeDao.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.domain;
import android.content.ContentValues;
import android.content.Context;
import com.htmessage.yichatopen.manager.DBManager;
import java.util.List;
public class InviteMessgeDao {
public static final String TABLE_NAME = "new_friends_msgs";
public static final String COLUMN_NAME_ID = "id";
public static final String COLUMN_NAME_FROM = "username";
public static final String COLUMN_NAME_GROUP_ID = "groupid";
public static final String COLUMN_NAME_GROUP_Name = "groupname";
public static final String COLUMN_NAME_TIME = "time";
public static final String COLUMN_NAME_REASON = "reason";
public static final String COLUMN_NAME_STATUS = "status";
public static final String COLUMN_NAME_ISINVITEFROMME = "isInviteFromMe";
public static final String COLUMN_NAME_GROUPINVITER = "groupinviter";
public static final String COLUMN_NAME_UNREAD_MSG_COUNT = "unreadMsgCount";
public InviteMessgeDao(Context context){
}
/**
* save message
* @param message
* @return return cursor of the message
*/
public Integer saveMessage(InviteMessage message){
return DBManager.getInstance().saveMessage(message);
}
/**
* update message
* @param msgId
* @param values
*/
public void updateMessage(int msgId,ContentValues values){
DBManager.getInstance().updateMessage(msgId, values);
}
/**
* get messges
* @return
*/
public List getMessagesList(){
return DBManager.getInstance().getMessagesList();
}
public void deleteMessage(String from){
DBManager.getInstance().deleteMessage(from);
}
public int getUnreadMessagesCount(){
return DBManager.getInstance().getUnreadNotifyCount();
}
public void saveUnreadMessageCount(int count){
DBManager.getInstance().setUnreadNotifyCount(count);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/domain/User.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.domain;
import android.annotation.SuppressLint;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.utils.CommonUtils;
@SuppressLint("ParcelCreator")
public class User implements Parcelable {
/**
* initial letter for nickname
*/
protected String initialLetter;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
/**
* avatar of the user
*/
protected String avatar;
private String username;
protected String userInfo;
private String nick;
public String getNick() {
return nick;
}
public void setNick(String nick) {
this.nick = nick;
}
public User(String username){
this.username = username;
}
public String getInitialLetter() {
if(initialLetter == null){
CommonUtils.setUserInitialLetter(this);
}
return initialLetter;
}
public void setInitialLetter(String initialLetter) {
this.initialLetter = initialLetter;
}
public String getAvatar() {
if(!TextUtils.isEmpty(avatar)){
if (!avatar.contains("http")){
avatar = HTConstant.URL_AVATAR+avatar;
}
}
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getUserInfo(){
return userInfo;
}
public void setUserInfo(String userInfo){
this.userInfo=userInfo;
}
@Override
public int hashCode() {
return 17 * getUsername().hashCode();
}
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof User)) {
return false;
}
return getUsername().equals(((User) o).getUsername());
}
@Override
public String toString() {
return nick == null ? username : nick;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/domain/UserDao.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.domain;
import android.content.Context;
import com.htmessage.yichatopen.manager.DBManager;
import java.util.List;
import java.util.Map;
public class UserDao {
public static final String TABLE_NAME = "uers";
public static final String COLUMN_NAME_ID = "username";
public static final String COLUMN_NAME_NICK = "nick";
public static final String COLUMN_NAME_AVATAR = "avatar";
public static final String COLUMN_NAME_INFO = "userInfo";
public static final String PREF_TABLE_NAME = "pref";
public static final String COLUMN_NAME_DISABLED_GROUPS = "disabled_groups";
public static final String COLUMN_NAME_DISABLED_IDS = "disabled_ids";
public static final String ROBOT_TABLE_NAME = "robots";
public static final String ROBOT_COLUMN_NAME_ID = "username";
public static final String ROBOT_COLUMN_NAME_NICK = "nick";
public static final String ROBOT_COLUMN_NAME_AVATAR = "avatar";
public UserDao(Context context) {
}
/**
* save contact list
*
* @param contactList
*/
public void saveContactList(List contactList) {
DBManager.getInstance().saveContactList(contactList);
}
/**
* get contact list
*
* @return
*/
public Map getContactList() {
return DBManager.getInstance().getContactList();
}
/**
* delete a contact
* @param username
*/
public void deleteContact(String username){
DBManager.getInstance().deleteContact(username);
}
/**
* save a contact
* @param user
*/
public void saveContact(User user){
DBManager.getInstance().saveContact(user);
}
public void setDisabledGroups(List groups){
DBManager.getInstance().setDisabledGroups(groups);
}
public List getDisabledGroups(){
return DBManager.getInstance().getDisabledGroups();
}
public void setDisabledIds(List ids){
DBManager.getInstance().setDisabledIds(ids);
}
public List getDisabledIds(){
return DBManager.getInstance().getDisabledIds();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/ContactsManager.java
================================================
package com.htmessage.yichatopen.manager;
import android.content.Context;
import android.util.Log;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.domain.UserDao;
import java.util.List;
import java.util.Map;
/**
* Created by huangfangyi on 2016/12/8.
* qq 84543217
*/
public class ContactsManager {
private static ContactsManager contactsManager;
private Context context;
private UserDao userDao;
private Map contacts=null;
synchronized public static void init(Context context) {
if (contactsManager == null) {
contactsManager = new ContactsManager(context);
}
}
public ContactsManager(Context context) {
this.context = context;
userDao= new UserDao(context);
initContacts();
}
public static ContactsManager getInstance(){
if(contactsManager==null){
throw new RuntimeException("please init this first!");
}
return contactsManager;
}
public boolean saveContactList(List contactList) {
Log.d("saveContactList----->",contactList.size()+"");
contacts.clear();
for (User user:contactList){
contacts.put(user.getUsername(),user);
}
userDao.saveContactList(contactList);
return true;
}
public Map getContactList() {
if(contacts==null){
contacts=userDao.getContactList();
}
return contacts;
}
public void saveContact(User user){
contacts.put(user.getUsername(),user);
userDao.saveContact(user);
}
private void initContacts(){
contacts=userDao.getContactList();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/DBManager.java
================================================
package com.htmessage.yichatopen.manager;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.domain.InviteMessage;
import com.htmessage.yichatopen.domain.InviteMessage.Status;
import com.htmessage.yichatopen.domain.InviteMessgeDao;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.domain.UserDao;
import com.htmessage.yichatopen.utils.CommonUtils;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
public class DBManager {
static private DBManager dbMgr = new DBManager();
private DbOpenHelper dbHelper;
private DBManager() {
dbHelper = DbOpenHelper.getInstance(HTApp.getInstance().getApplicationContext());
}
public static synchronized DBManager getInstance() {
if (dbMgr == null) {
dbMgr = new DBManager();
}
return dbMgr;
}
/**
* save contact list
*
* @param contactList
*/
synchronized public void saveContactList(List contactList) {
Log.d("saveContactList3----->", contactList.size() + "");
SQLiteDatabase db = dbHelper.getWritableDatabase();
if (db.isOpen()) {
db.delete(UserDao.TABLE_NAME, null, null);
for (User user : contactList) {
ContentValues values = new ContentValues();
values.put(UserDao.COLUMN_NAME_ID, user.getUsername());
if (user.getNick() != null)
values.put(UserDao.COLUMN_NAME_NICK, user.getNick());
if (user.getAvatar() != null)
values.put(UserDao.COLUMN_NAME_AVATAR, user.getAvatar());
if (user.getUserInfo() != null)
values.put(UserDao.COLUMN_NAME_INFO, user.getUserInfo());
db.replace(UserDao.TABLE_NAME, null, values);
}
}
}
/**
* get contact list
*
* @return
*/
synchronized public Map getContactList() {
SQLiteDatabase db = dbHelper.getReadableDatabase();
Map users = new Hashtable();
if (db.isOpen()) {
Cursor cursor = db.rawQuery("select * from " + UserDao.TABLE_NAME /* + " desc" */, null);
while (cursor.moveToNext()) {
String username = cursor.getString(cursor.getColumnIndex(UserDao.COLUMN_NAME_ID));
String nick = cursor.getString(cursor.getColumnIndex(UserDao.COLUMN_NAME_NICK));
String avatar = cursor.getString(cursor.getColumnIndex(UserDao.COLUMN_NAME_AVATAR));
String userInfo = cursor.getString(cursor.getColumnIndex(UserDao.COLUMN_NAME_INFO));
User user = new User(username);
user.setNick(nick);
user.setAvatar(avatar);
user.setUserInfo(userInfo);
CommonUtils.setUserInitialLetter(user);
if ("123456789".contains(user.getInitialLetter())) {
user.setInitialLetter("#");
}
users.put(username, user);
}
cursor.close();
}
return users;
}
/**
* delete a contact
*
* @param username
*/
synchronized public void deleteContact(String username) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
if (db.isOpen()) {
db.delete(UserDao.TABLE_NAME, UserDao.COLUMN_NAME_ID + " = ?", new String[]{username});
}
}
/**
* save a contact
*
* @param user
*/
synchronized public void saveContact(User user) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(UserDao.COLUMN_NAME_ID, user.getUsername());
if (user.getNick() != null)
values.put(UserDao.COLUMN_NAME_NICK, user.getNick());
if (user.getAvatar() != null)
values.put(UserDao.COLUMN_NAME_AVATAR, user.getAvatar());
if (user.getUserInfo() != null)
values.put(UserDao.COLUMN_NAME_INFO, user.getUserInfo());
if (db.isOpen()) {
db.replace(UserDao.TABLE_NAME, null, values);
}
}
public void setDisabledGroups(List groups) {
setList(UserDao.COLUMN_NAME_DISABLED_GROUPS, groups);
}
public List getDisabledGroups() {
return getList(UserDao.COLUMN_NAME_DISABLED_GROUPS);
}
public void setDisabledIds(List ids) {
setList(UserDao.COLUMN_NAME_DISABLED_IDS, ids);
}
public List getDisabledIds() {
return getList(UserDao.COLUMN_NAME_DISABLED_IDS);
}
synchronized private void setList(String column, List strList) {
StringBuilder strBuilder = new StringBuilder();
for (String hxid : strList) {
strBuilder.append(hxid).append("$");
}
SQLiteDatabase db = dbHelper.getWritableDatabase();
if (db.isOpen()) {
ContentValues values = new ContentValues();
values.put(column, strBuilder.toString());
db.update(UserDao.PREF_TABLE_NAME, values, null, null);
}
}
synchronized private List getList(String column) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select " + column + " from " + UserDao.PREF_TABLE_NAME, null);
if (!cursor.moveToFirst()) {
cursor.close();
return null;
}
String strVal = cursor.getString(0);
if (strVal == null || strVal.equals("")) {
return null;
}
cursor.close();
String[] array = strVal.split("$");
if (array != null && array.length > 0) {
List list = new ArrayList();
for (String str : array) {
list.add(str);
}
return list;
}
return null;
}
/**
* save a message
*
* @param message
* @return return cursor of the message
*/
public synchronized Integer saveMessage(InviteMessage message) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int id = -1;
if (db.isOpen()) {
ContentValues values = new ContentValues();
values.put(InviteMessgeDao.COLUMN_NAME_FROM, message.getFrom());
values.put(InviteMessgeDao.COLUMN_NAME_REASON, message.getReason());
values.put(InviteMessgeDao.COLUMN_NAME_TIME, message.getTime());
values.put(InviteMessgeDao.COLUMN_NAME_STATUS, message.getStatus().ordinal());
db.insert(InviteMessgeDao.TABLE_NAME, null, values);
Cursor cursor = db.rawQuery("select last_insert_rowid() from " + InviteMessgeDao.TABLE_NAME, null);
if (cursor.moveToFirst()) {
id = cursor.getInt(0);
}
cursor.close();
}
return id;
}
/**
* update message
*
* @param msgId
* @param values
*/
synchronized public void updateMessage(int msgId, ContentValues values) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
if (db.isOpen()) {
db.update(InviteMessgeDao.TABLE_NAME, values, InviteMessgeDao.COLUMN_NAME_ID + " = ?", new String[]{String.valueOf(msgId)});
}
}
/**
* get messges
*
* @return
*/
synchronized public List getMessagesList() {
SQLiteDatabase db = dbHelper.getReadableDatabase();
List msgs = new ArrayList();
if (db.isOpen()) {
Cursor cursor = db.rawQuery("select * from " + InviteMessgeDao.TABLE_NAME + " desc", null);
while (cursor.moveToNext()) {
InviteMessage msg = new InviteMessage();
int id = cursor.getInt(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_ID));
String from = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_FROM));
String groupid = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_GROUP_ID));
String groupname = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_GROUP_Name));
String reason = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_REASON));
long time = cursor.getLong(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_TIME));
int status = cursor.getInt(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_STATUS));
String groupInviter = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_GROUPINVITER));
msg.setId(id);
msg.setFrom(from);
msg.setReason(reason);
msg.setTime(time);
if (status == Status.BEINVITEED.ordinal())
msg.setStatus(Status.BEINVITEED);
else if (status == Status.BEAGREED.ordinal())
msg.setStatus(Status.BEAGREED);
else if (status == Status.BEREFUSED.ordinal())
msg.setStatus(Status.BEREFUSED);
else if (status == Status.AGREED.ordinal())
msg.setStatus(Status.AGREED);
else if (status == Status.REFUSED.ordinal())
msg.setStatus(Status.REFUSED);
msgs.add(msg);
}
cursor.close();
}
return msgs;
}
/**
* delete invitation message
*
* @param from
*/
synchronized public void deleteMessage(String from) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
if (db.isOpen()) {
db.delete(InviteMessgeDao.TABLE_NAME, InviteMessgeDao.COLUMN_NAME_FROM + " = ?", new String[]{from});
}
}
public synchronized int getUnreadNotifyCount() {
int count = 0;
SQLiteDatabase db = dbHelper.getReadableDatabase();
if (db.isOpen()) {
Cursor cursor = db.rawQuery("select " + InviteMessgeDao.COLUMN_NAME_UNREAD_MSG_COUNT + " from " + InviteMessgeDao.TABLE_NAME, null);
if (cursor.moveToFirst()) {
count = cursor.getInt(0);
}
cursor.close();
}
return count;
}
public synchronized void setUnreadNotifyCount(int count) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
if (db.isOpen()) {
ContentValues values = new ContentValues();
values.put(InviteMessgeDao.COLUMN_NAME_UNREAD_MSG_COUNT, count);
db.update(InviteMessgeDao.TABLE_NAME, values, null, null);
}
}
synchronized public void closeDB() {
if (dbHelper != null) {
dbHelper.closeDB();
}
dbMgr = null;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/DbOpenHelper.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.manager;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.domain.InviteMessgeDao;
import com.htmessage.yichatopen.domain.UserDao;
public class DbOpenHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static DbOpenHelper instance;
private static final String USERNAME_TABLE_CREATE = "CREATE TABLE "
+ UserDao.TABLE_NAME + " ("
+ UserDao.COLUMN_NAME_NICK + " TEXT, "
+ UserDao.COLUMN_NAME_AVATAR + " TEXT, "
+ UserDao.COLUMN_NAME_INFO+ " TEXT, "
+ UserDao.COLUMN_NAME_ID + " TEXT PRIMARY KEY);";
private static final String INIVTE_MESSAGE_TABLE_CREATE = "CREATE TABLE "
+ InviteMessgeDao.TABLE_NAME + " ("
+ InviteMessgeDao.COLUMN_NAME_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ InviteMessgeDao.COLUMN_NAME_FROM + " TEXT, "
+ InviteMessgeDao.COLUMN_NAME_GROUP_ID + " TEXT, "
+ InviteMessgeDao.COLUMN_NAME_GROUP_Name + " TEXT, "
+ InviteMessgeDao.COLUMN_NAME_REASON + " TEXT, "
+ InviteMessgeDao.COLUMN_NAME_STATUS + " INTEGER, "
+ InviteMessgeDao.COLUMN_NAME_ISINVITEFROMME + " INTEGER, "
+ InviteMessgeDao.COLUMN_NAME_UNREAD_MSG_COUNT + " INTEGER, "
+ InviteMessgeDao.COLUMN_NAME_TIME + " TEXT, "
+ InviteMessgeDao.COLUMN_NAME_GROUPINVITER + " TEXT); ";
private DbOpenHelper(Context context) {
super(context, getUserDatabaseName(), null, DATABASE_VERSION);
Log.d("SDKDbOpenHelper----->",getUserDatabaseName());
}
public static DbOpenHelper getInstance(Context context) {
if (instance == null) {
instance = new DbOpenHelper(context.getApplicationContext());
}
return instance;
}
private static String getUserDatabaseName() {
return HTApp.getInstance().getUsername()+ "_app.db";
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(USERNAME_TABLE_CREATE);
db.execSQL(INIVTE_MESSAGE_TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void closeDB() {
if (instance != null) {
try {
SQLiteDatabase db = instance.getWritableDatabase();
db.close();
} catch (Exception e) {
e.printStackTrace();
}
instance = null;
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/LocalUserManager.java
================================================
/**
* Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.manager;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
public class LocalUserManager {
/**
* 保存Preference的name
*/
public static final String PREFERENCE_NAME = "userInfo";
private static SharedPreferences mSharedPreferences;
private static LocalUserManager mPreferencemManager;
private static SharedPreferences.Editor editor;
private String SHARED_KEY_USER_INFO = "shared_key_user_info";
private static Context context;
private LocalUserManager(Context cxt) {
this.context=cxt;
mSharedPreferences = cxt.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
editor = mSharedPreferences.edit();
}
public static synchronized void init(Context cxt) {
if (mPreferencemManager == null) {
mPreferencemManager = new LocalUserManager(cxt);
}
}
/**
* 单例模式,获取instance实例
*
* @param
* @return
*/
public synchronized static LocalUserManager getInstance() {
Log.d("CurrentUserManager---->",context.getPackageName());
if (mPreferencemManager == null) {
throw new RuntimeException("please init first!");
}
return mPreferencemManager;
}
public void setUserJson(JSONObject userJson) {
String userInfo = "";
if (userJson != null) {
try {
userInfo = userJson.toJSONString();
} catch (JSONException e) {
}
}
editor.putString(SHARED_KEY_USER_INFO, userInfo);
editor.commit();
}
public JSONObject getUserJson() {
JSONObject userJson =null;
String userStr = mSharedPreferences.getString(SHARED_KEY_USER_INFO, null);
if (userStr != null) {
userJson = JSONObject.parseObject(userStr);
}
return userJson;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/Manager.java
================================================
package com.htmessage.yichatopen.manager;
import android.content.Context;
/**
* Created by huangfangyi on 2016/12/8.
* qq 84543217
*/
public class Manager {
public static void initManagerList(Context context){
NotifierManager.init(context);
ContactsManager.init(context);
SettingsManager.init(context);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/MyNotification.java
================================================
package com.htmessage.yichatopen.manager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.domain.User;
import com.htmessage.yichatopen.activity.chat.ChatActivity;
import com.htmessage.sdk.ChatType;
import com.htmessage.sdk.client.HTClient;
import com.htmessage.sdk.model.HTConversation;
import com.htmessage.sdk.model.HTMessage;
import com.htmessage.sdk.model.HTMessageTextBody;
/**
* Created by huangfangyi on 2016/12/19.
* qq 84543217
*/
public class MyNotification {
private static MyNotification myNotification;
private static NotificationManager manager = null;
private Context mContext;
private Notification.Builder nBuilder;
private NotificationCompat.Builder builder;
private boolean isOpenOutGoing = false;//默认不打开常驻 打开滑动删除
private static Notification notification;
public MyNotification(Context context) {
this.mContext = context;
manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
//为了版本兼容 选择V4包下的NotificationCompat进行构造
builder = new NotificationCompat.Builder(mContext);
nBuilder = new Notification.Builder(mContext);
setOutGoingAndAutoCancle(isOpenOutGoing);// 默认不打开常驻
}
public static void init(Context context) {
if (myNotification == null) {
myNotification = new MyNotification(context);
}
}
public static MyNotification getInstance() {
if (myNotification == null) {
throw new RuntimeException("please init first~!");
}
return myNotification;
}
/**
* 设置常驻和滑动删除是否打开
*
* @param flag false 打开滑动删除,不设置常驻 true 设置常驻,不设置滑动删除
*/
public void setOutGoingAndAutoCancle(@NonNull boolean flag) {
if (builder != null) {
builder.setAutoCancel(!flag);
builder.setOngoing(flag);
}
if (nBuilder != null) {
nBuilder.setAutoCancel(!flag);
nBuilder.setOngoing(flag);
}
}
public void onNewMessage(HTMessage htMessage) {
String userId = htMessage.getUsername();
String userNick = userId;
Intent intent = new Intent();
intent.setClass(mContext, ChatActivity.class);
intent.putExtra("userId", userId);
if (htMessage.getChatType() == ChatType.singleChat) {
User user = ContactsManager.getInstance().getContactList().get(userId);
if (user != null) {
userNick = user.getNick();
}
}
// 如果当前Activity启动在前台,则不开启新的Activity。
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, Integer.valueOf(userId), intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder
.setContentIntent(pendingIntent)
.setContentTitle(userNick)
// .setTicker("发来一个新消息")
.setContentText(getContent(htMessage))
.setWhen(System.currentTimeMillis())
.setSmallIcon(mContext.getApplicationInfo().icon);
notification = builder.build();
notification.flags = Notification.FLAG_ONGOING_EVENT;
notification.flags = Notification.FLAG_AUTO_CANCEL;
manager.notify(Integer.valueOf(userId), notification);//发送通知
}
public void cancel(int id) {
manager.cancel(id);
}
protected final static String[] msgs = { "发来一张图片", "发来一段语音"};
private String getContent(HTMessage message) {
HTConversation htConversation = HTClient.getInstance().conversationManager().getConversation(message.getFrom());
String notifyText = "";
if (htConversation != null) {
if (htConversation.getUnReadCount() > 0) {
notifyText = mContext.getString(R.string.zhongkuohao) + htConversation.getUnReadCount() + mContext.getString(R.string.zhongkuohao_msg);
}
}
switch (message.getType()) {
case TEXT:
HTMessageTextBody htMessageTextBody = (HTMessageTextBody) message.getBody();
String content = htMessageTextBody.getContent();
if (content != null) {
notifyText += content;
} else {
notifyText += msgs[0];
}
break;
case IMAGE:
notifyText += msgs[0];
break;
case VOICE:
notifyText += msgs[1];
break;
}
return notifyText;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/Notifier.java
================================================
/************************************************************
* * Hyphenate CONFIDENTIAL
* __________________
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Hyphenate Inc.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Hyphenate Inc.
*/
package com.htmessage.yichatopen.manager;
import android.app.ActivityManager;
import android.app.NotificationManager;
import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Vibrator;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
/**
* new message notifier class
*
* this class is subject to be inherited and implement the relative APIs
*/
public class Notifier {
private final static String TAG = "notify";
Ringtone ringtone = null;
protected final static String[] msg_eng = {"sent a message", "sent a picture", "sent a voice",
"sent location message", "sent a video", "sent a file", "%1 contacts sent %2 messages"
};
protected final static String[] msg_ch = {"发来一条消息", "发来一张图片", "发来一段语音", "发来位置信息", "发来一个视频", "发来一个文件",
"%1个联系人发来%2条消息"
};
protected static int notifyID = 0525; // start notification id
protected static int foregroundNotifyID = 0555;
protected NotificationManager notificationManager = null;
protected HashSet fromUsers = new HashSet();
protected int notificationNum = 0;
protected Context appContext;
protected String packageName;
protected String[] msgs;
protected long lastNotifiyTime;
protected AudioManager audioManager;
protected Vibrator vibrator;
public Notifier() {
}
/**
* this function can be override
*
* @param context
* @return
*/
public Notifier init(Context context) {
appContext = context;
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
packageName = appContext.getApplicationInfo().packageName;
if (Locale.getDefault().getLanguage().equals("zh")) {
msgs = msg_ch;
} else {
msgs = msg_eng;
}
audioManager = (AudioManager) appContext.getSystemService(Context.AUDIO_SERVICE);
vibrator = (Vibrator) appContext.getSystemService(Context.VIBRATOR_SERVICE);
return this;
}
/**
* this function can be override
*/
public void reset() {
resetNotificationCount();
cancelNotificaton();
}
void resetNotificationCount() {
notificationNum = 0;
fromUsers.clear();
}
void cancelNotificaton() {
if (notificationManager != null)
notificationManager.cancel(notifyID);
}
public static boolean isAppRunningForeground(Context context) {
ActivityManager var1 = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List var2 = var1.getRunningTasks(1);
return context.getPackageName().equalsIgnoreCase(((ActivityManager.RunningTaskInfo) var2.get(0)).baseActivity.getPackageName());
}
//
//
// /**
// * vibrate and play tone
// */
// public void vibrateAndPlayTone( String string) {
//
//
// if (System.currentTimeMillis() - lastNotifiyTime < 1000) {
// // received new messages within 2 seconds, skip play ringtone
// return;
// }
//
// try {
// lastNotifiyTime = System.currentTimeMillis();
//
// // check if in silent mode
// if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
// return;
// }
//
//// long[] pattern = new long[] { 0, 180, 80, 120 };
//// vibrator.vibrate(pattern, -1);
// if (ringtone == null) {
// Uri notificationUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
//
// ringtone = RingtoneManager.getRingtone(appContext, notificationUri);
// if (ringtone == null) {
// return;
// }
// }
//
// if (!ringtone.isPlaying()) {
// String vendor = Build.MANUFACTURER;
//
// ringtone.play();
// // for samsung S3, we meet a bug that the phone will
// // continue ringtone without stop
// // so add below special handler to stop it after 3s if
// // needed
// if (vendor != null && vendor.toLowerCase().contains("samsung")) {
// Thread ctlThread = new Thread() {
// public void run() {
// try {
// Thread.sleep(3000);
// if (ringtone.isPlaying()) {
// ringtone.stop();
// }
// } catch (Exception e) {
// }
// }
// };
// ctlThread.run();
// }
// }
//
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
/**
* vibrate and play tone
*/
public void vibrateAndPlayTone(String string) {
if (System.currentTimeMillis() - lastNotifiyTime < 1000) { //时间间隔小于1秒钟的返回
// received new messages within 2 seconds, skip play ringtone
return;
}
lastNotifiyTime=System.currentTimeMillis();
playSoundAndVibrator();
}
/**
* 播放声音
*/
private void playSound() {
try {
lastNotifiyTime = System.currentTimeMillis();
// check if in silent mode
if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
return;
}
if (ringtone == null) {
Uri notificationUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
ringtone = RingtoneManager.getRingtone(appContext, notificationUri);
if (ringtone == null) {
return;
}
}
if (!ringtone.isPlaying()) {
String vendor = Build.MANUFACTURER;
ringtone.play();
// for samsung S3, we meet a bug that the phone will
// continue ringtone without stop
// so add below special handler to stop it after 3s if
// needed
if (vendor != null && vendor.toLowerCase().contains("samsung")) {
Thread ctlThread = new Thread() {
public void run() {
try {
Thread.sleep(3000);
if (ringtone.isPlaying()) {
ringtone.stop();
}
} catch (Exception e) {
}
}
};
ctlThread.run();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 声音和震动
*/
private void playSoundAndVibrator() {
try {
lastNotifiyTime = System.currentTimeMillis();
// check if in silent mode
if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
return;
}
if (vibrator == null) {
vibrator = (Vibrator) appContext.getSystemService(Context.VIBRATOR_SERVICE);
}
if (ringtone == null) {
Uri notificationUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
ringtone = RingtoneManager.getRingtone(appContext, notificationUri);
if (ringtone == null) {
return;
}
}
/**
* 四个参数就是——停止 开启 停止 开启
* -1不重复,非-1为从pattern的指定下标开始重复
*/
long[] pattern = new long[]{0, 180, 80, 120};
vibrator.vibrate(pattern, -1);
/**
* 播放声音
*/
if (!ringtone.isPlaying()) {
String vendor = Build.MANUFACTURER;
ringtone.play();
// for samsung S3, we meet a bug that the phone will
// continue ringtone without stop
// so add below special handler to stop it after 3s if
// needed
if (vendor != null && vendor.toLowerCase().contains("samsung")) {
Thread ctlThread = new Thread() {
public void run() {
try {
Thread.sleep(3000);
if (ringtone.isPlaying()) {
ringtone.stop();
}
} catch (Exception e) {
}
}
};
ctlThread.run();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 震动
*/
private void playVibrator() {
lastNotifiyTime = System.currentTimeMillis();
if (vibrator == null) {
vibrator = (Vibrator) appContext.getSystemService(Context.VIBRATOR_SERVICE);
}
/**
* 四个参数就是——停止 开启 停止 开启
* -1不重复,非-1为从pattern的指定下标开始重复
*/
long[] pattern = new long[]{0, 180, 80, 120};
vibrator.vibrate(pattern, -1);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/NotifierManager.java
================================================
package com.htmessage.yichatopen.manager;
import android.content.Context;
/**
* Created by huangfangyi on 2016/10/12.
* qq 84543217
*/
public class NotifierManager {
private static NotifierManager notifierManager = null;
/**
* application context
*/
private Context appContext;
/**
* get notifierManager of EaseUI
*
* @return
*/
public static NotifierManager getInstance() {
if (notifierManager == null) {
throw new RuntimeException("NotifierManager please init first!");
}
return notifierManager;
}
public static synchronized void init(Context context) {
if (notifierManager == null) {
notifierManager = new NotifierManager(context);
}
}
public NotifierManager(Context context) {
appContext = context;
initNotifier();
}
/**
* the notifier
*/
private Notifier notifier = null;
private void initNotifier() {
notifier = createNotifier();
notifier.init(appContext);
}
protected Notifier createNotifier() {
return new Notifier();
}
public Notifier getNotifier() {
return notifier;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/PreferenceManager.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.manager;
import android.content.Context;
import android.content.SharedPreferences;
public class PreferenceManager {
/**
* name of preference
*/
public static final String PREFERENCE_NAME = "saveInfo";
private static SharedPreferences mSharedPreferences;
private static PreferenceManager mPreferencemManager;
private static SharedPreferences.Editor editor;
private String SHARED_KEY_SETTING_NOTIFICATION = "shared_key_setting_notification";
private String SHARED_KEY_SETTING_SOUND = "shared_key_setting_sound";
private String SHARED_KEY_SETTING_VIBRATE = "shared_key_setting_vibrate";
private String SHARED_KEY_SETTING_SPEAKER = "shared_key_setting_speaker";
private static String SHARED_KEY_SETTING_CHATROOM_OWNER_LEAVE = "shared_key_setting_chatroom_owner_leave";
private static String SHARED_KEY_SETTING_DELETE_MESSAGES_WHEN_EXIT_GROUP = "shared_key_setting_delete_messages_when_exit_group";
private static String SHARED_KEY_SETTING_AUTO_ACCEPT_GROUP_INVITATION = "shared_key_setting_auto_accept_group_invitation";
private static String SHARED_KEY_SETTING_ADAPTIVE_VIDEO_ENCODE = "shared_key_setting_adaptive_video_encode";
private static String SHARED_KEY_SETTING_GROUPS_SYNCED = "SHARED_KEY_SETTING_GROUPS_SYNCED";
private static String SHARED_KEY_SETTING_CONTACT_SYNCED = "SHARED_KEY_SETTING_CONTACT_SYNCED";
private static String SHARED_KEY_SETTING_BALCKLIST_SYNCED = "SHARED_KEY_SETTING_BALCKLIST_SYNCED";
private static String SHARED_KEY_CURRENTUSER_USERNAME = "SHARED_KEY_CURRENTUSER_USERNAME";
private static String SHARED_KEY_CURRENTUSER_NICK = "SHARED_KEY_CURRENTUSER_NICK";
private static String SHARED_KEY_CURRENTUSER_AVATAR = "SHARED_KEY_CURRENTUSER_AVATAR";
private PreferenceManager(Context cxt) {
mSharedPreferences = cxt.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
editor = mSharedPreferences.edit();
}
public static synchronized void init(Context cxt) {
if (mPreferencemManager == null) {
mPreferencemManager = new PreferenceManager(cxt);
}
}
/**
* get instance of PreferenceManager
*
* @param
* @return
*/
public synchronized static PreferenceManager getInstance() {
if (mPreferencemManager == null) {
throw new RuntimeException("please init first!");
}
return mPreferencemManager;
}
public void setSettingMsgNotification(boolean paramBoolean) {
editor.putBoolean(SHARED_KEY_SETTING_NOTIFICATION, paramBoolean);
editor.commit();
}
private static final String KEY_GROUP = "KEY_GROUP";
public void setActivityCount(String groupId, int count) {
editor.putInt(KEY_GROUP + groupId, count);
editor.commit();
}
public int getActivityCount(String groupId) {
return mSharedPreferences.getInt(KEY_GROUP + groupId, 0);
}
public boolean getSettingMsgNotification() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_NOTIFICATION, true);
}
public void setSettingMsgSound(boolean paramBoolean) {
editor.putBoolean(SHARED_KEY_SETTING_SOUND, paramBoolean);
editor.commit();
}
public boolean getSettingMsgSound() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_SOUND, true);
}
public void setSettingMsgVibrate(boolean paramBoolean) {
editor.putBoolean(SHARED_KEY_SETTING_VIBRATE, paramBoolean);
editor.commit();
}
public boolean getSettingMsgVibrate() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_VIBRATE, true);
}
public void setSettingMsgSpeaker(boolean paramBoolean) {
editor.putBoolean(SHARED_KEY_SETTING_SPEAKER, paramBoolean);
editor.commit();
}
public boolean getSettingMsgSpeaker() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_SPEAKER, true);
}
public void setSettingAllowChatroomOwnerLeave(boolean value) {
editor.putBoolean(SHARED_KEY_SETTING_CHATROOM_OWNER_LEAVE, value);
editor.commit();
}
public boolean getSettingAllowChatroomOwnerLeave() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_CHATROOM_OWNER_LEAVE, true);
}
public void setDeleteMessagesAsExitGroup(boolean value) {
editor.putBoolean(SHARED_KEY_SETTING_DELETE_MESSAGES_WHEN_EXIT_GROUP, value);
editor.commit();
}
public boolean isDeleteMessagesAsExitGroup() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_DELETE_MESSAGES_WHEN_EXIT_GROUP, true);
}
public void setAutoAcceptGroupInvitation(boolean value) {
editor.putBoolean(SHARED_KEY_SETTING_AUTO_ACCEPT_GROUP_INVITATION, value);
editor.commit();
}
public boolean isAutoAcceptGroupInvitation() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_AUTO_ACCEPT_GROUP_INVITATION, true);
}
public void setAdaptiveVideoEncode(boolean value) {
editor.putBoolean(SHARED_KEY_SETTING_ADAPTIVE_VIDEO_ENCODE, value);
editor.commit();
}
public boolean isAdaptiveVideoEncode() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_ADAPTIVE_VIDEO_ENCODE, false);
}
public void setGroupsSynced(boolean synced) {
editor.putBoolean(SHARED_KEY_SETTING_GROUPS_SYNCED, synced);
editor.commit();
}
public boolean isGroupsSynced() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_GROUPS_SYNCED, false);
}
public void setContactSynced(boolean synced) {
editor.putBoolean(SHARED_KEY_SETTING_CONTACT_SYNCED, synced);
editor.commit();
}
public boolean isContactSynced() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_CONTACT_SYNCED, false);
}
public void setBlacklistSynced(boolean synced) {
editor.putBoolean(SHARED_KEY_SETTING_BALCKLIST_SYNCED, synced);
editor.commit();
}
public boolean isBacklistSynced() {
return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_BALCKLIST_SYNCED, false);
}
public void setCurrentUserNick(String nick) {
editor.putString(SHARED_KEY_CURRENTUSER_NICK, nick);
editor.commit();
}
public void setCurrentUserAvatar(String avatar) {
editor.putString(SHARED_KEY_CURRENTUSER_AVATAR, avatar);
editor.commit();
}
public String getCurrentUserNick() {
return mSharedPreferences.getString(SHARED_KEY_CURRENTUSER_NICK, null);
}
public String getCurrentUserAvatar() {
return mSharedPreferences.getString(SHARED_KEY_CURRENTUSER_AVATAR, null);
}
public void setCurrentUserName(String username) {
editor.putString(SHARED_KEY_CURRENTUSER_USERNAME, username);
editor.commit();
}
public String getCurrentUsername() {
return mSharedPreferences.getString(SHARED_KEY_CURRENTUSER_USERNAME, null);
}
public void removeCurrentUserInfo() {
editor.remove(SHARED_KEY_CURRENTUSER_NICK);
editor.remove(SHARED_KEY_CURRENTUSER_AVATAR);
editor.commit();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/manager/SettingsManager.java
================================================
package com.htmessage.yichatopen.manager;
import android.content.Context;
import java.util.HashMap;
import java.util.Map;
public class SettingsManager {
protected Context context = null;
protected Map valueCache = new HashMap();
private static SettingsManager settingManager;
public SettingsManager(Context ctx){
context = ctx;
PreferenceManager.init(context);
}
public synchronized static void init(Context context){
if(settingManager==null){
settingManager=new SettingsManager(context);
}
}
public static SettingsManager getInstance(){
if(settingManager==null){
throw new RuntimeException("settingManager please init first");
}
return settingManager;
}
public void setSettingMsgNotification(boolean paramBoolean) {
PreferenceManager.getInstance().setSettingMsgNotification(paramBoolean);
valueCache.put(Key.VibrateAndPlayToneOn, paramBoolean);
}
public boolean getSettingMsgNotification() {
Object val = valueCache.get(Key.VibrateAndPlayToneOn);
if(val == null){
val = PreferenceManager.getInstance().getSettingMsgNotification();
valueCache.put(Key.VibrateAndPlayToneOn, val);
}
return (Boolean) (val != null?val:true);
}
public void setSettingMsgSound(boolean paramBoolean) {
PreferenceManager.getInstance().setSettingMsgSound(paramBoolean);
valueCache.put(Key.PlayToneOn, paramBoolean);
}
public boolean getSettingMsgSound() {
Object val = valueCache.get(Key.PlayToneOn);
if(val == null){
val = PreferenceManager.getInstance().getSettingMsgSound();
valueCache.put(Key.PlayToneOn, val);
}
return (Boolean) (val != null?val:true);
}
public void setSettingMsgVibrate(boolean paramBoolean) {
PreferenceManager.getInstance().setSettingMsgVibrate(paramBoolean);
valueCache.put(Key.VibrateOn, paramBoolean);
}
public boolean getSettingMsgVibrate() {
Object val = valueCache.get(Key.VibrateOn);
if(val == null){
val = PreferenceManager.getInstance().getSettingMsgVibrate();
valueCache.put(Key.VibrateOn, val);
}
return (Boolean) (val != null?val:true);
}
public void setSettingMsgSpeaker(boolean paramBoolean) {
PreferenceManager.getInstance().setSettingMsgSpeaker(paramBoolean);
valueCache.put(Key.SpakerOn, paramBoolean);
}
public boolean getSettingMsgSpeaker() {
Object val = valueCache.get(Key.SpakerOn);
if(val == null){
val = PreferenceManager.getInstance().getSettingMsgSpeaker();
valueCache.put(Key.SpakerOn, val);
}
return (Boolean) (val != null?val:true);
}
public void allowChatroomOwnerLeave(boolean value){
PreferenceManager.getInstance().setSettingAllowChatroomOwnerLeave(value);
}
public boolean isChatroomOwnerLeaveAllowed(){
return PreferenceManager.getInstance().getSettingAllowChatroomOwnerLeave();
}
public void setDeleteMessagesAsExitGroup(boolean value) {
PreferenceManager.getInstance().setDeleteMessagesAsExitGroup(value);
}
public boolean isDeleteMessagesAsExitGroup() {
return PreferenceManager.getInstance().isDeleteMessagesAsExitGroup();
}
public void setAutoAcceptGroupInvitation(boolean value) {
PreferenceManager.getInstance().setAutoAcceptGroupInvitation(value);
}
public boolean isAutoAcceptGroupInvitation() {
return PreferenceManager.getInstance().isAutoAcceptGroupInvitation();
}
public void setAdaptiveVideoEncode(boolean value) {
PreferenceManager.getInstance().setAdaptiveVideoEncode(value);
}
public boolean isAdaptiveVideoEncode() {
return PreferenceManager.getInstance().isAdaptiveVideoEncode();
}
enum Key{
VibrateAndPlayToneOn,
VibrateOn,
PlayToneOn,
SpakerOn,
DisabledGroups,
DisabledIds
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/runtimepermissions/Permissions.java
================================================
/**
* Copyright 2015 Anthony Restaino
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied. See the License for the specific language governing
permissions and limitations under the License.
*/
package com.htmessage.yichatopen.runtimepermissions;
/**
* Enum class to handle the different states
* of permissions since the PackageManager only
* has a granted and denied state.
*/
enum Permissions {
GRANTED,
DENIED,
NOT_FOUND
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/runtimepermissions/PermissionsManager.java
================================================
/**
* Copyright 2015 Anthony Restaino
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied. See the License for the specific language governing
permissions and limitations under the License.
*/
package com.htmessage.yichatopen.runtimepermissions;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* A class to help you manage your permissions simply.
*/
public class PermissionsManager {
private static final String TAG = PermissionsManager.class.getSimpleName();
private final Set mPendingRequests = new HashSet(1);
private final Set mPermissions = new HashSet(1);
private final List> mPendingActions = new ArrayList>(1);
private static PermissionsManager mInstance = null;
public static PermissionsManager getInstance() {
if (mInstance == null) {
mInstance = new PermissionsManager();
}
return mInstance;
}
private PermissionsManager() {
initializePermissionsMap();
}
/**
* This method uses reflection to read all the permissions in the Manifest class.
* This is necessary because some permissions do not exist on older versions of Android,
* since they do not exist, they will be denied when you check whether you have permission
* which is problematic since a new permission is often added where there was no previous
* permission required. We initialize a Set of available permissions and check the set
* when checking if we have permission since we want to know when we are denied a permission
* because it doesn't exist yet.
*/
private synchronized void initializePermissionsMap() {
Field[] fields = Manifest.permission.class.getFields();
for (Field field : fields) {
String name = null;
try {
name = (String) field.get("");
} catch (IllegalAccessException e) {
Log.e(TAG, "Could not access field", e);
}
mPermissions.add(name);
}
}
/**
* This method retrieves all the permissions declared in the application's manifest.
* It returns a non null array of permisions that can be declared.
*
* @param activity the Activity necessary to check what permissions we have.
* @return a non null array of permissions that are declared in the application manifest.
*/
@NonNull
private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {
PackageInfo packageInfo = null;
List list = new ArrayList(1);
try {
Log.d(TAG, activity.getPackageName());
packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "A problem occurred when retrieving permissions", e);
}
if (packageInfo != null) {
String[] permissions = packageInfo.requestedPermissions;
if (permissions != null) {
for (String perm : permissions) {
Log.d(TAG, "Manifest contained permission: " + perm);
list.add(perm);
}
}
}
return list.toArray(new String[list.size()]);
}
/**
* This method adds the {@link PermissionsResultAction} to the current list
* of pending actions that will be completed when the permissions are
* received. The list of permissions passed to this method are registered
* in the PermissionsResultAction object so that it will be notified of changes
* made to these permissions.
*
* @param permissions the required permissions for the action to be executed.
* @param action the action to add to the current list of pending actions.
*/
private synchronized void addPendingAction(@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
if (action == null) {
return;
}
action.registerPermissions(permissions);
mPendingActions.add(new WeakReference(action));
}
/**
* This method removes a pending action from the list of pending actions.
* It is used for cases where the permission has already been granted, so
* you immediately wish to remove the pending action from the queue and
* execute the action.
*
* @param action the action to remove
*/
private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {
for (Iterator> iterator = mPendingActions.iterator();
iterator.hasNext(); ) {
WeakReference weakRef = iterator.next();
if (weakRef.get() == action || weakRef.get() == null) {
iterator.remove();
}
}
}
/**
* This static method can be used to check whether or not you have a specific permission.
* It is basically a less verbose method of using {@link ActivityCompat#checkSelfPermission(Context, String)}
* and will simply return a boolean whether or not you have the permission. If you pass
* in a null Context object, it will return false as otherwise it cannot check the permission.
* However, the Activity parameter is nullable so that you can pass in a reference that you
* are not always sure will be valid or not (e.g. getActivity() from Fragment).
*
* @param context the Context necessary to check the permission
* @param permission the permission to check
* @return true if you have been granted the permission, false otherwise
*/
@SuppressWarnings("unused")
public synchronized boolean hasPermission(@Nullable Context context, @NonNull String permission) {
return context != null && (ActivityCompat.checkSelfPermission(context, permission)
== PackageManager.PERMISSION_GRANTED || !mPermissions.contains(permission));
}
/**
* This static method can be used to check whether or not you have several specific permissions.
* It is simpler than checking using {@link ActivityCompat#checkSelfPermission(Context, String)}
* for each permission and will simply return a boolean whether or not you have all the permissions.
* If you pass in a null Context object, it will return false as otherwise it cannot check the
* permission. However, the Activity parameter is nullable so that you can pass in a reference
* that you are not always sure will be valid or not (e.g. getActivity() from Fragment).
*
* @param context the Context necessary to check the permission
* @param permissions the permissions to check
* @return true if you have been granted all the permissions, false otherwise
*/
@SuppressWarnings("unused")
public synchronized boolean hasAllPermissions(@Nullable Context context, @NonNull String[] permissions) {
if (context == null) {
return false;
}
boolean hasAllPermissions = true;
for (String perm : permissions) {
hasAllPermissions &= hasPermission(context, perm);
}
return hasAllPermissions;
}
/**
* This method will request all the permissions declared in your application manifest
* for the specified {@link PermissionsResultAction}. The purpose of this method is to enable
* all permissions to be requested at one shot. The PermissionsResultAction is used to notify
* you of the user allowing or denying each permission. The Activity and PermissionsResultAction
* parameters are both annotated Nullable, but this method will not work if the Activity
* is null. It is only annotated Nullable as a courtesy to prevent crashes in the case
* that you call this from a Fragment where {@link Fragment#getActivity()} could yield
* null. Additionally, you will not receive any notification of permissions being granted
* if you provide a null PermissionsResultAction.
*
* @param activity the Activity necessary to request and check permissions.
* @param action the PermissionsResultAction used to notify you of permissions being accepted.
*/
@SuppressWarnings("unused")
public synchronized void requestAllManifestPermissionsIfNecessary(final @Nullable Activity activity,
final @Nullable PermissionsResultAction action) {
if (activity == null) {
return;
}
String[] perms = getManifestPermissions(activity);
requestPermissionsIfNecessaryForResult(activity, perms, action);
}
/**
* This method should be used to execute a {@link PermissionsResultAction} for the array
* of permissions passed to this method. This method will request the permissions if
* they need to be requested (i.e. we don't have permission yet) and will add the
* PermissionsResultAction to the queue to be notified of permissions being granted or
* denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
* The Activity variable is nullable, but if it is null, the method will fail to execute.
* This is only nullable as a courtesy for Fragments where getActivity() may yeild null
* if the Fragment is not currently added to its parent Activity.
*
* @param activity the activity necessary to request the permissions.
* @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
* @param action the PermissionsResultAction to notify when the permissions are granted or denied.
*/
@SuppressWarnings("unused")
public synchronized void requestPermissionsIfNecessaryForResult(@Nullable Activity activity,
@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
if (activity == null) {
return;
}
addPendingAction(permissions, action);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
doPermissionWorkBeforeAndroidM(activity, permissions, action);
} else {
List permList = getPermissionsListToRequest(activity, permissions, action);
if (permList.isEmpty()) {
//if there is no permission to request, there is no reason to keep the action int the list
removePendingAction(action);
} else {
String[] permsToRequest = permList.toArray(new String[permList.size()]);
mPendingRequests.addAll(permList);
ActivityCompat.requestPermissions(activity, permsToRequest, 1);
}
}
}
/**
* This method should be used to execute a {@link PermissionsResultAction} for the array
* of permissions passed to this method. This method will request the permissions if
* they need to be requested (i.e. we don't have permission yet) and will add the
* PermissionsResultAction to the queue to be notified of permissions being granted or
* denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
* The Fragment variable is used, but if {@link Fragment#getActivity()} returns null, this method
* will fail to work as the activity reference is necessary to check for permissions.
*
* @param fragment the fragment necessary to request the permissions.
* @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
* @param action the PermissionsResultAction to notify when the permissions are granted or denied.
*/
@SuppressWarnings("unused")
public synchronized void requestPermissionsIfNecessaryForResult(@NonNull Fragment fragment,
@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
Activity activity = fragment.getActivity();
if (activity == null) {
return;
}
addPendingAction(permissions, action);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
doPermissionWorkBeforeAndroidM(activity, permissions, action);
} else {
List permList = getPermissionsListToRequest(activity, permissions, action);
if (permList.isEmpty()) {
//if there is no permission to request, there is no reason to keep the action int the list
removePendingAction(action);
} else {
String[] permsToRequest = permList.toArray(new String[permList.size()]);
mPendingRequests.addAll(permList);
fragment.requestPermissions(permsToRequest, 1);
}
}
}
/**
* This method notifies the PermissionsManager that the permissions have change. If you are making
* the permissions requests using an Activity, then this method should be called from the
* Activity callback onRequestPermissionsResult() with the variables passed to that method. If
* you are passing a Fragment to make the permissions request, then you should call this in
* the {@link Fragment#onRequestPermissionsResult(int, String[], int[])} method.
* It will notify all the pending PermissionsResultAction objects currently
* in the queue, and will remove the permissions request from the list of pending requests.
*
* @param permissions the permissions that have changed.
* @param results the values for each permission.
*/
@SuppressWarnings("unused")
public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {
int size = permissions.length;
if (results.length < size) {
size = results.length;
}
Iterator> iterator = mPendingActions.iterator();
while (iterator.hasNext()) {
PermissionsResultAction action = iterator.next().get();
for (int n = 0; n < size; n++) {
if (action == null || action.onResult(permissions[n], results[n])) {
iterator.remove();
break;
}
}
}
for (int n = 0; n < size; n++) {
mPendingRequests.remove(permissions[n]);
}
}
/**
* When request permissions on devices before Android M (Android 6.0, API Level 23)
* Do the granted or denied work directly according to the permission status
*
* @param activity the activity to check permissions
* @param permissions the permissions names
* @param action the callback work object, containing what we what to do after
* permission check
*/
private void doPermissionWorkBeforeAndroidM(@NonNull Activity activity,
@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
for (String perm : permissions) {
if (action != null) {
if (!mPermissions.contains(perm)) {
action.onResult(perm, Permissions.NOT_FOUND);
} else if (ActivityCompat.checkSelfPermission(activity, perm)
!= PackageManager.PERMISSION_GRANTED) {
action.onResult(perm, Permissions.DENIED);
} else {
action.onResult(perm, Permissions.GRANTED);
}
}
}
}
/**
* Filter the permissions list:
* If a permission is not granted, add it to the result list
* if a permission is granted, do the granted work, do not add it to the result list
*
* @param activity the activity to check permissions
* @param permissions all the permissions names
* @param action the callback work object, containing what we what to do after
* permission check
* @return a list of permissions names that are not granted yet
*/
@NonNull
private List getPermissionsListToRequest(@NonNull Activity activity,
@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
List permList = new ArrayList(permissions.length);
for (String perm : permissions) {
if (!mPermissions.contains(perm)) {
if (action != null) {
action.onResult(perm, Permissions.NOT_FOUND);
}
} else if (ActivityCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) {
if (!mPendingRequests.contains(perm)) {
permList.add(perm);
}
} else {
if (action != null) {
action.onResult(perm, Permissions.GRANTED);
}
}
}
return permList;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/runtimepermissions/PermissionsResultAction.java
================================================
/**
* Copyright 2015 Anthony Restaino
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied. See the License for the specific language governing
permissions and limitations under the License.
*/
package com.htmessage.yichatopen.runtimepermissions;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.util.Log;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* This abstract class should be used to create an if/else action that the PermissionsManager
* can execute when the permissions you request are granted or denied. Simple use involves
* creating an anonymous instance of it and passing that instance to the
* requestPermissionsIfNecessaryForResult method. The result will be sent back to you as
* either onGranted (all permissions have been granted), or onDenied (a required permission
* has been denied). Ideally you put your functionality in the onGranted method and notify
* the user what won't work in the onDenied method.
*/
public abstract class PermissionsResultAction {
private static final String TAG = PermissionsResultAction.class.getSimpleName();
private final Set mPermissions = new HashSet(1);
private Looper mLooper = Looper.getMainLooper();
/**
* Default Constructor
*/
public PermissionsResultAction() {}
/**
* Alternate Constructor. Pass the looper you wish the PermissionsResultAction
* callbacks to be executed on if it is not the current Looper. For instance,
* if you are making a permissions request from a background thread but wish the
* callback to be on the UI thread, use this constructor to specify the UI Looper.
*
* @param looper the looper that the callbacks will be called using.
*/
@SuppressWarnings("unused")
public PermissionsResultAction(@NonNull Looper looper) {mLooper = looper;}
/**
* This method is called when ALL permissions that have been
* requested have been granted by the user. In this method
* you should put all your permissions sensitive code that can
* only be executed with the required permissions.
*/
public abstract void onGranted();
/**
* This method is called when a permission has been denied by
* the user. It provides you with the permission that was denied
* and will be executed on the Looper you pass to the constructor
* of this class, or the Looper that this object was created on.
*
* @param permission the permission that was denied.
*/
public abstract void onDenied(String permission);
/**
* This method is used to determine if a permission not
* being present on the current Android platform should
* affect whether the PermissionsResultAction should continue
* listening for events. By default, it returns true and will
* simply ignore the permission that did not exist. Usually this will
* work fine since most new permissions are introduced to
* restrict what was previously allowed without permission.
* If that is not the case for your particular permission you
* request, override this method and return false to result in the
* Action being denied.
*
* @param permission the permission that doesn't exist on this
* Android version
* @return return true if the PermissionsResultAction should
* ignore the lack of the permission and proceed with exection
* or false if the PermissionsResultAction should treat the
* absence of the permission on the API level as a denial.
*/
@SuppressWarnings({"WeakerAccess", "SameReturnValue"})
public synchronized boolean shouldIgnorePermissionNotFound(String permission) {
Log.d(TAG, "Permission not found: " + permission);
return true;
}
@SuppressWarnings("WeakerAccess")
@CallSuper
protected synchronized final boolean onResult(final @NonNull String permission, int result) {
if (result == PackageManager.PERMISSION_GRANTED) {
return onResult(permission, Permissions.GRANTED);
} else {
return onResult(permission, Permissions.DENIED);
}
}
/**
* This method is called when a particular permission has changed.
* This method will be called for all permissions, so this method determines
* if the permission affects the state or not and whether it can proceed with
* calling onGranted or if onDenied should be called.
*
* @param permission the permission that changed.
* @param result the result for that permission.
* @return this method returns true if its primary action has been completed
* and it should be removed from the data structure holding a reference to it.
*/
@SuppressWarnings("WeakerAccess")
@CallSuper
protected synchronized final boolean onResult(final @NonNull String permission, Permissions result) {
mPermissions.remove(permission);
if (result == Permissions.GRANTED) {
if (mPermissions.isEmpty()) {
new Handler(mLooper).post(new Runnable() {
@Override
public void run() {
onGranted();
}
});
return true;
}
} else if (result == Permissions.DENIED) {
new Handler(mLooper).post(new Runnable() {
@Override
public void run() {
onDenied(permission);
}
});
return true;
} else if (result == Permissions.NOT_FOUND) {
if (shouldIgnorePermissionNotFound(permission)) {
if (mPermissions.isEmpty()) {
new Handler(mLooper).post(new Runnable() {
@Override
public void run() {
onGranted();
}
});
return true;
}
} else {
new Handler(mLooper).post(new Runnable() {
@Override
public void run() {
onDenied(permission);
}
});
return true;
}
}
return false;
}
/**
* This method registers the PermissionsResultAction object for the specified permissions
* so that it will know which permissions to look for changes to. The PermissionsResultAction
* will then know to look out for changes to these permissions.
*
* @param perms the permissions to listen for
*/
@SuppressWarnings("WeakerAccess")
@CallSuper
protected synchronized final void registerPermissions(@NonNull String[] perms) {
Collections.addAll(mPermissions, perms);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/ACache.java
================================================
package com.htmessage.yichatopen.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class ACache {
public static final int TIME_HOUR = 60 * 60;
public static final int TIME_DAY = TIME_HOUR * 24;
private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb
private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量
private static Map mInstanceMap = new HashMap();
private ACacheManager mCache;
public static ACache get(Context ctx) {
return get(ctx, "ACache");
}
public static ACache get(Context ctx, String cacheName) {
File f = new File(ctx.getCacheDir(), cacheName);
return get(f, MAX_SIZE, MAX_COUNT);
}
public static ACache get(File cacheDir) {
return get(cacheDir, MAX_SIZE, MAX_COUNT);
}
public static ACache get(Context ctx, long max_zise, int max_count) {
File f = new File(ctx.getCacheDir(), "ACache");
return get(f, max_zise, max_count);
}
public static ACache get(File cacheDir, long max_zise, int max_count) {
ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid());
if (manager == null) {
manager = new ACache(cacheDir, max_zise, max_count);
mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager);
}
return manager;
}
private static String myPid() {
return "_" + android.os.Process.myPid();
}
private ACache(File cacheDir, long max_size, int max_count) {
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath());
}
mCache = new ACacheManager(cacheDir, max_size, max_count);
}
class xFileOutputStream extends FileOutputStream {
File file;
public xFileOutputStream(File file) throws FileNotFoundException {
super(file);
this.file = file;
}
public void close() throws IOException {
super.close();
mCache.put(file);
}
}
// =======================================
// ============ String数据 读写 ==============
// =======================================
/**
* 保存 String数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的String数据
*/
public void put(String key, String value) {
File file = mCache.newFile(key);
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(file), 1024);
out.write(value);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
mCache.put(file);
}
}
/**
* 保存 String数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的String数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, String value, int saveTime) {
put(key, Utils.newStringWithDateInfo(saveTime, value));
}
/**
* 读取 String数据
*
* @param key
* @return String 数据
*/
public String getAsString(String key) {
File file = mCache.get(key);
if (!file.exists())
return null;
boolean removeFile = false;
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(file));
String readString = "";
String currentLine;
while ((currentLine = in.readLine()) != null) {
readString += currentLine;
}
if (!Utils.isDue(readString)) {
return Utils.clearDateInfo(readString);
} else {
removeFile = true;
return null;
}
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (removeFile)
remove(key);
}
}
// =======================================
// ============= JSONObject 数据 读写 ==============
// =======================================
/**
* 保存 JSONObject数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的JSON数据
*/
public void put(String key, JSONObject value) {
put(key, value.toJSONString());
}
/**
* 保存 JSONObject数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的JSONObject数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, JSONObject value, int saveTime) {
put(key, value.toString(), saveTime);
}
/**
* 读取JSONObject数据
*
* @param key
* @return JSONObject数据
*/
public JSONObject getAsJSONObject(String key) {
String JSONString = getAsString(key);
try {
JSONObject obj = JSONObject.parseObject(JSONString);
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// =======================================
// ============ JSONArray 数据 读写 =============
// =======================================
/**
* 保存 JSONArray数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的JSONArray数据
*/
public void put(String key, JSONArray value) {
put(key, value.toJSONString());
}
/**
* 保存 JSONArray数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的JSONArray数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, JSONArray value, int saveTime) {
put(key, value.toJSONString(), saveTime);
}
/**
* 读取JSONArray数据
*
* @param key
* @return JSONArray数据
*/
public JSONArray getAsJSONArray(String key) {
String JSONString = getAsString(key);
try {
JSONArray obj = JSONArray.parseArray(JSONString);
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// =======================================
// ============== byte 数据 读写 =============
// =======================================
/**
* 保存 byte数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的数据
*/
public void put(String key, byte[] value) {
File file = mCache.newFile(key);
FileOutputStream out = null;
try {
out = new FileOutputStream(file);
out.write(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
mCache.put(file);
}
}
/**
* Cache for a stream
*
* @param key the file name.
* @return OutputStream stream for writing data.
* @throws FileNotFoundException if the file can not be created.
*/
public OutputStream put(String key) throws FileNotFoundException {
return new xFileOutputStream(mCache.newFile(key));
}
/**
* @param key the file name.
* @return (InputStream or null) stream previously saved in cache.
* @throws FileNotFoundException if the file can not be opened
*/
public InputStream get(String key) throws FileNotFoundException {
File file = mCache.get(key);
if (!file.exists())
return null;
return new FileInputStream(file);
}
/**
* 保存 byte数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, byte[] value, int saveTime) {
put(key, Utils.newByteArrayWithDateInfo(saveTime, value));
}
/**
* 获取 byte 数据
*
* @param key
* @return byte 数据
*/
public byte[] getAsBinary(String key) {
RandomAccessFile RAFile = null;
boolean removeFile = false;
try {
File file = mCache.get(key);
if (!file.exists())
return null;
RAFile = new RandomAccessFile(file, "r");
byte[] byteArray = new byte[(int) RAFile.length()];
RAFile.read(byteArray);
if (!Utils.isDue(byteArray)) {
return Utils.clearDateInfo(byteArray);
} else {
removeFile = true;
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (RAFile != null) {
try {
RAFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (removeFile)
remove(key);
}
}
// =======================================
// ============= 序列化 数据 读写 ===============
// =======================================
/**
* 保存 Serializable数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的value
*/
public void put(String key, Serializable value) {
put(key, value, -1);
}
/**
* 保存 Serializable数据到 缓存中
*
* @param key 保存的key
* @param value 保存的value
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, Serializable value, int saveTime) {
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(value);
byte[] data = baos.toByteArray();
if (saveTime != -1) {
put(key, data, saveTime);
} else {
put(key, data);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
oos.close();
} catch (IOException e) {
}
}
}
/**
* 保存 Serializable数据到 缓存中
*
* @param key 保存的key
* @param value 保存的value
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, Object value) {
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(value);
byte[] data = baos.toByteArray();
put(key, data);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
oos.close();
} catch (IOException e) {
}
}
}
/**
* 读取 Serializable数据
*
* @param key
* @return Serializable 数据
*/
public Object getAsObject(String key) {
byte[] data = getAsBinary(key);
if (data != null) {
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
bais = new ByteArrayInputStream(data);
ois = new ObjectInputStream(bais);
Object reObject = ois.readObject();
return reObject;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (bais != null)
bais.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (ois != null)
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
// =======================================
// ============== bitmap 数据 读写 =============
// =======================================
/**
* 保存 bitmap 到 缓存中
*
* @param key 保存的key
* @param value 保存的bitmap数据
*/
public void put(String key, Bitmap value) {
put(key, Utils.Bitmap2Bytes(value));
}
/**
* 保存 bitmap 到 缓存中
*
* @param key 保存的key
* @param value 保存的 bitmap 数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, Bitmap value, int saveTime) {
put(key, Utils.Bitmap2Bytes(value), saveTime);
}
/**
* 读取 bitmap 数据
*
* @param key
* @return bitmap 数据
*/
public Bitmap getAsBitmap(String key) {
if (getAsBinary(key) == null) {
return null;
}
return Utils.Bytes2Bimap(getAsBinary(key));
}
// =======================================
// ============= drawable 数据 读写 =============
// =======================================
/**
* 保存 drawable 到 缓存中
*
* @param key 保存的key
* @param value 保存的drawable数据
*/
public void put(String key, Drawable value) {
put(key, Utils.drawable2Bitmap(value));
}
/**
* 保存 drawable 到 缓存中
*
* @param key 保存的key
* @param value 保存的 drawable 数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, Drawable value, int saveTime) {
put(key, Utils.drawable2Bitmap(value), saveTime);
}
/**
* 读取 Drawable 数据
*
* @param key
* @return Drawable 数据
*/
public Drawable getAsDrawable(String key) {
if (getAsBinary(key) == null) {
return null;
}
return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key)));
}
/**
* 获取缓存文件
*
* @param key
* @return value 缓存的文件
*/
public File file(String key) {
File f = mCache.newFile(key);
if (f.exists())
return f;
return null;
}
/**
* 移除某个key
*
* @param key
* @return 是否移除成功
*/
public boolean remove(String key) {
return mCache.remove(key);
}
/**
* 清除所有数据
*/
public void clear() {
mCache.clear();
}
/**
* @author 杨福海(michael) www.yangfuhai.com
* @version 1.0
* @title 缓存管理器
*/
public class ACacheManager {
private final AtomicLong cacheSize;
private final AtomicInteger cacheCount;
private final long sizeLimit;
private final int countLimit;
private final Map lastUsageDates = Collections.synchronizedMap(new HashMap());
protected File cacheDir;
private ACacheManager(File cacheDir, long sizeLimit, int countLimit) {
this.cacheDir = cacheDir;
this.sizeLimit = sizeLimit;
this.countLimit = countLimit;
cacheSize = new AtomicLong();
cacheCount = new AtomicInteger();
calculateCacheSizeAndCacheCount();
}
/**
* 计算 cacheSize和cacheCount
*/
private void calculateCacheSizeAndCacheCount() {
new Thread(new Runnable() {
@Override
public void run() {
int size = 0;
int count = 0;
File[] cachedFiles = cacheDir.listFiles();
if (cachedFiles != null) {
for (File cachedFile : cachedFiles) {
size += calculateSize(cachedFile);
count += 1;
lastUsageDates.put(cachedFile, cachedFile.lastModified());
}
cacheSize.set(size);
cacheCount.set(count);
}
}
}).start();
}
private void put(File file) {
int curCacheCount = cacheCount.get();
while (curCacheCount + 1 > countLimit) {
long freedSize = removeNext();
cacheSize.addAndGet(-freedSize);
curCacheCount = cacheCount.addAndGet(-1);
}
cacheCount.addAndGet(1);
long valueSize = calculateSize(file);
long curCacheSize = cacheSize.get();
while (curCacheSize + valueSize > sizeLimit) {
long freedSize = removeNext();
curCacheSize = cacheSize.addAndGet(-freedSize);
}
cacheSize.addAndGet(valueSize);
Long currentTime = System.currentTimeMillis();
file.setLastModified(currentTime);
lastUsageDates.put(file, currentTime);
}
private File get(String key) {
File file = newFile(key);
Long currentTime = System.currentTimeMillis();
file.setLastModified(currentTime);
lastUsageDates.put(file, currentTime);
return file;
}
private File newFile(String key) {
return new File(cacheDir, key.hashCode() + "");
}
private boolean remove(String key) {
File image = get(key);
return image.delete();
}
private void clear() {
lastUsageDates.clear();
cacheSize.set(0);
File[] files = cacheDir.listFiles();
if (files != null) {
for (File f : files) {
f.delete();
}
}
}
/**
* 移除旧的文件
*
* @return
*/
private long removeNext() {
if (lastUsageDates.isEmpty()) {
return 0;
}
Long oldestUsage = null;
File mostLongUsedFile = null;
Set> entries = lastUsageDates.entrySet();
synchronized (lastUsageDates) {
for (Entry entry : entries) {
if (mostLongUsedFile == null) {
mostLongUsedFile = entry.getKey();
oldestUsage = entry.getValue();
} else {
Long lastValueUsage = entry.getValue();
if (lastValueUsage < oldestUsage) {
oldestUsage = lastValueUsage;
mostLongUsedFile = entry.getKey();
}
}
}
}
long fileSize = calculateSize(mostLongUsedFile);
if (mostLongUsedFile.delete()) {
lastUsageDates.remove(mostLongUsedFile);
}
return fileSize;
}
private long calculateSize(File file) {
return file.length();
}
}
/**
* @author 杨福海(michael) www.yangfuhai.com
* @version 1.0
* @title 时间计算工具类
*/
private static class Utils {
/**
* 判断缓存的String数据是否到期
*
* @param str
* @return true:到期了 false:还没有到期
*/
private static boolean isDue(String str) {
return isDue(str.getBytes());
}
/**
* 判断缓存的byte数据是否到期
*
* @param data
* @return true:到期了 false:还没有到期
*/
private static boolean isDue(byte[] data) {
String[] strs = getDateInfoFromDate(data);
if (strs != null && strs.length == 2) {
String saveTimeStr = strs[0];
while (saveTimeStr.startsWith("0")) {
saveTimeStr = saveTimeStr.substring(1, saveTimeStr.length());
}
long saveTime = Long.valueOf(saveTimeStr);
long deleteAfter = Long.valueOf(strs[1]);
if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) {
return true;
}
}
return false;
}
private static String newStringWithDateInfo(int second, String strInfo) {
return createDateInfo(second) + strInfo;
}
private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) {
byte[] data1 = createDateInfo(second).getBytes();
byte[] retdata = new byte[data1.length + data2.length];
System.arraycopy(data1, 0, retdata, 0, data1.length);
System.arraycopy(data2, 0, retdata, data1.length, data2.length);
return retdata;
}
private static String clearDateInfo(String strInfo) {
if (strInfo != null && hasDateInfo(strInfo.getBytes())) {
strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, strInfo.length());
}
return strInfo;
}
private static byte[] clearDateInfo(byte[] data) {
if (hasDateInfo(data)) {
return copyOfRange(data, indexOf(data, mSeparator) + 1, data.length);
}
return data;
}
private static boolean hasDateInfo(byte[] data) {
return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14;
}
private static String[] getDateInfoFromDate(byte[] data) {
if (hasDateInfo(data)) {
String saveDate = new String(copyOfRange(data, 0, 13));
String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator)));
return new String[]{saveDate, deleteAfter};
}
return null;
}
private static int indexOf(byte[] data, char c) {
for (int i = 0; i < data.length; i++) {
if (data[i] == c) {
return i;
}
}
return -1;
}
private static byte[] copyOfRange(byte[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
byte[] copy = new byte[newLength];
System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
return copy;
}
private static final char mSeparator = ' ';
private static String createDateInfo(int second) {
String currentTime = System.currentTimeMillis() + "";
while (currentTime.length() < 13) {
currentTime = "0" + currentTime;
}
return currentTime + "-" + second + mSeparator;
}
/*
* Bitmap → byte[]
*/
private static byte[] Bitmap2Bytes(Bitmap bm) {
if (bm == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
/*
* byte[] → Bitmap
*/
private static Bitmap Bytes2Bimap(byte[] b) {
if (b.length == 0) {
return null;
}
return BitmapFactory.decodeByteArray(b, 0, b.length);
}
/*
* Drawable → Bitmap
*/
private static Bitmap drawable2Bitmap(Drawable drawable) {
if (drawable == null) {
return null;
}
// 取 drawable 的长宽
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
// 取 drawable 的颜色格式
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
// 建立对应 bitmap
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
// 建立对应 bitmap 的画布
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
// 把 drawable 内容画到画布中
drawable.draw(canvas);
return bitmap;
}
/*
* Bitmap → Drawable
*/
@SuppressWarnings("deprecation")
private static Drawable bitmap2Drawable(Bitmap bm) {
if (bm == null) {
return null;
}
BitmapDrawable bd = new BitmapDrawable(bm);
bd.setTargetDensity(bm.getDensity());
return new BitmapDrawable(bm);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/CommonUtils.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.country.CountryCodeUtil;
import com.htmessage.yichatopen.activity.country.CountryComparator;
import com.htmessage.yichatopen.activity.country.CountrySortAdapter;
import com.htmessage.yichatopen.activity.country.CountrySortModel;
import com.htmessage.yichatopen.activity.country.GetCountryNameSort;
import com.htmessage.yichatopen.activity.country.SideBar;
import com.htmessage.yichatopen.HTConstant;
import com.htmessage.yichatopen.domain.User;
import com.github.promeg.pinyinhelper.Pinyin;
public class CommonUtils {
private static final String TAG = "CommonUtils";
public static User Json2User(JSONObject userJson) {
User user = new User(userJson.getString(HTConstant.JSON_KEY_HXID));
user.setNick(userJson.getString(HTConstant.JSON_KEY_NICK));
user.setAvatar(userJson.getString(HTConstant.JSON_KEY_AVATAR));
user.setUserInfo(userJson.toJSONString());
CommonUtils.setUserInitialLetter(user);
return user;
}
public static boolean isNetWorkConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo != null) {
return mNetworkInfo.isAvailable() && mNetworkInfo.isConnected();
}
}
return false;
}
/**
* check if sdcard exist
*
* @return
*/
public static boolean isSdcardExist() {
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
return true;
else
return false;
}
static String getString(Context context, int resId){
return context.getResources().getString(resId);
}
/**
* get top activity
* @param context
* @return
*/
public static String getTopActivity(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List runningTaskInfos = manager.getRunningTasks(1);
if (runningTaskInfos != null)
return runningTaskInfos.get(0).topActivity.getClassName();
else
return "";
}
/**
* set initial letter of according user's nickname( username if no nickname)
*
* @param
* @param user
*/
public static void setUserInitialLetter(User user) {
final String DefaultLetter = "#";
String letter = DefaultLetter;
if ( !TextUtils.isEmpty(user.getNick()) ) {
letter = Pinyin.toPinyin(user.getNick().toCharArray()[0]);
user.setInitialLetter(letter.toUpperCase().substring(0,1));
if ("123456789".contains(user.getInitialLetter())) {
user.setInitialLetter("#");
}
return;
}
if (letter == DefaultLetter && !TextUtils.isEmpty(user.getUsername())) {
letter = Pinyin.toPinyin(user.getUsername().toCharArray()[0]);
}
user.setInitialLetter(letter.substring(0,1));
if ("123456789".contains(user.getInitialLetter())) {
user.setInitialLetter("#");
}
}
/**
* 获取国家代码
*
* @param context 上下文对象
* @param country 显示国家的textview
* @param countryCode 显示国家代码的textview
*/
public static void showPup(final Context context, final TextView country, final TextView countryCode) {
final boolean cn = context.getResources().getConfiguration().locale.getCountry().equals("CN");
final List countryList = CountryCodeUtil.getCountryList(context, cn);
//获得pup的view
View view = LayoutInflater.from(context).inflate(R.layout.layout_pup, null, false);
final ImageView iv_back = (ImageView) view.findViewById(R.id.iv_back);
final TextView tv_title = (TextView) view.findViewById(R.id.tv_title);
tv_title.setText(R.string.country);
final EditText country_et_search = (EditText) view.findViewById(R.id.country_et_search);
final ImageView country_iv_cleartext = (ImageView) view.findViewById(R.id.country_iv_cleartext);
final ListView ll_country = (ListView) view.findViewById(R.id.country_lv_list);
final TextView country_dialog = (TextView) view.findViewById(R.id.country_dialog);
final SideBar country_sidebar = (SideBar) view.findViewById(R.id.country_sidebar);
country_sidebar.setTextView(country_dialog);
final CountrySortAdapter adapter = new CountrySortAdapter(context, countryList);
ll_country.setAdapter(adapter);
DisplayMetrics dm = new DisplayMetrics();
//取得窗口属性
((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(dm);
//窗口的宽度
int screenWidth = dm.widthPixels;
//窗口高度
int screenHeight = dm.heightPixels / 2;
//设置window的宽高 1 window的布局 2、window的宽 3、window的高 4、window是否获取焦点
// final PopupWindow window = new PopupWindow(view, WindowManager.LayoutParams.MATCH_PARENT, screenHeight, true);
final PopupWindow window = new PopupWindow(view, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true);
//设置window背景色
window.setBackgroundDrawable(new ColorDrawable(0x00000000));
//设置可以获取焦点,否则弹出菜单中的EditText是无法获取输入的
window.setFocusable(true);
//设置键盘不遮盖
window.setSoftInputMode(PopupWindow.INPUT_METHOD_NEEDED);
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
//设置window动画
// window.setAnimationStyle(R.style.custom_pup_style);
//设置window在底部显示
window.showAtLocation(view, Gravity.BOTTOM, 0, 0);
country_iv_cleartext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
country_et_search.setText("");
Collections.sort(countryList, new CountryComparator());
adapter.updateListView(countryList);
}
});
country_et_search.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
String searchContent = country_et_search.getText().toString();
if (searchContent.equals("")) {
country_iv_cleartext.setVisibility(View.INVISIBLE);
} else {
country_iv_cleartext.setVisibility(View.VISIBLE);
}
if (searchContent.length() > 0) {
// 按照输入内容进行匹配
ArrayList fileterList = (ArrayList) new GetCountryNameSort()
.search(searchContent, countryList);
adapter.updateListView(fileterList);
} else {
adapter.updateListView(countryList);
}
ll_country.setSelection(0);
}
});
// 右侧sideBar监听
country_sidebar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {
@Override
public void onTouchingLetterChanged(String s) {
// 该字母首次出现的位置
int position = adapter.getPositionForSection(s.charAt(0));
if (position != -1) {
ll_country.setSelection(position);
}
}
});
ll_country.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
window.dismiss();
String countryName = null;
String countryNumber = null;
String searchContent = country_et_search.getText().toString();
if (searchContent.length() > 0) {
// 按照输入内容进行匹配
ArrayList fileterList = (ArrayList) new GetCountryNameSort()
.search(searchContent, countryList);
//获取国家名字及代码
countryName = fileterList.get(i).countryName;
countryNumber = fileterList.get(i).countryNumber;
} else {
//获取国家名字及代码
countryName = countryList.get(i).countryName;
countryNumber = countryList.get(i).countryNumber;
}
country.setText(countryName);
countryCode.setText(countryNumber);
Log.e(TAG, "countryName: + " + countryName + "countryNumber: " + countryNumber);
}
});
iv_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
window.dismiss();
}
});
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/DateUtils.java
================================================
package com.htmessage.yichatopen.utils;
import android.content.Context;
import android.util.Log;
import com.htmessage.yichatopen.R;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
/**
* Created by huangfangyi on 2016/12/24.
* qq 84543217
*/
public class DateUtils {
private static final long INTERVAL_IN_MILLISECONDS = 30000L;
public DateUtils() {
}
/**
* 计算时间差
*
* @param starTime
* 开始时间
* @param endTime
* 结束时间
* @param type
* 返回类型 ==1----天,时,分。 ==2----时
* @return 返回时间差
*/
public static String getTimeDifference(Context context, long starTime, long endTime) {
String timeString = "";
try {
Date parse = new Date(starTime);
Date parse1 = new Date(endTime);
long diff = parse1.getTime() - parse.getTime();
long day = diff / (24 * 60 * 60 * 1000);
long hour = (diff / (60 * 60 * 1000) - day * 24);
long min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
long s = (diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
long ms = (diff - day * 24 * 60 * 60 * 1000 - hour * 60 * 60 * 1000
- min * 60 * 1000 - s * 1000);
long hour1 = diff / (60 * 60 * 1000);
long min1 = ((diff / (60 * 1000)) - hour1 * 60);
if (day == 0){
if (hour1 == 0){
if (0<=min1 && min1<=5){
timeString = context.getString(R.string.just);
}else if (min1>5 && min1<=15){
timeString = context.getString(R.string.just_15);
}else if (min1>15 && min1<=30){
timeString = context.getString(R.string.just_30);
}else{
timeString = context.getString(R.string.just_1hour);
}
}else{
timeString = hour1+context.getString(R.string.An_hour_ago);
}
}else{
timeString = day+context.getString(R.string.Days_ago);
}
// timeString = hour1 + "小时" + min1 + "分";
Log.d("slj",day + "天" + hour + "小时" + min + "分" + s + "秒");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return timeString;
}
public static String getTimestampString(Date var0) {
String var1 = null;
String var2 = Locale.getDefault().getLanguage();
boolean var3 = var2.startsWith("zh");
long var4 = var0.getTime();
if(isSameDay(var4)) {
if(var3) {
var1 = "aa hh:mm";
} else {
var1 = "hh:mm aa";
}
} else if(isYesterday(var4)) {
if(!var3) {
return "Yesterday " + (new SimpleDateFormat("hh:mm aa", Locale.ENGLISH)).format(var0);
}
var1 = "昨天aa hh:mm";
} else if(var3) {
var1 = "M月d日aa hh:mm";
} else {
var1 = "MMM dd hh:mm aa";
}
return var3?(new SimpleDateFormat(var1, Locale.CHINESE)).format(var0):(new SimpleDateFormat(var1, Locale.ENGLISH)).format(var0);
}
public static boolean isCloseEnough(long var0, long var2) {
long var4 = var0 - var2;
if(var4 < 0L) {
var4 = -var4;
}
return var4 < 30000L;
}
private static boolean isSameDay(long var0) {
TimeInfo var2 = getTodayStartAndEndTime();
return var0 > var2.getStartTime() && var0 < var2.getEndTime();
}
private static boolean isYesterday(long var0) {
TimeInfo var2 = getYesterdayStartAndEndTime();
return var0 > var2.getStartTime() && var0 < var2.getEndTime();
}
public static Date StringToDate(String var0, String var1) {
SimpleDateFormat var2 = new SimpleDateFormat(var1);
Date var3 = null;
try {
var3 = var2.parse(var0);
} catch (ParseException var5) {
var5.printStackTrace();
}
return var3;
}
public static String toTime(int var0) {
var0 /= 1000;
int var1 = var0 / 60;
boolean var2 = false;
if(var1 >= 60) {
int var4 = var1 / 60;
var1 %= 60;
}
int var3 = var0 % 60;
return String.format("%02d:%02d", new Object[]{Integer.valueOf(var1), Integer.valueOf(var3)});
}
public static String toTimeBySecond(int var0) {
int var1 = var0 / 60;
boolean var2 = false;
if(var1 >= 60) {
int var4 = var1 / 60;
var1 %= 60;
}
int var3 = var0 % 60;
return String.format("%02d:%02d", new Object[]{Integer.valueOf(var1), Integer.valueOf(var3)});
}
public static TimeInfo getYesterdayStartAndEndTime() {
Calendar var0 = Calendar.getInstance();
var0.add(Calendar.DAY_OF_MONTH, -1);//5
var0.set(Calendar.HOUR_OF_DAY, 0);//11
var0.set(Calendar.MINUTE, 0);//12
var0.set(Calendar.SECOND, 0);//13
var0.set(Calendar.MILLISECOND, 0);//Calendar.MILLISECOND
Date var1 = var0.getTime();
long var2 = var1.getTime();
Calendar var4 = Calendar.getInstance();
var4.add(Calendar.DAY_OF_MONTH, -1);//5
var4.set(Calendar.HOUR_OF_DAY, 23);//11
var4.set(Calendar.MINUTE, 59);//12
var4.set(Calendar.SECOND, 59);//13
var4.set(Calendar.MILLISECOND, 999);//Calendar.MILLISECOND
Date var5 = var4.getTime();
long var6 = var5.getTime();
TimeInfo var8 = new TimeInfo();
var8.setStartTime(var2);
var8.setEndTime(var6);
return var8;
}
public static TimeInfo getTodayStartAndEndTime() {
Calendar var0 = Calendar.getInstance();
var0.set(Calendar.HOUR_OF_DAY, 0);
var0.set(Calendar.MINUTE, 0);
var0.set(Calendar.SECOND, 0);
var0.set(Calendar.MILLISECOND, 0);
Date var1 = var0.getTime();
long var2 = var1.getTime();
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss S");
Calendar var5 = Calendar.getInstance();
var5.set(Calendar.HOUR_OF_DAY, 23);
var5.set(Calendar.MINUTE, 59);
var5.set(Calendar.SECOND, 59);
var5.set(Calendar.MILLISECOND, 999);
Date var6 = var5.getTime();
long var7 = var6.getTime();
TimeInfo var9 = new TimeInfo();
var9.setStartTime(var2);
var9.setEndTime(var7);
return var9;
}
public static TimeInfo getBeforeYesterdayStartAndEndTime() {
Calendar var0 = Calendar.getInstance();
var0.add(Calendar.DAY_OF_MONTH, -2);
var0.set(Calendar.HOUR_OF_DAY, 0);
var0.set(Calendar.MINUTE, 0);
var0.set(Calendar.SECOND, 0);
var0.set(Calendar.MILLISECOND, 0);
Date var1 = var0.getTime();
long var2 = var1.getTime();
Calendar var4 = Calendar.getInstance();
var4.add(Calendar.DAY_OF_MONTH, -2);
var4.set(Calendar.HOUR_OF_DAY, 23);
var4.set(Calendar.MINUTE, 59);
var4.set(Calendar.SECOND, 59);
var4.set(Calendar.MILLISECOND, 999);
Date var5 = var4.getTime();
long var6 = var5.getTime();
TimeInfo var8 = new TimeInfo();
var8.setStartTime(var2);
var8.setEndTime(var6);
return var8;
}
public static TimeInfo getCurrentMonthStartAndEndTime() {
Calendar var0 = Calendar.getInstance();
var0.set(Calendar.DATE, 1);
var0.set(Calendar.HOUR_OF_DAY, 0);
var0.set(Calendar.MINUTE, 0);
var0.set(Calendar.SECOND, 0);
var0.set(Calendar.MILLISECOND, 0);
Date var1 = var0.getTime();
long var2 = var1.getTime();
Calendar var4 = Calendar.getInstance();
Date var5 = var4.getTime();
long var6 = var5.getTime();
TimeInfo var8 = new TimeInfo();
var8.setStartTime(var2);
var8.setEndTime(var6);
return var8;
}
public static TimeInfo getLastMonthStartAndEndTime() {
Calendar var0 = Calendar.getInstance();
var0.add(Calendar.MONTH, -1);
var0.set(Calendar.DATE, 1);
var0.set(Calendar.HOUR_OF_DAY, 0);
var0.set(Calendar.MINUTE, 0);
var0.set(Calendar.SECOND, 0);
var0.set(Calendar.MILLISECOND, 0);
Date var1 = var0.getTime();
long var2 = var1.getTime();
Calendar var4 = Calendar.getInstance();
var4.add(Calendar.MONTH, -1);
var4.set(Calendar.DATE, 1);
var4.set(Calendar.HOUR_OF_DAY, 23);
var4.set(Calendar.MINUTE, 59);
var4.set(Calendar.SECOND, 59);
var4.set(Calendar.MILLISECOND, 999);
var4.roll(Calendar.DATE, -1);
Date var5 = var4.getTime();
long var6 = var5.getTime();
TimeInfo var8 = new TimeInfo();
var8.setStartTime(var2);
var8.setEndTime(var6);
return var8;
}
public static String getStringTime(long time){
Date date = new Date(time);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String startTime = sdf.format(date);
return startTime;
}
public static String getTimestampStr() {
return Long.toString(System.currentTimeMillis());
}
public static class TimeInfo {
private long startTime;
private long endTime;
public TimeInfo() {
}
public long getStartTime() {
return this.startTime;
}
public void setStartTime(long var1) {
this.startTime = var1;
}
public long getEndTime() {
return this.endTime;
}
public void setEndTime(long var1) {
this.endTime = var1;
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/HTMessageUtils.java
================================================
package com.htmessage.yichatopen.utils;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.sdk.ChatType;
import com.htmessage.sdk.client.HTClient;
import com.htmessage.sdk.model.HTMessage;
import com.htmessage.sdk.model.HTMessageImageBody;
import com.htmessage.sdk.model.HTMessageTextBody;
import com.htmessage.sdk.model.HTMessageVoiceBody;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.HTClientHelper;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.activity.chat.activity.ChooseContactActivity;
import com.htmessage.yichatopen.HTConstant;
import java.io.File;
/**
* Created by huangfangyi on 2017/7/8.
* qq 84543217
*/
public class HTMessageUtils {
public static HTMessage creatWithDrowMsg(HTMessage htMessage) {
String text = null;
JSONObject jsonObject = htMessage.getAttributes();
String userId = jsonObject.getString(HTConstant.JSON_KEY_HXID);
String nick = jsonObject.getString(HTConstant.JSON_KEY_NICK);
if (HTApp.getInstance().getUsername().equals(userId)) {
text = HTApp.getContext().getString(R.string.revoke_content);
} else {
text = String.format(HTApp.getContext().getString(R.string.revoke_content_someone), nick);
}
jsonObject.put("action", 6001);
HTMessage message1 = HTMessage.createTextSendMessage(htMessage.getUsername(), text);
message1.setMsgId(htMessage.getMsgId());
message1.setChatType(htMessage.getChatType());
message1.setDirect(htMessage.getDirect());
message1.setAttributes(jsonObject.toJSONString());
message1.setTime(htMessage.getTime());
message1.setLocalTime(htMessage.getLocalTime());
message1.setFrom(htMessage.getFrom());
message1.setTo(htMessage.getTo());
message1.setStatus(htMessage.getStatus());
message1.setExt(htMessage.getExt());
HTClient.getInstance().messageManager().updateMessageInDB(message1);
return message1;
}
/**
* 获取copy的信息
*
* @param context
* @param message
*/
public static void getCopyMsg(Activity context, HTMessage message, String toChatUserName) {
String copyType = "";
String fileName = "";
String localUrl = "";
String remotePath = "";
HTMessage.Type type = message.getType();
if (type == HTMessage.Type.IMAGE) {
copyType = "image";
HTMessageImageBody body = (HTMessageImageBody) message.getBody();
fileName = body.getFileName();
remotePath = body.getRemotePath();
localUrl = body.getLocalPath();
} else if (type == HTMessage.Type.VOICE) {
HTMessageVoiceBody body = (HTMessageVoiceBody) message.getBody();
copyType = "voice";
remotePath = body.getRemotePath();
fileName = body.getFileName();
localUrl = body.getLocalPath();
} else if (type == HTMessage.Type.TEXT) {
copyType = "text";
localUrl = ((HTMessageTextBody) message.getBody()).getContent();
}
String msgId = message.getMsgId();
if (!TextUtils.isEmpty(localUrl)) {
switch (copyType) {
case "text":
showCopySendDialog(context, copyType, localUrl, message, null);
break;
default:
getFilePath(context, copyType, message, msgId, fileName, remotePath, toChatUserName, null);
break;
}
} else {
switch (copyType) {
case "text":
showCopySendDialog(context, copyType, localUrl, message, null);
break;
default:
getFilePath(context, copyType, message, msgId, fileName, remotePath, toChatUserName, null);
break;
}
}
}
/**
* 下载copy文件并复制
*
* @param context
* @param copyType
* @param message
* @param msgId
* @param fileName
* @param remotePath
*/
public static void getFilePath(final Activity context, final String copyType, final HTMessage message, String msgId, final String fileName, final String remotePath) {
String fileType = fileName.substring(fileName.lastIndexOf("."));
if (!TextUtils.isEmpty(msgId) && !TextUtils.isEmpty(fileType) && !TextUtils.isEmpty(remotePath)) {
// final File file = new File(HTApp.getInstance().getDirFilePath() + msgId + fileType);
final File file = new File(HTApp.getInstance().getDirFilePath() + fileName);
if (file.exists()) {
switch (copyType) {
case "image":
showCopySendDialog(context, copyType, file.getAbsolutePath(), message, file.getAbsolutePath());
break;
case "voice":
showCopySendDialog(context, copyType, file.getAbsolutePath(), message, null);
break;
}
return;
}
final ProgressDialog dialog = new ProgressDialog(context);
dialog.setMessage(context.getString(R.string.copying));
dialog.setCanceledOnTouchOutside(false);
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
final String path = HTApp.getInstance().getDirFilePath() + fileName;
dialog.show();
new OkHttpUtils(context).loadFile(remotePath, path, new OkHttpUtils.DownloadCallBack() {
@Override
public void onSuccess() {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
File file1 = new File(path);
switch (copyType) {
case "image":
showCopySendDialog(context, copyType, file1.getAbsolutePath(), message, file1.getAbsolutePath());
break;
case "voice":
showCopySendDialog(context, copyType, file1.getAbsolutePath(), message, null);
break;
}
((Activity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, R.string.copy_success, Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onFailure(String message) {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
((Activity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, R.string.copy_failed, Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
/**
* 复制并转发
*
* @param copyType
* @param localPath
* @param message1
*/
public static void showCopySendDialog(Activity context, final String copyType, String localPath, final HTMessage message1, String imagePath) {
if (message1.getType() == HTMessage.Type.TEXT) {
ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
// 将文本内容放到系统剪贴板里。
cm.setText(localPath);
ACache.get(context.getApplicationContext()).remove("myCopy");
} else {
JSONObject jsonObject = new JSONObject();
jsonObject.put("copyType", copyType);
jsonObject.put("localPath", localPath);
jsonObject.put("msgId", message1.getMsgId());
jsonObject.put("imagePath", imagePath);
ACache.get(context.getApplicationContext()).put("myCopy", jsonObject.toJSONString());
}
}
/**
* 获取copy的信息
*
* @param context
* @param message
*/
public static void getForWordMessage(Activity context, HTMessage message, final String toChatUsername, final JSONObject userJson) {
String copyType = "";
String fileName = "";
String localUrl = "";
String remotePath = "";
HTMessage.Type type = message.getType();
if (type == HTMessage.Type.IMAGE) {
copyType = "image";
HTMessageImageBody body = (HTMessageImageBody) message.getBody();
fileName = body.getFileName();
remotePath = body.getRemotePath();
localUrl = body.getLocalPath();
} else if (type == HTMessage.Type.VOICE) {
HTMessageVoiceBody body = (HTMessageVoiceBody) message.getBody();
copyType = "voice";
remotePath = body.getRemotePath();
fileName = body.getFileName();
localUrl = body.getLocalPath();
} else if (type == HTMessage.Type.TEXT) {
copyType = "text";
localUrl = ((HTMessageTextBody) message.getBody()).getContent();
}
String msgId = message.getMsgId();
if (!TextUtils.isEmpty(localUrl)) {
switch (copyType) {
case "text":
showForwordDialog(context, copyType, localUrl, message, null, toChatUsername, userJson);
break;
default:
getFilePath(context, copyType, message, msgId, fileName, remotePath, toChatUsername, userJson);
break;
}
} else {
switch (copyType) {
case "text":
showForwordDialog(context, copyType, localUrl, message, null, toChatUsername, userJson);
break;
default:
getFilePath(context, copyType, message, msgId, fileName, remotePath, toChatUsername, userJson);
break;
}
}
}
/**
* 下载copy文件并复制
*
* @param context
* @param copyType
* @param message
* @param msgId
* @param fileName
* @param remotePath
*/
public static void getFilePath(final Activity context, final String copyType, final HTMessage message, String msgId, final String fileName, final String remotePath, final String toChatUsername, final JSONObject userJson) {
String fileType = fileName.substring(fileName.lastIndexOf("."));
String filePath = null;
if (!TextUtils.isEmpty(msgId) && !TextUtils.isEmpty(fileType) && !TextUtils.isEmpty(remotePath)) {
PathUtils pathUtils = new PathUtils(toChatUsername, context);
if (message.getType() == HTMessage.Type.VOICE) {
filePath = pathUtils.getVoicePath().getAbsolutePath() + "/" + fileName;
} else if (message.getType() == HTMessage.Type.IMAGE) {
filePath = pathUtils.getImagePath().getAbsolutePath() + "/" + fileName;
}
File file = new File(filePath);
if (file.exists()) {
switch (copyType) {
case "image":
if (userJson != null) {
showForwordDialog(context, copyType, file.getAbsolutePath(), message, file.getAbsolutePath(), toChatUsername, userJson);
} else {
showCopySendDialog(context, copyType, file.getAbsolutePath(), message, file.getAbsolutePath());
}
break;
case "voice":
if (userJson != null) {
showForwordDialog(context, copyType, file.getAbsolutePath(), message, null, toChatUsername, userJson);
} else {
showCopySendDialog(context, copyType, file.getAbsolutePath(), message, null);
}
break;
}
return;
}
loadMessageFile(message, toChatUsername, context, new CallBack() {
@Override
public void error() {
if (userJson == null) {
Toast.makeText(context, R.string.copy_failed, Toast.LENGTH_SHORT).show();
}
}
@Override
public void completed(String localPath) {
switch (copyType) {
case "image":
if (userJson != null) {
showForwordDialog(context, copyType, localPath, message, localPath, toChatUsername, userJson);
} else {
showCopySendDialog(context, copyType,localPath, message, localPath);
}
break;
case "voice":
if (userJson != null) {
showForwordDialog(context, copyType, localPath, message, null, toChatUsername, userJson);
} else {
Log.d("slj","===复制:"+userJson);
showCopySendDialog(context, copyType, localPath, message, null);
}
break;
}
if (userJson == null) {
Toast.makeText(context, R.string.copy_success, Toast.LENGTH_SHORT).show();
}
}
});
}
// if (!TextUtils.isEmpty(msgId) && !TextUtils.isEmpty(fileType) && !TextUtils.isEmpty(remotePath)) {
// final File file = new File(HTApp.getInstance().getDirFilePath() + fileName);
// if (file.exists()) {
// switch (copyType) {
// case "image":
// showForwordDialog(context, copyType, file.getAbsolutePath(), message, file.getAbsolutePath(),toChatUsername,userJson);
// break;
// case "voice":
// showForwordDialog(context, copyType, file.getAbsolutePath(), message, null,toChatUsername,userJson);
// break;
// }
// return;
// }
// final ProgressDialog dialog = new ProgressDialog(context);
// dialog.setMessage(context.getString(R.string.forword_get));
// dialog.setCanceledOnTouchOutside(false);
// dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
//// final String path = HTApp.getInstance().getDirFilePath() + msgId + fileType;
// final String path = HTApp.getInstance().getDirFilePath() + fileName;
// dialog.show();
// new OkHttpUtils(context).loadFile(remotePath, path, new OkHttpUtils.DownloadCallBack() {
// @Override
// public void onSuccess() {
// if (dialog != null && dialog.isShowing()) {
// dialog.dismiss();
// }
// File file1 = new File(path);
// switch (copyType) {
// case "image":
// showForwordDialog(context, copyType, file1.getAbsolutePath(), message, file1.getAbsolutePath(),toChatUsername,userJson);
// break;
// case "voice":
// showForwordDialog(context, copyType, file1.getAbsolutePath(), message, null,toChatUsername,userJson);
// break;
// }
// }
//
// @Override
// public void onFailure(String message) {
// if (dialog != null && dialog.isShowing()) {
// dialog.dismiss();
// }
// }
// });
// }
}
/**
* 转发
*
* @param forwordType
* @param localPath
* @param message1
* @param imagePath
* @param toChatUsername
* @param extJSON
*/
private static void showForwordDialog(Activity context, final String forwordType, final String localPath, final HTMessage message1, String imagePath, String toChatUsername, JSONObject extJSON) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("forwordType", forwordType);
jsonObject.put("localPath", localPath);
jsonObject.put("msgId", message1.getMsgId());
jsonObject.put("imagePath", imagePath);
jsonObject.put("toChatUsername", toChatUsername);
jsonObject.put("exobj", extJSON.toJSONString());
Intent intent = new Intent(context, ChooseContactActivity.class);
intent.putExtra("obj", jsonObject.toJSONString());
context.startActivity(intent);
}
public static void loadMessageFile(HTMessage htMessage, String chatTo, final Activity context, final CallBack callBack) {
final ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setMessage(context.getString(R.string.loading));
progressDialog.show();
PathUtils pathUtils = new PathUtils(chatTo, context);
String remotePath = "";
String fileName = "";
String filePath = null;
if (htMessage.getType() == HTMessage.Type.VOICE) {
HTMessageVoiceBody htMessageVoiceBody = (HTMessageVoiceBody) htMessage.getBody();
remotePath = htMessageVoiceBody.getRemotePath();
fileName = htMessageVoiceBody.getFileName();
filePath = pathUtils.getVoicePath().getAbsolutePath() + "/" + fileName;
} else if (htMessage.getType() == HTMessage.Type.IMAGE) {
HTMessageImageBody htMessageImageBody = (HTMessageImageBody) htMessage.getBody();
remotePath = htMessageImageBody.getRemotePath();
fileName = htMessageImageBody.getFileName();
filePath = pathUtils.getImagePath().getAbsolutePath() + "/" + fileName;
}
final String finalFilePath = filePath;
new OkHttpUtils(context).loadFile(remotePath, filePath, new OkHttpUtils.DownloadCallBack() {
@Override
public void onSuccess() {
context.runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
callBack.completed(finalFilePath);
}
});
}
@Override
public void onFailure(String message) {
context.runOnUiThread(new Runnable() {
@Override
public void run() {
callBack.error();
progressDialog.dismiss();
}
});
}
});
}
public interface CallBack {
void error();
void completed(String localPath);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/ImageUtils.java
================================================
package com.htmessage.yichatopen.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.ExifInterface;
import android.media.ThumbnailUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Created by huangfangyi on 2016/12/4.
* qq 84543217
*/
public class ImageUtils {
public ImageUtils() {
}
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
return getRoundedCornerBitmap(bitmap, 6);
}
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
public static Bitmap getVideoThumbnail(String videoPath, int width, int height,
int kind) {
Bitmap bitmap = null;
// 获取视频的缩略图
bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, kind);
System.out.println("w" + bitmap.getWidth());
System.out.println("h" + bitmap.getHeight());
bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height,
ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
return bitmap;
}
public static Bitmap decodeScaleImage(String var0) {
BitmapFactory.Options var3 = getBitmapOptions(var0);
int var4 = calculateInSampleSize(var3, 420, 420);
var3.inSampleSize = var4;
var3.inJustDecodeBounds = false;
Bitmap var5 = BitmapFactory.decodeFile(var0, var3);
int var6 = readPictureDegree(var0);
Bitmap var7 = null;
if (var5 != null && var6 != 0) {
var7 = rotaingImageView(var6, var5);
var5.recycle();
var5 = null;
return var7;
} else {
return var5;
}
}
public static String getScaledImage(Context var0, String var1) {
File var2 = new File(var1);
if (!var2.exists()) {
return var1;
} else {
long var3 = var2.length();
if (var3 <= 102400L) {
return var1;
} else {
Bitmap var5 = decodeScaleImage(var1);
try {
File var6 = File.createTempFile("image", ".jpg", var0.getFilesDir());
FileOutputStream var7 = new FileOutputStream(var6);
var5.compress(Bitmap.CompressFormat.JPEG, 70, var7);
var7.close();
return var6.getAbsolutePath();
} catch (Exception var8) {
var8.printStackTrace();
return var1;
}
}
}
}
public static String getScaledImage(Context var0, String var1, int var2) {
File var3 = new File(var1);
if (var3.exists()) {
long var4 = var3.length();
if (var4 > 102400L) {
Bitmap var6 = decodeScaleImage(var1);
try {
File var7 = new File(var0.getExternalCacheDir(), "eaemobTemp" + var2 + ".jpg");
FileOutputStream var8 = new FileOutputStream(var7);
var6.compress(Bitmap.CompressFormat.JPEG, 60, var8);
var8.close();
return var7.getAbsolutePath();
} catch (Exception var9) {
var9.printStackTrace();
}
}
}
return var1;
}
public static Bitmap rotaingImageView(int var0, Bitmap var1) {
Matrix var2 = new Matrix();
var2.postRotate((float) var0);
Bitmap var3 = Bitmap.createBitmap(var1, 0, 0, var1.getWidth(), var1.getHeight(), var2, true);
return var3;
}
/* 获取缩略图
*
* @param path
* @param targetWidth
* @return
*/
public static String getThumbnailImage(String path, int targetWidth, int targetHight) {
Bitmap scaleImage = decodeScaleImage(path);
try {
File file = File.createTempFile("image", ".jpg");
FileOutputStream fileOutputStream = new FileOutputStream(file);
scaleImage.compress(Bitmap.CompressFormat.JPEG, 60, fileOutputStream);
fileOutputStream.close();
return file.getAbsolutePath();
} catch (Exception e) {
e.printStackTrace();
return path;
}
}
/**
* 图片解析
*
* @param context
* @param resId
* @param targetWidth
* @param targetHeight
* @return
*/
public static Bitmap decodeScaleImage(Context context, int resId, int targetWidth, int targetHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(context.getResources(), resId, options);
options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId, options);
return bitmap;
}
/**
* 计算样本大小
*
* @param options
* @param targetWidth
* @param targetHeight
* @return
*/
public static int calculateInSampleSize(BitmapFactory.Options options, int targetWidth, int targetHeight) {
int height = options.outHeight;
int width = options.outWidth;
int scale = 1;
if (height > targetHeight || width > targetWidth) {
int heightScale = Math.round((float) height / (float) targetHeight);
int widthScale = Math.round((float) width / (float) targetWidth);
scale = heightScale > widthScale ? heightScale : widthScale;
}
return scale;
}
/**
* 获取BitmapFactory.Options
*
* @param pathName
* @return
*/
public static BitmapFactory.Options getBitmapOptions(String pathName) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, opts);
return opts;
}
/**
* 获取图片角度
*
* @param filename
* @return
*/
public static int readPictureDegree(String filename) {
short degree = 0;
try {
ExifInterface exifInterface = new ExifInterface(filename);
int anInt = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
switch (anInt) {
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
case ExifInterface.ORIENTATION_TRANSPOSE:
case ExifInterface.ORIENTATION_TRANSVERSE:
default:
break;
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
/**
* 旋转ImageView
*
* @param degree
* @param source
* @return
*/
public static Bitmap rotatingImageView(int degree, Bitmap source) {
Matrix matrix = new Matrix();
matrix.postRotate((float) degree);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
/**
* 设置水印图片在左上角
*
* @param src
* @param watermark
* @param paddingLeft
* @param paddingTop
* @return
*/
public static Bitmap createWaterMaskLeftTop(Context context, Bitmap src, Bitmap watermark, int paddingLeft, int paddingTop) {
return createWaterMaskBitmap(src, watermark, dp2px(context, paddingLeft), dp2px(context, paddingTop));
}
/**
* 创建水印图片
* @param src
* @param watermark
* @param paddingLeft
* @param paddingTop
* @return
*/
private static Bitmap createWaterMaskBitmap(Bitmap src, Bitmap watermark, int paddingLeft, int paddingTop) {
if (src == null) {
return null;
}
int width = src.getWidth();
int height = src.getHeight();
//创建一个bitmap
Bitmap newb = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
//将该图片作为画布
Canvas canvas = new Canvas(newb);
//在画布 0,0坐标上开始绘制原始图片
canvas.drawBitmap(src, 0, 0, null);
//在画布上绘制水印图片
canvas.drawBitmap(watermark, paddingLeft, paddingTop, null);
// 保存
canvas.save(Canvas.ALL_SAVE_FLAG);
// 存储
canvas.restore();
return newb;
}
/**
* 设置水印图片在右下角
*
* @param src
* @param watermark
* @param paddingRight
* @param paddingBottom
* @return
*/
public static Bitmap createWaterMaskRightBottom(Context context, Bitmap src, Bitmap watermark, int paddingRight, int paddingBottom) {
return createWaterMaskBitmap(src, watermark, src.getWidth() - watermark.getWidth() - dp2px(context, paddingRight),
src.getHeight() - watermark.getHeight() - dp2px(context, paddingBottom));
}
/**
* 设置水印图片到右上角
*
* @param src
* @param watermark
* @param paddingRight
* @param paddingTop
* @return
*/
public static Bitmap createWaterMaskRightTop(Context context, Bitmap src, Bitmap watermark, int paddingRight, int paddingTop) {
return createWaterMaskBitmap(src, watermark, src.getWidth() - watermark.getWidth() - dp2px(context, paddingRight), dp2px(context, paddingTop));
}
/**
* 设置水印图片到左下角
*
* @param src
* @param watermark
* @param paddingLeft
* @param paddingBottom
* @return
*/
public static Bitmap createWaterMaskLeftBottom(Context context, Bitmap src, Bitmap watermark, int paddingLeft, int paddingBottom) {
return createWaterMaskBitmap(src, watermark, dp2px(context, paddingLeft), src.getHeight() - watermark.getHeight() - dp2px(context, paddingBottom));
}
/**
* 设置水印图片到中间
*
* @param src
* @param watermark
* @return
*/
public static Bitmap createWaterMaskCenter(Bitmap src, Bitmap watermark) {
return createWaterMaskBitmap(src, watermark, (src.getWidth() - watermark.getWidth()) / 2, (src.getHeight() - watermark.getHeight()) / 2);
}
/**
* 给图片添加文字到左上角
*
* @param context
* @param bitmap
* @param text
* @return
*/
public static Bitmap drawTextToLeftTop(Context context, Bitmap bitmap, String text, int size, int color, int paddingLeft, int paddingTop) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(context, bitmap, text, paint, bounds, dp2px(context, paddingLeft), dp2px(context, paddingTop) + bounds.height());
}
/**
* 绘制文字到右下角
*
* @param context
* @param bitmap
* @param text
* @param size
* @param color
* @param paddingRight
* @param paddingBottom
* @return
*/
public static Bitmap drawTextToRightBottom(Context context, Bitmap bitmap, String text, int size, int color, int paddingRight, int paddingBottom) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(context, bitmap, text, paint, bounds, bitmap.getWidth() - bounds.width() - dp2px(context, paddingRight), bitmap.getHeight() - dp2px(context, paddingBottom));
}
/**
* 绘制文字到右上方
*
* @param context
* @param bitmap
* @param text
* @param size
* @param color
* @param paddingRight
* @param paddingTop
* @return
*/
public static Bitmap drawTextToRightTop(Context context, Bitmap bitmap, String text, int size, int color, int paddingRight, int paddingTop) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(context, bitmap, text, paint, bounds, bitmap.getWidth() - bounds.width() - dp2px(context, paddingRight), dp2px(context, paddingTop) + bounds.height());
}
/**
* 绘制文字到左下方
*
* @param context
* @param bitmap
* @param text
* @param size
* @param color
* @param paddingLeft
* @param paddingBottom
* @return
*/
public static Bitmap drawTextToLeftBottom(Context context, Bitmap bitmap, String text,
int size, int color, int paddingLeft, int paddingBottom) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(context, bitmap, text, paint, bounds, dp2px(context, paddingLeft), bitmap.getHeight() - dp2px(context, paddingBottom));
}
/**
* 绘制文字到中间
*
* @param context
* @param bitmap
* @param text
* @param size
* @param color
* @return
*/
public static Bitmap drawTextToCenter(Context context, Bitmap bitmap, String text,
int size, int color) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(context, bitmap, text, paint, bounds, (bitmap.getWidth() - bounds.width()) / 2, (bitmap.getHeight() + bounds.height()) / 2);
}
/**
* 图片上绘制文字
* @param context
* @param bitmap
* @param text
* @param paint
* @param bounds
* @param paddingLeft
* @param paddingTop
* @return
*/
private static Bitmap drawTextToBitmap(Context context, Bitmap bitmap, String text, Paint paint, Rect bounds, int paddingLeft, int paddingTop) {
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
paint.setDither(true); // 获取跟清晰的图像采样
paint.setFilterBitmap(true);// 过滤一些
if (bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
canvas.drawText(text, paddingLeft, paddingTop, paint);
return bitmap;
}
/**
* 缩放图片
*
* @param src
* @param w
* @param h
* @return
*/
public static Bitmap scaleWithWH(Bitmap src, double w, double h) {
if (w == 0 || h == 0 || src == null) {
return src;
} else {
// 记录src的宽高
int width = src.getWidth();
int height = src.getHeight();
// 创建一个matrix容器
Matrix matrix = new Matrix();
// 计算缩放比例
float scaleWidth = (float) (w / width);
float scaleHeight = (float) (h / height);
// 开始缩放
matrix.postScale(scaleWidth, scaleHeight);
// 创建缩放后的图片
return Bitmap.createBitmap(src, 0, 0, width, height, matrix, true);
}
}
/**
* dip转pix
*
* @param context
* @param dp
* @return
*/
public static int dp2px(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/OkHttpUtils.java
================================================
package com.htmessage.yichatopen.utils;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.yichatopen.R;
import com.htmessage.yichatopen.HTConstant;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* Created by huangfangyi on 2016/10/27.
* qq 84543217
*/
public class OkHttpUtils {
private Context context;
private OkHttpClient okHttpClient;
private static final int RESULT_ERROR = 1000;
private static final int RESULT_SUCESS = 2000;
private HttpCallBack httpCallBack;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int reusltCode = msg.what;
switch (reusltCode) {
case RESULT_ERROR:
httpCallBack.onFailure((String) msg.obj);
// Toast.makeText(context, "服务器端无响应", Toast.LENGTH_SHORT).show();
Log.d("result----->", (String) msg.obj);
break;
case RESULT_SUCESS:
String result = (String) msg.obj;
Log.d("result----->", result);
try {
JSONObject jsonObject = JSONObject.parseObject(result);
httpCallBack.onResponse(jsonObject);
} catch (JSONException e) {
httpCallBack.onFailure((String) msg.obj);
// Toast.makeText(context, "响应数据解析错误", Toast.LENGTH_SHORT).show();
}
break;
}
}
};
public OkHttpUtils(Context context) {
this.context = context;
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10000L, TimeUnit.MILLISECONDS)
.readTimeout(10000L, TimeUnit.MILLISECONDS)
.build();
}
//纯粹键值对post请求
public void post(List params, String url, HttpCallBack httpCallBack) {
Log.d("url----->>", url);
this.httpCallBack = httpCallBack;
FormBody.Builder bodyBulder = new FormBody.Builder();
JSONObject userJson = HTApp.getInstance().getUserJson();
if (userJson!=null){
String session = userJson.getString(HTConstant.JSON_KEY_SESSION);
if (session!=null){
bodyBulder.add("session",session);
}
Log.d("session----->>", session);
}
for (Param param : params) {
bodyBulder.add(param.getKey(), param.getValue());
Log.d("param.getKey()----->>", param.getKey());
Log.d("param.getValue()----->>", param.getValue());
}
RequestBody requestBody = bodyBulder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
startRequest(request);
}
//键值对+文件 post请求
public void post(List params, List files, String url, HttpCallBack httpCallBack) {
Log.d("url----->>", url);
this.httpCallBack = httpCallBack;
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
for (Param param : params) {
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\""), RequestBody.create(MediaType.parse(guessMimeType(param.getKey())), param.getValue()));
Log.d("param.getKey()----->>", param.getKey());
Log.d("param.getValue()----->>", param.getValue());
}
for (File file : files) {
if (file != null && file.exists()) {
//TODO-本项目固化文件的键名为“file”
builder.addPart(Headers.of("Content-Disposition",
"form-data; name=\"" + "file" + "\"; filename=\"" + file.getName()+ "\""),
RequestBody.create(MediaType.parse(guessMimeType(file.getName())), file));
Log.d("file.getName()----->>", file.getName());
}
}
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
startRequest(request);
}
private void startRequest(Request request) {
if (CommonUtils.isNetWorkConnected(context)){
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Message message = handler.obtainMessage();
message.what = RESULT_ERROR;
message.obj = e.getMessage().toString();
message.sendToTarget();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Message message = handler.obtainMessage();
message.what = RESULT_SUCESS;
message.obj = response.body().string();
message.sendToTarget();
}
});
}else{
Toast.makeText(context, R.string.the_current_network, Toast.LENGTH_SHORT).show();
}
}
public interface HttpCallBack {
void onResponse(JSONObject jsonObject);
void onFailure(String errorMsg);
}
/**
* 下载不带进度
*/
public interface DownloadCallBack {
void onSuccess();
void onFailure(String message);
}
private String guessMimeType(String path) {
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String contentTypeFor = fileNameMap.getContentTypeFor(path);
if (contentTypeFor == null) {
contentTypeFor = "application/octet-stream";
}
return contentTypeFor;
}
public void loadFile(String url, final String savePath, final DownloadCallBack callBack){
Request request = new Request.Builder()
//下载地址
.url(url)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.onFailure(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
int len;
byte[] buf = new byte[2048];
InputStream inputStream = response.body().byteStream();
//可以在这里自定义路径
File file1 = new File(savePath);
FileOutputStream fileOutputStream = new FileOutputStream(file1);
while ((len = inputStream.read(buf)) != -1) {
fileOutputStream.write(buf, 0, len);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
callBack.onSuccess();
}
});
}
/**
* 下载的带进度的callback
*/
public interface ProgressDownloadCallBack {
void onSuccess();
void onProgress(int progress);
void onFailure();
}
/**
* 下载文件带进度
*
* @param url 下载地址
* @param savePath 保存地址
* @param callBack ProgressDownloadCallBack
*/
public void loadFileHasProgress(String url, final String savePath, final ProgressDownloadCallBack callBack) {
Request request = new Request.Builder()
//下载地址
.url(url)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.onFailure();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
int len;
byte[] buf = new byte[2048];
InputStream inputStream = response.body().byteStream();
long requestLength = response.body().contentLength();
long total = 0;
//可以在这里自定义路径
File file1 = new File(savePath);
FileOutputStream fileOutputStream = new FileOutputStream(file1);
while ((len = inputStream.read(buf)) != -1) {
total += len;
// publishing the progress....
if (requestLength > 0) // only if total length is known
callBack.onProgress((int) (total * 100 / requestLength));
fileOutputStream.write(buf, 0, len);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
callBack.onSuccess();
}
});
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/Param.java
================================================
package com.htmessage.yichatopen.utils;
/**
* Created by ustc on 2016/6/30.
*/
public class Param {
private String key;
private String value;
public Param(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/PathUtils.java
================================================
package com.htmessage.yichatopen.utils;
import android.content.Context;
import android.os.Environment;
import android.util.Log;
import com.htmessage.yichatopen.HTApp;
import com.htmessage.sdk.model.HTMessage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
/**
* Created by huangfangyi on 2016/12/4.
* qq 84543217
*/
public class PathUtils {
private static PathUtils instance;
private static File storageDir = null;
private File voicePath = null;
private File imagePath = null;
private File videoPath = null;
private File filePath;
private static String pathPrefix;
public PathUtils(String chatTo, Context context) {
String username= HTApp.getInstance().getUsername();
String packageName = context.getPackageName();
pathPrefix = "/Android/data/" + packageName + "/";
this.voicePath = generateVoicePath(username,chatTo,context);
if(!this.voicePath.exists()) {
this.voicePath.mkdirs();
}
this.imagePath = generateImagePath(username, chatTo, context);
if(!this.imagePath.exists()) {
this.imagePath.mkdirs();
}
this.videoPath = generateVideoPath(username, chatTo, context);
if(!this.videoPath.exists()) {
this.videoPath.mkdirs();
}
this.filePath = generateFiePath(username, chatTo, context);
if(!this.filePath.exists()) {
this.filePath.mkdirs();
}
}
public File getImagePath() {
return this.imagePath;
}
public File getVoicePath() {
return this.voicePath;
}
public File getFilePath() {
return this.filePath;
}
public File getVideoPath() {
return this.videoPath;
}
private static File getStorageDir(Context context) {
if(storageDir == null) {
File file = Environment.getExternalStorageDirectory();
if(file.exists()) {
return file;
}
storageDir = context.getFilesDir();
}
return storageDir;
}
private static File generateImagePath(String username, String chatTo, Context context) {
String filePath = null;
if(username == null) {
filePath = pathPrefix + chatTo + "/image/";
} else {
filePath = pathPrefix + username + "/" + chatTo + "/image/";
}
return new File(getStorageDir(context), filePath);
}
private static File generateVoicePath(String username, String chatTo, Context context) {
String filePath = null;
if(username == null) {
filePath = pathPrefix + chatTo + "/voice/";
} else {
filePath = pathPrefix + username + "/" + chatTo + "/voice/";
}
return new File(getStorageDir(context), filePath);
}
private static File generateFiePath(String username, String chatTo, Context context) {
String filePath = null;
if(username == null) {
filePath = pathPrefix + chatTo + "/file/";
} else {
filePath = pathPrefix + username + "/" + chatTo + "/file/";
}
return new File(getStorageDir(context), filePath);
}
private static File generateVideoPath(String username, String chatTo, Context context) {
String filePath = null;
if(username == null) {
filePath = pathPrefix + chatTo + "/video/";
} else {
filePath = pathPrefix + username + "/" + chatTo + "/video/";
}
return new File(getStorageDir(context), filePath);
}
public void saveSendFileInDisk(final String filePath, final HTMessage.Type type, final NewFilePathCallBack newFilePathCallBack){
final String fileName=filePath.substring(filePath.lastIndexOf("/")+1);
new Thread(new Runnable() {
@Override
public void run() {
String finalPath=null;
if(type== HTMessage.Type.IMAGE){
finalPath=getImagePath().getAbsolutePath()+fileName;
}else if(type== HTMessage.Type.VOICE){
finalPath=getVoicePath().getAbsolutePath()+fileName;
}
else if(type== HTMessage.Type.VIDEO){
finalPath=getVideoPath().getAbsolutePath()+fileName;
}
else if(type== HTMessage.Type.FILE){
finalPath=getFilePath().getAbsolutePath()+fileName;
}
Log.d("filePath--->",filePath);
Log.d("finalPath--->",finalPath);
copyFile(filePath,finalPath,newFilePathCallBack);
}
}).start();
}
interface NewFilePathCallBack{
void onSuccess(String filePath);
}
/**
* 复制单个文件
* @param oldPath String 原文件路径 如:c:/fqf.txt
* @param newPath String 复制后路径 如:f:/fqf.txt
* @return boolean
*/
public void copyFile(String oldPath, String newPath,NewFilePathCallBack newFilePathCallBack) {
try {
int bytesum = 0;
int byteread = 0;
File oldfile = new File(oldPath);
if (oldfile.exists()) { //文件存在时
InputStream inStream = new FileInputStream(oldPath); //读入原文件
FileOutputStream fs = new FileOutputStream(newPath);
byte[] buffer = new byte[1444];
int length;
while ( (byteread = inStream.read(buffer)) != -1) {
bytesum += byteread; //字节数 文件大小
System.out.println(bytesum);
fs.write(buffer, 0, byteread);
}
inStream.close();
}
newFilePathCallBack.onSuccess(newPath);
}
catch (Exception e) {
System.out.println("复制单个文件操作出错");
e.printStackTrace();
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/UpdateLastLoginTimeUtils.java
================================================
package com.htmessage.yichatopen.utils;
import android.content.Context;
import android.util.Log;
import com.alibaba.fastjson.JSONObject;
import com.htmessage.yichatopen.HTConstant;
import java.util.ArrayList;
import java.util.List;
/**
* 项目名称:yichat0504
* 类描述:UpdateLocalLoginTimeUtils 描述:
* 创建人:songlijie
* 创建时间:2017/7/5 17:48
* 邮箱:814326663@qq.com
*/
public class UpdateLastLoginTimeUtils {
private static String TAG = UpdateLastLoginTimeUtils.class.getSimpleName();
public static void sendLocalTimeToService(Context context){
List params = new ArrayList<>();
new OkHttpUtils(context).post(params, HTConstant.URL_SEND_LOCAL_LOGIN_TIME, new OkHttpUtils.HttpCallBack() {
@Override
public void onResponse(JSONObject jsonObject) {
int code = jsonObject.getIntValue("code");
switch (code){
case 1:
Log.d(TAG,"上传本地成功!");
break;
default:
Log.d(TAG,"上传本地失败!");
break;
}
}
@Override
public void onFailure(String errorMsg) {
Log.d(TAG,"上传本地失败!"+errorMsg);
}
});
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/utils/Validator.java
================================================
package com.htmessage.yichatopen.utils;
import java.util.regex.Pattern;
/**
* 校验器:利用正则表达式校验邮箱、手机号等
*
* @author liujiduo
*
*/
public class Validator {
/**
* 正则表达式:验证用户名
*/
public static final String REGEX_USERNAME = "^[a-zA-Z]\\w{5,17}$";
/**
* 正则表达式:验证密码
*/
public static final String REGEX_PASSWORD = "^[a-zA-Z0-9]{6,16}$";
/**
* 正则表达式:验证手机号 .matches("^[1][3578]\\d{9}")
*/
// public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";//
public static final String REGEX_MOBILE = "^(13[0-9]|15[012356789]|17[03678]|18[0-9]|14[57])[0-9]{8}$";
/**
* 正则表达式:验证邮箱
*/
public static final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
/**
* 正则表达式:验证汉字
*/
public static final String REGEX_CHINESE = "^[\u4e00-\u9fa5],{0,}$";
/**
* 正则表达式:验证身份证
*/
public static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)";
/**
* 正则表达式:验证URL
*/
public static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
/**
* 正则表达式:验证IP地址
*/
public static final String REGEX_IP_ADDR = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)";
/**
* 校验用户名
*
* @param username
* @return 校验通过返回true,否则返回false
*/
public static boolean isUsername(String username) {
return Pattern.matches(REGEX_USERNAME, username);
}
/**
* 校验密码
*
* @param password
* @return 校验通过返回true,否则返回false
*/
public static boolean isPassword(String password) {
return Pattern.matches(REGEX_PASSWORD, password);
}
/**
* 校验手机号
*
* @param mobile
* @return 校验通过返回true,否则返回false
*/
public static boolean isMobile(String mobile) {
return Pattern.matches(REGEX_MOBILE, mobile);
}
/**
* 校验邮箱
*
* @param email
* @return 校验通过返回true,否则返回false
*/
public static boolean isEmail(String email) {
return Pattern.matches(REGEX_EMAIL, email);
}
/**
* 校验汉字
*
* @param chinese
* @return 校验通过返回true,否则返回false
*/
public static boolean isChinese(String chinese) {
return Pattern.matches(REGEX_CHINESE, chinese);
}
/**
* 校验身份证
*
* @param idCard
* @return 校验通过返回true,否则返回false
*/
public static boolean isIDCard(String idCard) {
return Pattern.matches(REGEX_ID_CARD, idCard);
}
/**
* 校验URL
*
* @param url
* @return 校验通过返回true,否则返回false
*/
public static boolean isUrl(String url) {
return Pattern.matches(REGEX_URL, url);
}
/**
* 校验IP地址
*
* @param ipAddr
* @return
*/
public static boolean isIPAddr(String ipAddr) {
return Pattern.matches(REGEX_IP_ADDR, ipAddr);
}
public static void main(String[] args) {
String username = "fdsdfsdj";
System.out.println(Validator.isUsername(username));
System.out.println(Validator.isChinese(username));
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/HTAlertDialog.java
================================================
package com.htmessage.yichatopen.widget;
import android.app.AlertDialog;
import android.content.Context;
import android.view.View;
import android.view.Window;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.htmessage.yichatopen.R;
/**
* Created by huangfangyi on 2016/7/3.\
* QQ:84543217
*/
public class HTAlertDialog {
private Context context;
private String title;
private String[] items;
public HTAlertDialog(Context context, String title, String[] items) {
this.context = context;
this.title = title;
this.items = items;
}
public void init(final OnItemClickListner onItemClickListner) {
final AlertDialog dlg = new AlertDialog.Builder(context).create();
dlg.show();
Window window = dlg.getWindow();
window.setContentView(R.layout.dialog_alert);
if (title != null) {
window.findViewById(R.id.ll_title).setVisibility(View.VISIBLE);
TextView tv_title = (TextView) window.findViewById(R.id.tv_title);
tv_title.setText(title);
}
//默认是2个item--最多支持5个,如需增加,请修改布局文件
LinearLayout[] linearLayouts=new LinearLayout[]{
(LinearLayout) window.findViewById(R.id.ll_content1),
(LinearLayout) window.findViewById(R.id.ll_content2),
(LinearLayout) window.findViewById(R.id.ll_content3),
(LinearLayout) window.findViewById(R.id.ll_content4),
(LinearLayout) window.findViewById(R.id.ll_content5)
};
TextView[] textViews=new TextView[]{
(TextView) window.findViewById(R.id.tv_content1),
(TextView) window.findViewById(R.id.tv_content2),
(TextView) window.findViewById(R.id.tv_content3),
(TextView) window.findViewById(R.id.tv_content4),
(TextView) window.findViewById(R.id.tv_content5),
};
for(int i=0;i= VERSION_CODES.JELLY_BEAN) {
SDK16.postOnAnimation(view, runnable);
} else {
view.postDelayed(runnable, SIXTY_FPS_INTERVAL);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/photoview/IPhotoView.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.htmessage.yichatopen.widget.photoview;
import android.graphics.RectF;
import android.view.View;
import android.widget.ImageView;
public interface IPhotoView {
/**
* Returns true if the PhotoView is set to allow zooming of Photos.
*
* @return true if the PhotoView allows zooming.
*/
boolean canZoom();
/**
* Gets the Display Rectangle of the currently displayed Drawable. The
* Rectangle is relative to this View and includes all scaling and
* translations.
*
* @return - RectF of Displayed Drawable
*/
RectF getDisplayRect();
/**
* @return The current minimum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
*/
float getMinScale();
/**
* @return The current middle scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
*/
float getMidScale();
/**
* @return The current maximum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
*/
float getMaxScale();
/**
* Returns the current scale value
*
* @return float - current scale value
*/
float getScale();
/**
* Return the current scale type in use by the ImageView.
*/
ImageView.ScaleType getScaleType();
/**
* Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll to it's horizontal edge.
*/
void setAllowParentInterceptOnEdge(boolean allow);
/**
* Sets the minimum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
*/
void setMinScale(float minScale);
/**
* Sets the middle scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
*/
void setMidScale(float midScale);
/**
* Sets the maximum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
*/
void setMaxScale(float maxScale);
/**
* Register a callback to be invoked when the Photo displayed by this view is long-pressed.
*
* @param listener - Listener to be registered.
*/
void setOnLongClickListener(View.OnLongClickListener listener);
/**
* Register a callback to be invoked when the Matrix has changed for this
* View. An example would be the user panning or scaling the Photo.
*
* @param listener - Listener to be registered.
*/
void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener);
/**
* Register a callback to be invoked when the Photo displayed by this View
* is tapped with a single tap.
*
* @param listener - Listener to be registered.
*/
void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener);
/**
* Register a callback to be invoked when the View is tapped with a single
* tap.
*
* @param listener - Listener to be registered.
*/
void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener);
/**
* Controls how the image should be resized or moved to match the size of
* the ImageView. Any scaling or panning will happen within the confines of
* this {@link ImageView.ScaleType}.
*
* @param scaleType - The desired scaling mode.
*/
void setScaleType(ImageView.ScaleType scaleType);
/**
* Allows you to enable/disable the zoom functionality on the ImageView.
* When disable the ImageView reverts to using the FIT_CENTER matrix.
*
* @param zoomable - Whether the zoom functionality is enabled.
*/
void setZoomable(boolean zoomable);
/**
* Zooms to the specified scale, around the focal point given.
*
* @param scale - Scale to zoom to
* @param focalX - X Focus Point
* @param focalY - Y Focus Point
*/
void zoomTo(float scale, float focalX, float focalY);
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/photoview/PhotoView.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.htmessage.yichatopen.widget.photoview;
import android.content.Context;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.widget.ImageView;
public class PhotoView extends ImageView implements IPhotoView {
private final PhotoViewAttacher mAttacher;
private ScaleType mPendingScaleType;
public PhotoView(Context context) {
this(context, null);
}
public PhotoView(Context context, AttributeSet attr) {
this(context, attr, 0);
}
public PhotoView(Context context, AttributeSet attr, int defStyle) {
super(context, attr, defStyle);
super.setScaleType(ScaleType.MATRIX);
mAttacher = new PhotoViewAttacher(this);
if (null != mPendingScaleType) {
setScaleType(mPendingScaleType);
mPendingScaleType = null;
}
}
@Override
public boolean canZoom() {
return mAttacher.canZoom();
}
@Override
public RectF getDisplayRect() {
return mAttacher.getDisplayRect();
}
@Override
public float getMinScale() {
return mAttacher.getMinScale();
}
@Override
public float getMidScale() {
return mAttacher.getMidScale();
}
@Override
public float getMaxScale() {
return mAttacher.getMaxScale();
}
@Override
public float getScale() {
return mAttacher.getScale();
}
@Override
public ScaleType getScaleType() {
return mAttacher.getScaleType();
}
@Override
public void setAllowParentInterceptOnEdge(boolean allow) {
mAttacher.setAllowParentInterceptOnEdge(allow);
}
@Override
public void setMinScale(float minScale) {
mAttacher.setMinScale(minScale);
}
@Override
public void setMidScale(float midScale) {
mAttacher.setMidScale(midScale);
}
@Override
public void setMaxScale(float maxScale) {
mAttacher.setMaxScale(maxScale);
}
@Override
// setImageBitmap calls through to this method
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
if (null != mAttacher) {
mAttacher.update();
}
}
@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
if (null != mAttacher) {
mAttacher.update();
}
}
@Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
if (null != mAttacher) {
mAttacher.update();
}
}
@Override
public void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener) {
mAttacher.setOnMatrixChangeListener(listener);
}
@Override
public void setOnLongClickListener(OnLongClickListener l) {
mAttacher.setOnLongClickListener(l);
}
@Override
public void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener) {
mAttacher.setOnPhotoTapListener(listener);
}
@Override
public void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener) {
mAttacher.setOnViewTapListener(listener);
}
@Override
public void setScaleType(ScaleType scaleType) {
if (null != mAttacher) {
mAttacher.setScaleType(scaleType);
} else {
mPendingScaleType = scaleType;
}
}
@Override
public void setZoomable(boolean zoomable) {
mAttacher.setZoomable(zoomable);
}
@Override
public void zoomTo(float scale, float focalX, float focalY) {
mAttacher.zoomTo(scale, focalX, focalY);
}
@Override
protected void onDetachedFromWindow() {
mAttacher.cleanup();
super.onDetachedFromWindow();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/photoview/PhotoViewAttacher.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.htmessage.yichatopen.widget.photoview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import java.lang.ref.WeakReference;
class PhotoViewAttacher implements IPhotoView, View.OnTouchListener, VersionedGestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener, ViewTreeObserver.OnGlobalLayoutListener {
static final String LOG_TAG = "PhotoViewAttacher";
// let debug flag be dynamic, but still Proguard can be used to remove from
// release builds
static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
static final int EDGE_NONE = -1;
static final int EDGE_LEFT = 0;
static final int EDGE_RIGHT = 1;
static final int EDGE_BOTH = 2;
public static final float DEFAULT_MAX_SCALE = 2.0f;
// public static final float DEFAULT_MID_SCALE = 1.75f;
public static final float DEFAULT_MIN_SCALE = 1.0f;
private float mMinScale = DEFAULT_MIN_SCALE;
// private float mMidScale = DEFAULT_MID_SCALE;
private float mMaxScale = DEFAULT_MAX_SCALE;
private boolean mAllowParentInterceptOnEdge = true;
// private static void checkZoomLevels(float minZoom, float midZoom,
// float maxZoom) {
// if (minZoom >= midZoom) {
// throw new IllegalArgumentException(
// "MinZoom should be less than MidZoom");
// } else if (midZoom >= maxZoom) {
// throw new IllegalArgumentException(
// "MidZoom should be less than MaxZoom");
// }
// }
private static void checkZoomLevels(float minZoom,float maxZoom) {
if (minZoom >= maxZoom) {
throw new IllegalArgumentException("MinZoom should be less than maxZoom");
} /*else if (midZoom >= maxZoom) {
throw new IllegalArgumentException("MidZoom should be less than MaxZoom");
}*/
}
/**
* @return true if the ImageView exists, and it's Drawable existss
*/
private static boolean hasDrawable(ImageView imageView) {
return null != imageView && null != imageView.getDrawable();
}
/**
* @return true if the ScaleType is supported.
*/
private static boolean isSupportedScaleType(final ScaleType scaleType) {
if (null == scaleType) {
return false;
}
switch (scaleType) {
case MATRIX:
throw new IllegalArgumentException(scaleType.name() + " is not supported in PhotoView");
default:
return true;
}
}
/**
* Set's the ImageView's ScaleType to Matrix.
*/
private static void setImageViewScaleTypeMatrix(ImageView imageView) {
if (null != imageView) {
if (imageView instanceof PhotoView) {
/**
* PhotoView sets it's own ScaleType to Matrix, then diverts all
* calls setScaleType to this.setScaleType. Basically we don't
* need to do anything here
*/
} else {
imageView.setScaleType(ScaleType.MATRIX);
}
}
}
private WeakReference mImageView;
private ViewTreeObserver mViewTreeObserver;
// Gesture Detectors
private GestureDetector mGestureDetector;
private VersionedGestureDetector mScaleDragDetector;
// These are set so we don't keep allocating them on the heap
private final Matrix mBaseMatrix = new Matrix();
private final Matrix mDrawMatrix = new Matrix();
private final Matrix mSuppMatrix = new Matrix();
private final RectF mDisplayRect = new RectF();
private final float[] mMatrixValues = new float[9];
// Listeners
private OnMatrixChangedListener mMatrixChangeListener;
private OnPhotoTapListener mPhotoTapListener;
private OnViewTapListener mViewTapListener;
private OnLongClickListener mLongClickListener;
private int mIvTop, mIvRight, mIvBottom, mIvLeft;
private FlingRunnable mCurrentFlingRunnable;
private int mScrollEdge = EDGE_BOTH;
private boolean mZoomEnabled;
private ScaleType mScaleType = ScaleType.FIT_CENTER;
public PhotoViewAttacher(ImageView imageView) {
mImageView = new WeakReference(imageView);
imageView.setOnTouchListener(this);
mViewTreeObserver = imageView.getViewTreeObserver();
mViewTreeObserver.addOnGlobalLayoutListener(this);
// Make sure we using MATRIX Scale Type
setImageViewScaleTypeMatrix(imageView);
if (!imageView.isInEditMode()) {
// Create Gesture Detectors...
mScaleDragDetector = VersionedGestureDetector.newInstance(imageView.getContext(), this);
mGestureDetector = new GestureDetector(imageView.getContext(),
new GestureDetector.SimpleOnGestureListener() {
// forward long click listener
@Override
public void onLongPress(MotionEvent e) {
if (null != mLongClickListener) {
mLongClickListener.onLongClick(mImageView.get());
}
}
});
mGestureDetector.setOnDoubleTapListener(this);
// Finally, update the UI so that we're zoomable
setZoomable(true);
}
}
@Override
public final boolean canZoom() {
return mZoomEnabled;
}
/**
* Clean-up the resources attached to this object. This needs to be called
* when the ImageView is no longer used. A good example is from
* {@link View#onDetachedFromWindow()} or from
* {@link android.app.Activity#onDestroy()}. This is automatically called if
* you are using {@link PhotoView.co.senab.photoview.PhotoView}.
*/
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public final void cleanup() {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
if (null != mImageView) {
mImageView.get().getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
if (null != mViewTreeObserver && mViewTreeObserver.isAlive()) {
mViewTreeObserver.removeOnGlobalLayoutListener(this);
mViewTreeObserver = null;
// Clear listeners too
mMatrixChangeListener = null;
mPhotoTapListener = null;
mViewTapListener = null;
// Finally, clear ImageView
mImageView = null;
}
} else {
if (null != mImageView) {
mImageView.get().getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
if (null != mViewTreeObserver && mViewTreeObserver.isAlive()) {
mViewTreeObserver.removeGlobalOnLayoutListener(this);
mViewTreeObserver = null;
// Clear listeners too
mMatrixChangeListener = null;
mPhotoTapListener = null;
mViewTapListener = null;
// Finally, clear ImageView
mImageView = null;
}
}
}
@Override
public final RectF getDisplayRect() {
checkMatrixBounds();
return getDisplayRect(getDisplayMatrix());
}
public final ImageView getImageView() {
ImageView imageView = null;
if (null != mImageView) {
imageView = mImageView.get();
}
// If we don't have an ImageView, call cleanup()
if (null == imageView) {
cleanup();
throw new IllegalStateException(
"ImageView no longer exists. You should not use this PhotoViewAttacher any more.");
}
return imageView;
}
@Override
public float getMinScale() {
return mMinScale;
}
// @Override
// public float getMidScale() {
// return mMidScale;
// }
@Override
public float getMaxScale() {
return mMaxScale;
}
@Override
public final float getScale() {
return getValue(mSuppMatrix, Matrix.MSCALE_X);
}
@Override
public final ScaleType getScaleType() {
return mScaleType;
}
public final boolean onDoubleTap(MotionEvent ev) {
try {
float scale = getScale();
float x = ev.getX();
float y = ev.getY();
/*
* if (scale < mMidScale) { zoomTo(mMidScale, x, y); } else
*/if (/* scale >= mMidScale && */scale < mMaxScale) {
zoomTo(mMaxScale, x, y);
} else {
zoomTo(mMinScale, x, y);
}
} catch (ArrayIndexOutOfBoundsException e) {
// Can sometimes happen when getX() and getY() is called
}
return true;
}
public final boolean onDoubleTapEvent(MotionEvent e) {
// Wait for the confirmed onDoubleTap() instead
return false;
}
public final void onDrag(float dx, float dy) {
if (DEBUG) {
Log.d(LOG_TAG, String.format("onDrag: dx: %.2f. dy: %.2f", dx, dy));
}
ImageView imageView = getImageView();
if (null != imageView && hasDrawable(imageView)) {
mSuppMatrix.postTranslate(dx, dy);
checkAndDisplayMatrix();
/**
* Here we decide whether to let the ImageView's parent to start
* taking over the touch event.
*
* First we check whether this function is enabled. We never want
* the parent to take over if we're scaling. We then check the edge
* we're on, and the direction of the scroll (i.e. if we're pulling
* against the edge, aka 'overscrolling', let the parent take over).
*/
if (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling()) {
if (mScrollEdge == EDGE_BOTH || (mScrollEdge == EDGE_LEFT && dx >= 1f)
|| (mScrollEdge == EDGE_RIGHT && dx <= -1f)) {
imageView.getParent().requestDisallowInterceptTouchEvent(false);
}
}
}
}
@Override
public final void onFling(float startX, float startY, float velocityX, float velocityY) {
if (DEBUG) {
Log.d(LOG_TAG, "onFling. sX: " + startX + " sY: " + startY + " Vx: " + velocityX + " Vy: " + velocityY);
}
ImageView imageView = getImageView();
if (hasDrawable(imageView)) {
mCurrentFlingRunnable = new FlingRunnable(imageView.getContext());
mCurrentFlingRunnable.fling(imageView.getWidth(), imageView.getHeight(), (int) velocityX, (int) velocityY);
imageView.post(mCurrentFlingRunnable);
}
}
@Override
public final void onGlobalLayout() {
ImageView imageView = getImageView();
if (null != imageView && mZoomEnabled) {
final int top = imageView.getTop();
final int right = imageView.getRight();
final int bottom = imageView.getBottom();
final int left = imageView.getLeft();
/**
* We need to check whether the ImageView's bounds have changed.
* This would be easier if we targeted API 11+ as we could just use
* View.OnLayoutChangeListener. Instead we have to replicate the
* work, keeping track of the ImageView's bounds and then checking
* if the values change.
*/
if (top != mIvTop || bottom != mIvBottom || left != mIvLeft || right != mIvRight) {
// Update our base matrix, as the bounds have changed
updateBaseMatrix(imageView.getDrawable());
// Update values as something has changed
mIvTop = top;
mIvRight = right;
mIvBottom = bottom;
mIvLeft = left;
}
}
}
public final void onScale(float scaleFactor, float focusX, float focusY) {
if (DEBUG) {
Log.d(LOG_TAG, String.format("onScale: scale: %.2f. fX: %.2f. fY: %.2f", scaleFactor, focusX, focusY));
}
if (hasDrawable(getImageView()) && (getScale() < mMaxScale || scaleFactor < 1f)) {
mSuppMatrix.postScale(scaleFactor, scaleFactor, focusX, focusY);
checkAndDisplayMatrix();
}
}
public final boolean onSingleTapConfirmed(MotionEvent e) {
ImageView imageView = getImageView();
if (null != imageView) {
if (null != mPhotoTapListener) {
final RectF displayRect = getDisplayRect();
if (null != displayRect) {
final float x = e.getX(), y = e.getY();
// Check to see if the user tapped on the photo
if (displayRect.contains(x, y)) {
float xResult = (x - displayRect.left) / displayRect.width();
float yResult = (y - displayRect.top) / displayRect.height();
mPhotoTapListener.onPhotoTap(imageView, xResult, yResult);
return true;
}
}
}
if (null != mViewTapListener) {
mViewTapListener.onViewTap(imageView, e.getX(), e.getY());
}
}
return false;
}
@Override
public final boolean onTouch(View v, MotionEvent ev) {
boolean handled = false;
if (mZoomEnabled) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// First, disable the Parent from intercepting the touch
// event
v.getParent().requestDisallowInterceptTouchEvent(true);
// If we're flinging, and the user presses down, cancel
// fling
cancelFling();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// If the user has zoomed less than min scale, zoom back
// to min scale
if (getScale() < mMinScale) {
RectF rect = getDisplayRect();
if (null != rect) {
v.post(new AnimatedZoomRunnable(getScale(), mMinScale, rect.centerX(), rect.centerY()));
handled = true;
}
}
break;
}
// Check to see if the user double tapped
if (null != mGestureDetector && mGestureDetector.onTouchEvent(ev)) {
handled = true;
}
// Finally, try the Scale/Drag detector
if (null != mScaleDragDetector && mScaleDragDetector.onTouchEvent(ev)) {
handled = true;
}
}
return handled;
}
@Override
public void setAllowParentInterceptOnEdge(boolean allow) {
mAllowParentInterceptOnEdge = allow;
}
@Override
public void setMinScale(float minScale) {
// checkZoomLevels(minScale, mMidScale, mMaxScale);
checkZoomLevels(minScale, mMaxScale);
mMinScale = minScale;
}
// @Override
// public void setMidScale(float midScale) {
// checkZoomLevels(mMinScale, midScale, mMaxScale);
// mMidScale = midScale;
// }
@Override
public void setMaxScale(float maxScale) {
// checkZoomLevels(mMinScale, mMidScale, maxScale);
checkZoomLevels(mMinScale, maxScale);
mMaxScale = maxScale;
}
@Override
public final void setOnLongClickListener(OnLongClickListener listener) {
mLongClickListener = listener;
}
@Override
public final void setOnMatrixChangeListener(OnMatrixChangedListener listener) {
mMatrixChangeListener = listener;
}
@Override
public final void setOnPhotoTapListener(OnPhotoTapListener listener) {
mPhotoTapListener = listener;
}
@Override
public final void setOnViewTapListener(OnViewTapListener listener) {
mViewTapListener = listener;
}
@Override
public final void setScaleType(ScaleType scaleType) {
if (isSupportedScaleType(scaleType) && scaleType != mScaleType) {
mScaleType = scaleType;
// Finally update
update();
}
}
@Override
public final void setZoomable(boolean zoomable) {
mZoomEnabled = zoomable;
update();
}
public final void update() {
ImageView imageView = getImageView();
if (null != imageView) {
if (mZoomEnabled) {
// Make sure we using MATRIX Scale Type
setImageViewScaleTypeMatrix(imageView);
// Update the base matrix using the current drawable
updateBaseMatrix(imageView.getDrawable());
} else {
// Reset the Matrix...
resetMatrix();
}
}
}
@Override
public final void zoomTo(float scale, float focalX, float focalY) {
ImageView imageView = getImageView();
if (null != imageView) {
imageView.post(new AnimatedZoomRunnable(getScale(), scale, focalX, focalY));
}
}
protected Matrix getDisplayMatrix() {
mDrawMatrix.set(mBaseMatrix);
mDrawMatrix.postConcat(mSuppMatrix);
return mDrawMatrix;
}
private void cancelFling() {
if (null != mCurrentFlingRunnable) {
mCurrentFlingRunnable.cancelFling();
mCurrentFlingRunnable = null;
}
}
/**
* Helper method that simply checks the Matrix, and then displays the result
*/
private void checkAndDisplayMatrix() {
checkMatrixBounds();
setImageViewMatrix(getDisplayMatrix());
}
private void checkImageViewScaleType() {
ImageView imageView = getImageView();
/**
* PhotoView's getScaleType() will just divert to this.getScaleType() so
* only call if we're not attached to a PhotoView.
*/
if (null != imageView && !(imageView instanceof PhotoView)) {
if (imageView.getScaleType() != ScaleType.MATRIX) {
throw new IllegalStateException(
"The ImageView's ScaleType has been changed since attaching a PhotoViewAttacher");
}
}
}
private void checkMatrixBounds() {
final ImageView imageView = getImageView();
if (null == imageView) {
return;
}
final RectF rect = getDisplayRect(getDisplayMatrix());
if (null == rect) {
return;
}
final float height = rect.height(), width = rect.width();
float deltaX = 0, deltaY = 0;
final int viewHeight = imageView.getHeight();
if (height <= viewHeight) {
switch (mScaleType) {
case FIT_START:
deltaY = -rect.top;
break;
case FIT_END:
deltaY = viewHeight - height - rect.top;
break;
default:
deltaY = (viewHeight - height) / 2 - rect.top;
break;
}
} else if (rect.top > 0) {
deltaY = -rect.top;
} else if (rect.bottom < viewHeight) {
deltaY = viewHeight - rect.bottom;
}
final int viewWidth = imageView.getWidth();
if (width <= viewWidth) {
switch (mScaleType) {
case FIT_START:
deltaX = -rect.left;
break;
case FIT_END:
deltaX = viewWidth - width - rect.left;
break;
default:
deltaX = (viewWidth - width) / 2 - rect.left;
break;
}
mScrollEdge = EDGE_BOTH;
} else if (rect.left > 0) {
mScrollEdge = EDGE_LEFT;
deltaX = -rect.left;
} else if (rect.right < viewWidth) {
deltaX = viewWidth - rect.right;
mScrollEdge = EDGE_RIGHT;
} else {
mScrollEdge = EDGE_NONE;
}
// Finally actually translate the matrix
mSuppMatrix.postTranslate(deltaX, deltaY);
}
/**
* Helper method that maps the supplied Matrix to the current Drawable
*
* @param matrix
* - Matrix to map Drawable against
* @return RectF - Displayed Rectangle
*/
private RectF getDisplayRect(Matrix matrix) {
ImageView imageView = getImageView();
if (null != imageView) {
Drawable d = imageView.getDrawable();
if (null != d) {
mDisplayRect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
matrix.mapRect(mDisplayRect);
return mDisplayRect;
}
}
return null;
}
/**
* Helper method that 'unpacks' a Matrix and returns the required value
*
* @param matrix
* - Matrix to unpack
* @param whichValue
* - Which value from Matrix.M* to return
* @return float - returned value
*/
private float getValue(Matrix matrix, int whichValue) {
matrix.getValues(mMatrixValues);
return mMatrixValues[whichValue];
}
/**
* Resets the Matrix back to FIT_CENTER, and then displays it.s
*/
private void resetMatrix() {
mSuppMatrix.reset();
setImageViewMatrix(getDisplayMatrix());
checkMatrixBounds();
}
private void setImageViewMatrix(Matrix matrix) {
ImageView imageView = getImageView();
if (null != imageView) {
checkImageViewScaleType();
imageView.setImageMatrix(matrix);
// Call MatrixChangedListener if needed
if (null != mMatrixChangeListener) {
RectF displayRect = getDisplayRect(matrix);
if (null != displayRect) {
mMatrixChangeListener.onMatrixChanged(displayRect);
}
}
}
}
/**
* Calculate Matrix for FIT_CENTER
*
* @param d
* - Drawable being displayed
*/
private void updateBaseMatrix(Drawable d) {
ImageView imageView = getImageView();
if (null == imageView || null == d) {
return;
}
final float viewWidth = imageView.getWidth();
final float viewHeight = imageView.getHeight();
final int drawableWidth = d.getIntrinsicWidth();
final int drawableHeight = d.getIntrinsicHeight();
mBaseMatrix.reset();
final float widthScale = viewWidth / drawableWidth;
final float heightScale = viewHeight / drawableHeight;
if (mScaleType == ScaleType.CENTER) {
mBaseMatrix.postTranslate((viewWidth - drawableWidth) / 2F, (viewHeight - drawableHeight) / 2F);
} else if (mScaleType == ScaleType.CENTER_CROP) {
float scale = Math.max(widthScale, heightScale);
mBaseMatrix.postScale(scale, scale);
mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,
(viewHeight - drawableHeight * scale) / 2F);
} else if (mScaleType == ScaleType.CENTER_INSIDE) {
float scale = Math.min(1.0f, Math.min(widthScale, heightScale));
mBaseMatrix.postScale(scale, scale);
mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,
(viewHeight - drawableHeight * scale) / 2F);
} else {
RectF mTempSrc = new RectF(0, 0, drawableWidth, drawableHeight);
RectF mTempDst = new RectF(0, 0, viewWidth, viewHeight);
switch (mScaleType) {
case FIT_CENTER:
mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.CENTER);
break;
case FIT_START:
mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.START);
break;
case FIT_END:
mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.END);
break;
case FIT_XY:
mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.FILL);
break;
default:
break;
}
}
resetMatrix();
}
/**
* Interface definition for a callback to be invoked when the internal
* Matrix has changed for this View.
*
* @author Chris Banes
*/
public static interface OnMatrixChangedListener {
/**
* Callback for when the Matrix displaying the Drawable has changed.
* This could be because the View's bounds have changed, or the user has
* zoomed.
*
* @param rect
* - Rectangle displaying the Drawable's new bounds.
*/
void onMatrixChanged(RectF rect);
}
/**
* Interface definition for a callback to be invoked when the Photo is
* tapped with a single tap.
*
* @author Chris Banes
*/
public static interface OnPhotoTapListener {
/**
* A callback to receive where the user taps on a photo. You will only
* receive a callback if the user taps on the actual photo, tapping on
* 'whitespace' will be ignored.
*
* @param view
* - View the user tapped.
* @param x
* - where the user tapped from the of the Drawable, as
* percentage of the Drawable width.
* @param y
* - where the user tapped from the top of the Drawable, as
* percentage of the Drawable height.
*/
void onPhotoTap(View view, float x, float y);
}
/**
* Interface definition for a callback to be invoked when the ImageView is
* tapped with a single tap.
*
* @author Chris Banes
*/
public static interface OnViewTapListener {
/**
* A callback to receive where the user taps on a ImageView. You will
* receive a callback if the user taps anywhere on the view, tapping on
* 'whitespace' will not be ignored.
*
* @param view
* - View the user tapped.
* @param x
* - where the user tapped from the left of the View.
* @param y
* - where the user tapped from the top of the View.
*/
void onViewTap(View view, float x, float y);
}
private class AnimatedZoomRunnable implements Runnable {
// These are 'postScale' values, means they're compounded each iteration
static final float ANIMATION_SCALE_PER_ITERATION_IN = 1.07f;
static final float ANIMATION_SCALE_PER_ITERATION_OUT = 0.93f;
private final float mFocalX, mFocalY;
private final float mTargetZoom;
private final float mDeltaScale;
public AnimatedZoomRunnable(final float currentZoom, final float targetZoom, final float focalX,
final float focalY) {
mTargetZoom = targetZoom;
mFocalX = focalX;
mFocalY = focalY;
if (currentZoom < targetZoom) {
mDeltaScale = ANIMATION_SCALE_PER_ITERATION_IN;
} else {
mDeltaScale = ANIMATION_SCALE_PER_ITERATION_OUT;
}
}
public void run() {
ImageView imageView = getImageView();
if (null != imageView) {
mSuppMatrix.postScale(mDeltaScale, mDeltaScale, mFocalX, mFocalY);
checkAndDisplayMatrix();
final float currentScale = getScale();
if ((mDeltaScale > 1f && currentScale < mTargetZoom)
|| (mDeltaScale < 1f && mTargetZoom < currentScale)) {
// We haven't hit our target scale yet, so post ourselves
// again
Compat.postOnAnimation(imageView, this);
} else {
// We've scaled past our target zoom, so calculate the
// necessary scale so we're back at target zoom
final float delta = mTargetZoom / currentScale;
mSuppMatrix.postScale(delta, delta, mFocalX, mFocalY);
checkAndDisplayMatrix();
}
}
}
}
private class FlingRunnable implements Runnable {
private final ScrollerProxy mScroller;
private int mCurrentX, mCurrentY;
public FlingRunnable(Context context) {
mScroller = ScrollerProxy.getScroller(context);
}
public void cancelFling() {
if (DEBUG) {
Log.d(LOG_TAG, "Cancel Fling");
}
mScroller.forceFinished(true);
}
public void fling(int viewWidth, int viewHeight, int velocityX, int velocityY) {
final RectF rect = getDisplayRect();
if (null == rect) {
return;
}
final int startX = Math.round(-rect.left);
final int minX, maxX, minY, maxY;
if (viewWidth < rect.width()) {
minX = 0;
maxX = Math.round(rect.width() - viewWidth);
} else {
minX = maxX = startX;
}
final int startY = Math.round(-rect.top);
if (viewHeight < rect.height()) {
minY = 0;
maxY = Math.round(rect.height() - viewHeight);
} else {
minY = maxY = startY;
}
mCurrentX = startX;
mCurrentY = startY;
if (DEBUG) {
Log.d(LOG_TAG, "fling. StartX:" + startX + " StartY:" + startY + " MaxX:" + maxX + " MaxY:" + maxY);
}
// If we actually can move, fling the scroller
if (startX != maxX || startY != maxY) {
mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, 0, 0);
}
}
@Override
public void run() {
ImageView imageView = getImageView();
if (null != imageView && mScroller.computeScrollOffset()) {
final int newX = mScroller.getCurrX();
final int newY = mScroller.getCurrY();
if (DEBUG) {
Log.d(LOG_TAG, "fling run(). CurrentX:" + mCurrentX + " CurrentY:" + mCurrentY + " NewX:" + newX
+ " NewY:" + newY);
}
mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY);
setImageViewMatrix(getDisplayMatrix());
mCurrentX = newX;
mCurrentY = newY;
// Post On animation
Compat.postOnAnimation(imageView, this);
}
}
}
@Override
public float getMidScale() {
return 0;
}
@Override
public void setMidScale(float midScale) {
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/photoview/SDK16.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.htmessage.yichatopen.widget.photoview;
import android.annotation.TargetApi;
import android.view.View;
@TargetApi(16)
class SDK16 {
public static void postOnAnimation(View view, Runnable r) {
view.postOnAnimation(r);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/photoview/ScrollerProxy.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.htmessage.yichatopen.widget.photoview;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.widget.OverScroller;
import android.widget.Scroller;
abstract class ScrollerProxy {
public static ScrollerProxy getScroller(Context context) {
if (VERSION.SDK_INT < VERSION_CODES.GINGERBREAD) {
return new PreGingerScroller(context);
} else {
return new GingerScroller(context);
}
}
public abstract boolean computeScrollOffset();
public abstract void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY,
int maxY, int overX, int overY);
public abstract void forceFinished(boolean finished);
public abstract int getCurrX();
public abstract int getCurrY();
@TargetApi(9)
private static class GingerScroller extends ScrollerProxy {
private OverScroller mScroller;
public GingerScroller(Context context) {
mScroller = new OverScroller(context);
}
@Override
public boolean computeScrollOffset() {
return mScroller.computeScrollOffset();
}
@Override
public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
int overX, int overY) {
mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY);
}
@Override
public void forceFinished(boolean finished) {
mScroller.forceFinished(finished);
}
@Override
public int getCurrX() {
return mScroller.getCurrX();
}
@Override
public int getCurrY() {
return mScroller.getCurrY();
}
}
private static class PreGingerScroller extends ScrollerProxy {
private Scroller mScroller;
public PreGingerScroller(Context context) {
mScroller = new Scroller(context);
}
@Override
public boolean computeScrollOffset() {
return mScroller.computeScrollOffset();
}
@Override
public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
int overX, int overY) {
mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);
}
@Override
public void forceFinished(boolean finished) {
mScroller.forceFinished(finished);
}
@Override
public int getCurrX() {
return mScroller.getCurrX();
}
@Override
public int getCurrY() {
return mScroller.getCurrY();
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/photoview/VersionedGestureDetector.java
================================================
/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.photoview;
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
abstract class VersionedGestureDetector {
static final String LOG_TAG = "VersionedGestureDetector";
OnGestureListener mListener;
public static VersionedGestureDetector newInstance(Context context, OnGestureListener listener) {
final int sdkVersion = Build.VERSION.SDK_INT;
VersionedGestureDetector detector = null;
if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
detector = new CupcakeDetector(context);
} else if (sdkVersion < Build.VERSION_CODES.FROYO) {
detector = new EclairDetector(context);
} else {
detector = new FroyoDetector(context);
}
detector.mListener = listener;
return detector;
}
public abstract boolean onTouchEvent(MotionEvent ev);
public abstract boolean isScaling();
public static interface OnGestureListener {
public void onDrag(float dx, float dy);
public void onFling(float startX, float startY, float velocityX, float velocityY);
public void onScale(float scaleFactor, float focusX, float focusY);
}
private static class CupcakeDetector extends VersionedGestureDetector {
float mLastTouchX;
float mLastTouchY;
final float mTouchSlop;
final float mMinimumVelocity;
public CupcakeDetector(Context context) {
final ViewConfiguration configuration = ViewConfiguration.get(context);
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mTouchSlop = configuration.getScaledTouchSlop();
}
private VelocityTracker mVelocityTracker;
private boolean mIsDragging;
float getActiveX(MotionEvent ev) {
return ev.getX();
}
float getActiveY(MotionEvent ev) {
return ev.getY();
}
public boolean isScaling() {
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(ev);
mLastTouchX = getActiveX(ev);
mLastTouchY = getActiveY(ev);
mIsDragging = false;
break;
}
case MotionEvent.ACTION_MOVE: {
final float x = getActiveX(ev);
final float y = getActiveY(ev);
final float dx = x - mLastTouchX, dy = y - mLastTouchY;
if (!mIsDragging) {
// Use Pythagoras to see if drag length is larger than
// touch slop
mIsDragging = Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
}
if (mIsDragging) {
mListener.onDrag(dx, dy);
mLastTouchX = x;
mLastTouchY = y;
if (null != mVelocityTracker) {
mVelocityTracker.addMovement(ev);
}
}
break;
}
case MotionEvent.ACTION_CANCEL: {
// Recycle Velocity Tracker
if (null != mVelocityTracker) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
break;
}
case MotionEvent.ACTION_UP: {
if (mIsDragging) {
if (null != mVelocityTracker) {
mLastTouchX = getActiveX(ev);
mLastTouchY = getActiveY(ev);
// Compute velocity within the last 1000ms
mVelocityTracker.addMovement(ev);
mVelocityTracker.computeCurrentVelocity(1000);
final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker.getYVelocity();
// If the velocity is greater than minVelocity, call
// listener
if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {
mListener.onFling(mLastTouchX, mLastTouchY, -vX, -vY);
}
}
}
// Recycle Velocity Tracker
if (null != mVelocityTracker) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
break;
}
}
return true;
}
}
@TargetApi(5)
private static class EclairDetector extends CupcakeDetector {
private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private int mActivePointerIndex = 0;
public EclairDetector(Context context) {
super(context);
}
@Override
float getActiveX(MotionEvent ev) {
try {
return ev.getX(mActivePointerIndex);
} catch (Exception e) {
return ev.getX();
}
}
@Override
float getActiveY(MotionEvent ev) {
try {
return ev.getY(mActivePointerIndex);
} catch (Exception e) {
return ev.getY();
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = ev.getPointerId(0);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mActivePointerId = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = ev.getPointerId(newPointerIndex);
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
}
break;
}
mActivePointerIndex = ev.findPointerIndex(mActivePointerId != INVALID_POINTER_ID ? mActivePointerId : 0);
return super.onTouchEvent(ev);
}
}
@TargetApi(8)
private static class FroyoDetector extends EclairDetector {
private final ScaleGestureDetector mDetector;
// Needs to be an inner class so that we don't hit
// VerifyError's on API 4.
private final OnScaleGestureListener mScaleListener = new OnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mListener.onScale(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY());
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
// NO-OP
}
};
public FroyoDetector(Context context) {
super(context);
mDetector = new ScaleGestureDetector(context, mScaleListener);
}
@Override
public boolean isScaling() {
return mDetector.isInProgress();
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
mDetector.onTouchEvent(ev);
return super.onTouchEvent(ev);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/scan/CameraConfigurationManager.java
================================================
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.scan;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
/**
*
* 邮箱: 1076559197@qq.com | tauchen1990@gmail.com
*
* 作者: 陈涛
*
* 日期: 2014年8月20日
*
* 描述: 该类主要负责设置相机的参数信息,获取最佳的预览界面
*
*/
public final class CameraConfigurationManager {
private static final String TAG = "CameraConfiguration";
private static final int MIN_PREVIEW_PIXELS = 480 * 320;
private static final double MAX_ASPECT_DISTORTION = 0.15;
private final Context context;
// 屏幕分辨率
private Point screenResolution;
// 相机分辨率
private Point cameraResolution;
public CameraConfigurationManager(Context context) {
this.context = context;
}
public void initFromCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
Point theScreenResolution = new Point();
theScreenResolution = getDisplaySize(display);
screenResolution = theScreenResolution;
Log.i(TAG, "Screen resolution: " + screenResolution);
/** 因为换成了竖屏显示,所以不替换屏幕宽高得出的预览图是变形的 */
Point screenResolutionForCamera = new Point();
screenResolutionForCamera.x = screenResolution.x;
screenResolutionForCamera.y = screenResolution.y;
if (screenResolution.x < screenResolution.y) {
screenResolutionForCamera.x = screenResolution.y;
screenResolutionForCamera.y = screenResolution.x;
}
cameraResolution = findBestPreviewSizeValue(parameters, screenResolutionForCamera);
Log.i(TAG, "Camera resolution x: " + cameraResolution.x);
Log.i(TAG, "Camera resolution y: " + cameraResolution.y);
}
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private Point getDisplaySize(final Display display) {
final Point point = new Point();
try {
display.getSize(point);
} catch (NoSuchMethodError ignore) {
point.x = display.getWidth();
point.y = display.getHeight();
}
return point;
}
public void setDesiredCameraParameters(Camera camera, boolean safeMode) {
Camera.Parameters parameters = camera.getParameters();
if (parameters == null) {
Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration.");
return;
}
Log.i(TAG, "Initial camera parameters: " + parameters.flatten());
if (safeMode) {
Log.w(TAG, "In camera config safe mode -- most settings will not be honored");
}
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
camera.setParameters(parameters);
Camera.Parameters afterParameters = camera.getParameters();
Camera.Size afterSize = afterParameters.getPreviewSize();
if (afterSize != null && (cameraResolution.x != afterSize.width || cameraResolution.y != afterSize.height)) {
Log.w(TAG, "Camera said it supported preview size " + cameraResolution.x + 'x' + cameraResolution.y + ", but after setting it, preview size is " + afterSize.width + 'x' + afterSize.height);
cameraResolution.x = afterSize.width;
cameraResolution.y = afterSize.height;
}
/** 设置相机预览为竖屏 */
camera.setDisplayOrientation(90);
}
public Point getCameraResolution() {
return cameraResolution;
}
public Point getScreenResolution() {
return screenResolution;
}
/**
* 从相机支持的分辨率中计算出最适合的预览界面尺寸
*
* @param parameters
* @param screenResolution
* @return
*/
private Point findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution) {
List rawSupportedSizes = parameters.getSupportedPreviewSizes();
if (rawSupportedSizes == null) {
Log.w(TAG, "Device returned no supported preview sizes; using default");
Camera.Size defaultSize = parameters.getPreviewSize();
return new Point(defaultSize.width, defaultSize.height);
}
// Sort by size, descending
List supportedPreviewSizes = new ArrayList(rawSupportedSizes);
Collections.sort(supportedPreviewSizes, new Comparator() {
@Override
public int compare(Camera.Size a, Camera.Size b) {
int aPixels = a.height * a.width;
int bPixels = b.height * b.width;
if (bPixels < aPixels) {
return -1;
}
if (bPixels > aPixels) {
return 1;
}
return 0;
}
});
if (Log.isLoggable(TAG, Log.INFO)) {
StringBuilder previewSizesString = new StringBuilder();
for (Camera.Size supportedPreviewSize : supportedPreviewSizes) {
previewSizesString.append(supportedPreviewSize.width).append('x').append(supportedPreviewSize.height).append(' ');
}
Log.i(TAG, "Supported preview sizes: " + previewSizesString);
}
double screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;
// Remove sizes that are unsuitable
Iterator it = supportedPreviewSizes.iterator();
while (it.hasNext()) {
Camera.Size supportedPreviewSize = it.next();
int realWidth = supportedPreviewSize.width;
int realHeight = supportedPreviewSize.height;
if (realWidth * realHeight < MIN_PREVIEW_PIXELS) {
it.remove();
continue;
}
boolean isCandidatePortrait = realWidth < realHeight;
int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth;
int maybeFlippedHeight = isCandidatePortrait ? realWidth : realHeight;
double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;
double distortion = Math.abs(aspectRatio - screenAspectRatio);
if (distortion > MAX_ASPECT_DISTORTION) {
it.remove();
continue;
}
if (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {
Point exactPoint = new Point(realWidth, realHeight);
Log.i(TAG, "Found preview size exactly matching screen size: " + exactPoint);
return exactPoint;
}
}
// If no exact match, use largest preview size. This was not a great
// idea on older devices because
// of the additional computation needed. We're likely to get here on
// newer Android 4+ devices, where
// the CPU is much more powerful.
if (!supportedPreviewSizes.isEmpty()) {
Camera.Size largestPreview = supportedPreviewSizes.get(0);
Point largestSize = new Point(largestPreview.width, largestPreview.height);
Log.i(TAG, "Using largest suitable preview size: " + largestSize);
return largestSize;
}
// If there is nothing at all suitable, return current preview size
Camera.Size defaultPreview = parameters.getPreviewSize();
Point defaultSize = new Point(defaultPreview.width, defaultPreview.height);
Log.i(TAG, "No suitable preview sizes, using default: " + defaultSize);
return defaultSize;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/scan/CameraManager.java
================================================
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.scan;
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.util.Log;
import java.io.IOException;
/**
*
* 邮箱: 1076559197@qq.com | tauchen1990@gmail.com
*
* 作者: 陈涛
*
* 日期: 2014年8月20日
*
* 描述: 该类主要负责对相机的操作
*
*/
public final class CameraManager {
private static final String TAG = CameraManager.class.getSimpleName();
private final CameraConfigurationManager configManager;
private Camera camera;
private boolean initialized;
public CameraManager(Context context) {
this.configManager = new CameraConfigurationManager(context);
}
/**
* Opens the camera driver and initializes the hardware parameters.
*
* @param
* The surface object which the camera will draw preview frames
* into.
* @throws IOException
* Indicates the camera driver failed to open.
*/
public synchronized void openDriver() throws IOException {
Camera theCamera = camera;
if (theCamera == null) {
theCamera = Camera.open();
if (theCamera == null) {
throw new IOException();
}
camera = theCamera;
}
if (!initialized) {
initialized = true;
configManager.initFromCameraParameters(theCamera);
}
Camera.Parameters parameters = theCamera.getParameters();
String parametersFlattened = parameters == null ? null : parameters.flatten(); // Save
// these,
// temporarily
try {
configManager.setDesiredCameraParameters(theCamera, false);
} catch (RuntimeException re) {
// Driver failed
Log.w(TAG, "Camera rejected parameters. Setting only minimal safe-mode parameters");
Log.i(TAG, "Resetting to saved camera params: " + parametersFlattened);
// Reset:
if (parametersFlattened != null) {
parameters = theCamera.getParameters();
parameters.unflatten(parametersFlattened);
try {
theCamera.setParameters(parameters);
configManager.setDesiredCameraParameters(theCamera, true);
} catch (RuntimeException re2) {
// Well, darn. Give up
Log.w(TAG, "Camera rejected even safe-mode parameters! No configuration");
}
}
}
}
public synchronized boolean isOpen() {
return camera != null;
}
public Camera getCamera(){
return camera;
}
/**
* Closes the camera driver if still in use.
*/
public synchronized void closeDriver() {
if (camera != null) {
camera.release();
camera = null;
}
}
/**
* 获取相机分辨率
*
* @return
*/
public Point getCameraResolution() {
return configManager.getCameraResolution();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/scan/CameraPreview.java
================================================
/*
* Barebones implementation of displaying camera preview.
*
* Created by lisah0 on 2012-02-24
*/
package com.htmessage.yichatopen.widget.scan;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private PreviewCallback previewCallback;
private AutoFocusCallback autoFocusCallback;
@SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera, PreviewCallback previewCb, AutoFocusCallback autoFocusCb) {
super(context);
mCamera = camera;
previewCallback = previewCb;
autoFocusCallback = autoFocusCb;
/*
* Set camera to continuous focus if supported, otherwise use software
* auto-focus. Only works for API level >=9.
*/
/*
* Camera.Parameters parameters = camera.getParameters(); for (String f
* : parameters.getSupportedFocusModes()) { if (f ==
* Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
* mCamera.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
* autoFocusCallback = null; break; } }
*/
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the
// preview.
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.d("DBG", "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Camera preview released in activity
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
/*
* If your preview can change or rotate, take care of those events here.
* Make sure to stop the preview before resizing or reformatting it.
*/
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
try {
// Hard code camera surface rotation 90 degs to match Activity view
// in portrait
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewCallback(previewCallback);
mCamera.startPreview();
mCamera.autoFocus(autoFocusCallback);
} catch (Exception e) {
Log.d("DBG", "Error starting camera preview: " + e.getMessage());
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/swipyrefresh/CircleImageView.java
================================================
package com.htmessage.yichatopen.widget.swipyrefresh;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.support.v4.view.ViewCompat;
import android.view.animation.Animation;
import android.widget.ImageView;
/**
* Private class created to work around issues with AnimationListeners being
* called before the animation is actually complete and support shadows on older
* platforms.
*
* @hide
*/
class CircleImageView extends ImageView {
private static final int KEY_SHADOW_COLOR = 0x1E000000;
private static final int FILL_SHADOW_COLOR = 0x3D000000;
// PX
private static final float X_OFFSET = 0f;
private static final float Y_OFFSET = 1.75f;
private static final float SHADOW_RADIUS = 3.5f;
private static final int SHADOW_ELEVATION = 4;
private Animation.AnimationListener mListener;
private int mShadowRadius;
public CircleImageView(Context context, int color, final float radius) {
super(context);
final float density = getContext().getResources().getDisplayMetrics().density;
final int diameter = (int) (radius * density * 2);
final int shadowYOffset = (int) (density * Y_OFFSET);
final int shadowXOffset = (int) (density * X_OFFSET);
mShadowRadius = (int) (density * SHADOW_RADIUS);
ShapeDrawable circle;
if (elevationSupported()) {
circle = new ShapeDrawable(new OvalShape());
ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
} else {
OvalShape oval = new OvalShadow(mShadowRadius, diameter);
circle = new ShapeDrawable(oval);
ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE,
circle.getPaint());
circle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset,
shadowYOffset, KEY_SHADOW_COLOR);
final int padding = (int) mShadowRadius;
// set padding so the inner image sits correctly within the shadow.
setPadding(padding, padding, padding, padding);
}
circle.getPaint().setColor(color);
setBackgroundDrawable(circle);
}
private boolean elevationSupported() {
return android.os.Build.VERSION.SDK_INT >= 21;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!elevationSupported()) {
setMeasuredDimension(getMeasuredWidth() + mShadowRadius * 2,
getMeasuredHeight() + mShadowRadius * 2);
}
}
public void setAnimationListener(Animation.AnimationListener listener) {
mListener = listener;
}
@Override
public void onAnimationStart() {
super.onAnimationStart();
if (mListener != null) {
mListener.onAnimationStart(getAnimation());
}
}
@Override
public void onAnimationEnd() {
super.onAnimationEnd();
if (mListener != null) {
mListener.onAnimationEnd(getAnimation());
}
}
/**
* Update the background color of the circle image view.
*/
@SuppressWarnings("ResourceType")
public void setBackgroundColor(int colorRes) {
if (getBackground() instanceof ShapeDrawable) {
final Resources res = getResources();
((ShapeDrawable) getBackground()).getPaint().setColor(
res.getColor(colorRes));
}
}
private class OvalShadow extends OvalShape {
private RadialGradient mRadialGradient;
private int mShadowRadius;
private Paint mShadowPaint;
private int mCircleDiameter;
public OvalShadow(int shadowRadius, int circleDiameter) {
super();
mShadowPaint = new Paint();
mShadowRadius = shadowRadius;
mCircleDiameter = circleDiameter;
mRadialGradient = new RadialGradient(mCircleDiameter / 2,
mCircleDiameter / 2, mShadowRadius, new int[] {
FILL_SHADOW_COLOR, Color.TRANSPARENT }, null,
Shader.TileMode.CLAMP);
mShadowPaint.setShader(mRadialGradient);
}
@Override
public void draw(Canvas canvas, Paint paint) {
final int viewWidth = CircleImageView.this.getWidth();
final int viewHeight = CircleImageView.this.getHeight();
canvas.drawCircle(viewWidth / 2, viewHeight / 2,
(mCircleDiameter / 2 + mShadowRadius), mShadowPaint);
canvas.drawCircle(viewWidth / 2, viewHeight / 2,
(mCircleDiameter / 2), paint);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/swipyrefresh/MaterialProgressDrawable.java
================================================
package com.htmessage.yichatopen.widget.swipyrefresh;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
/**
* Fancy progress indicator for Material theme.
*
* @hide
*/
class MaterialProgressDrawable extends Drawable implements Animatable {
private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
private static final Interpolator END_CURVE_INTERPOLATOR = new EndCurveInterpolator();
private static final Interpolator START_CURVE_INTERPOLATOR = new StartCurveInterpolator();
private static final Interpolator EASE_INTERPOLATOR = new AccelerateDecelerateInterpolator();
@Retention(RetentionPolicy.CLASS)
@IntDef({LARGE, DEFAULT})
public @interface ProgressDrawableSize {}
// Maps to ProgressBar.Large style
static final int LARGE = 0;
// Maps to ProgressBar default style
static final int DEFAULT = 1;
// Maps to ProgressBar default style
private static final int CIRCLE_DIAMETER = 40;
private static final float CENTER_RADIUS = 8.75f; //should add up to 10 when + stroke_width
private static final float STROKE_WIDTH = 2.5f;
// Maps to ProgressBar.Large style
private static final int CIRCLE_DIAMETER_LARGE = 56;
private static final float CENTER_RADIUS_LARGE = 12.5f;
private static final float STROKE_WIDTH_LARGE = 3f;
private final int[] COLORS = new int[] {
Color.BLACK
};
/** The duration of a single progress spin in milliseconds. */
private static final int ANIMATION_DURATION = 1000 * 80 / 60;
/** The number of points in the progress "star". */
private static final float NUM_POINTS = 5f;
/** The list of animators operating on this drawable. */
private final ArrayList mAnimators = new ArrayList();
/** The indicator ring, used to manage animation state. */
private final Ring mRing;
/** Canvas rotation in degrees. */
private float mRotation;
/** Layout info for the arrowhead in dp */
private static final int ARROW_WIDTH = 10;
private static final int ARROW_HEIGHT = 5;
private static final float ARROW_OFFSET_ANGLE = 5;
/** Layout info for the arrowhead for the large spinner in dp */
private static final int ARROW_WIDTH_LARGE = 12;
private static final int ARROW_HEIGHT_LARGE = 6;
private static final float MAX_PROGRESS_ARC = .8f;
private Resources mResources;
private View mParent;
private Animation mAnimation;
private float mRotationCount;
private double mWidth;
private double mHeight;
private Animation mFinishAnimation;
public MaterialProgressDrawable(Context context, View parent) {
mParent = parent;
mResources = context.getResources();
mRing = new Ring(mCallback);
mRing.setColors(COLORS);
updateSizes(DEFAULT);
setupAnimators();
}
private void setSizeParameters(double progressCircleWidth, double progressCircleHeight,
double centerRadius, double strokeWidth, float arrowWidth, float arrowHeight) {
final Ring ring = mRing;
final DisplayMetrics metrics = mResources.getDisplayMetrics();
final float screenDensity = metrics.density;
mWidth = progressCircleWidth * screenDensity;
mHeight = progressCircleHeight * screenDensity;
ring.setStrokeWidth((float) strokeWidth * screenDensity);
ring.setCenterRadius(centerRadius * screenDensity);
ring.setColorIndex(0);
ring.setArrowDimensions(arrowWidth * screenDensity, arrowHeight * screenDensity);
ring.setInsets((int) mWidth, (int) mHeight);
}
/**
* Set the overall size for the progress spinner. This updates the radius
* and stroke width of the ring.
*
* @param size One of {@link com.orangegangsters.github.swiperefreshlayout.MaterialProgressDrawable.LARGE} or
* {@link com.orangegangsters.github.swiperefreshlayout.MaterialProgressDrawable.DEFAULT}
*/
public void updateSizes(@ProgressDrawableSize int size) {
if (size == LARGE) {
setSizeParameters(CIRCLE_DIAMETER_LARGE, CIRCLE_DIAMETER_LARGE, CENTER_RADIUS_LARGE,
STROKE_WIDTH_LARGE, ARROW_WIDTH_LARGE, ARROW_HEIGHT_LARGE);
} else {
setSizeParameters(CIRCLE_DIAMETER, CIRCLE_DIAMETER, CENTER_RADIUS, STROKE_WIDTH,
ARROW_WIDTH, ARROW_HEIGHT);
}
}
/**
* @param show Set to true to display the arrowhead on the progress spinner.
*/
public void showArrow(boolean show) {
mRing.setShowArrow(show);
}
/**
* @param scale Set the scale of the arrowhead for the spinner.
*/
public void setArrowScale(float scale) {
mRing.setArrowScale(scale);
}
/**
* Set the start and end trim for the progress spinner arc.
*
* @param startAngle start angle
* @param endAngle end angle
*/
public void setStartEndTrim(float startAngle, float endAngle) {
mRing.setStartTrim(startAngle);
mRing.setEndTrim(endAngle);
}
/**
* Set the amount of rotation to apply to the progress spinner.
*
* @param rotation Rotation is from [0..1]
*/
public void setProgressRotation(float rotation) {
mRing.setRotation(rotation);
}
/**
* Update the background color of the circle image view.
*/
public void setBackgroundColor(int color) {
mRing.setBackgroundColor(color);
}
/**
* Set the colors used in the progress animation from color resources.
* The first color will also be the color of the bar that grows in response
* to a user swipe gesture.
*
* @param colors
*/
public void setColorSchemeColors(int... colors) {
mRing.setColors(colors);
mRing.setColorIndex(0);
}
@Override
public int getIntrinsicHeight() {
return (int) mHeight;
}
@Override
public int getIntrinsicWidth() {
return (int) mWidth;
}
@Override
public void draw(Canvas c) {
final Rect bounds = getBounds();
final int saveCount = c.save();
c.rotate(mRotation, bounds.exactCenterX(), bounds.exactCenterY());
mRing.draw(c, bounds);
c.restoreToCount(saveCount);
}
@Override
public void setAlpha(int alpha) {
mRing.setAlpha(alpha);
}
public int getAlpha() {
return mRing.getAlpha();
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
mRing.setColorFilter(colorFilter);
}
@SuppressWarnings("unused")
void setRotation(float rotation) {
mRotation = rotation;
invalidateSelf();
}
@SuppressWarnings("unused")
private float getRotation() {
return mRotation;
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public boolean isRunning() {
final ArrayList animators = mAnimators;
final int N = animators.size();
for (int i = 0; i < N; i++) {
final Animation animator = animators.get(i);
if (animator.hasStarted() && !animator.hasEnded()) {
return true;
}
}
return false;
}
@Override
public void start() {
mAnimation.reset();
mRing.storeOriginals();
// Already showing some part of the ring
if (mRing.getEndTrim() != mRing.getStartTrim()) {
mParent.startAnimation(mFinishAnimation);
} else {
mRing.setColorIndex(0);
mRing.resetOriginals();
mParent.startAnimation(mAnimation);
}
}
@Override
public void stop() {
mParent.clearAnimation();
setRotation(0);
mRing.setShowArrow(false);
mRing.setColorIndex(0);
mRing.resetOriginals();
}
private void setupAnimators() {
final Ring ring = mRing;
final Animation finishRingAnimation = new Animation() {
public void applyTransformation(float interpolatedTime, Transformation t) {
// shrink back down and complete a full rotation before starting other circles
// Rotation goes between [0..1].
float targetRotation = (float) (Math.floor(ring.getStartingRotation()
/ MAX_PROGRESS_ARC) + 1f);
final float startTrim = ring.getStartingStartTrim()
+ (ring.getStartingEndTrim() - ring.getStartingStartTrim())
* interpolatedTime;
ring.setStartTrim(startTrim);
final float rotation = ring.getStartingRotation()
+ ((targetRotation - ring.getStartingRotation()) * interpolatedTime);
ring.setRotation(rotation);
ring.setArrowScale(1 - interpolatedTime);
}
};
finishRingAnimation.setInterpolator(EASE_INTERPOLATOR);
finishRingAnimation.setDuration(ANIMATION_DURATION/2);
finishRingAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
ring.goToNextColor();
ring.storeOriginals();
ring.setShowArrow(false);
mParent.startAnimation(mAnimation);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
final Animation animation = new Animation() {
@Override
public void applyTransformation(float interpolatedTime, Transformation t) {
// The minProgressArc is calculated from 0 to create an angle that
// matches the stroke width.
final float minProgressArc = (float) Math.toRadians(ring.getStrokeWidth()
/ (2 * Math.PI * ring.getCenterRadius()));
final float startingEndTrim = ring.getStartingEndTrim();
final float startingTrim = ring.getStartingStartTrim();
final float startingRotation = ring.getStartingRotation();
// Offset the minProgressArc to where the endTrim is located.
final float minArc = MAX_PROGRESS_ARC - minProgressArc;
final float endTrim = startingEndTrim
+ (minArc * START_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime));
ring.setEndTrim(endTrim);
final float startTrim = startingTrim
+ (MAX_PROGRESS_ARC * END_CURVE_INTERPOLATOR
.getInterpolation(interpolatedTime));
ring.setStartTrim(startTrim);
final float rotation = startingRotation + (0.25f * interpolatedTime);
ring.setRotation(rotation);
float groupRotation = ((720.0f / NUM_POINTS) * interpolatedTime)
+ (720.0f * (mRotationCount / NUM_POINTS));
setRotation(groupRotation);
}
};
animation.setRepeatCount(Animation.INFINITE);
animation.setRepeatMode(Animation.RESTART);
animation.setInterpolator(LINEAR_INTERPOLATOR);
animation.setDuration(ANIMATION_DURATION);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
mRotationCount = 0;
}
@Override
public void onAnimationEnd(Animation animation) {
// do nothing
}
@Override
public void onAnimationRepeat(Animation animation) {
ring.storeOriginals();
ring.goToNextColor();
ring.setStartTrim(ring.getEndTrim());
mRotationCount = (mRotationCount + 1) % (NUM_POINTS);
}
});
mFinishAnimation = finishRingAnimation;
mAnimation = animation;
}
private final Callback mCallback = new Callback() {
@Override
public void invalidateDrawable(Drawable d) {
invalidateSelf();
}
@Override
public void scheduleDrawable(Drawable d, Runnable what, long when) {
scheduleSelf(what, when);
}
@Override
public void unscheduleDrawable(Drawable d, Runnable what) {
unscheduleSelf(what);
}
};
private static class Ring {
private final RectF mTempBounds = new RectF();
private final Paint mPaint = new Paint();
private final Paint mArrowPaint = new Paint();
private final Callback mCallback;
private float mStartTrim = 0.0f;
private float mEndTrim = 0.0f;
private float mRotation = 0.0f;
private float mStrokeWidth = 5.0f;
private float mStrokeInset = 2.5f;
private int[] mColors;
// mColorIndex represents the offset into the available mColors that the
// progress circle should currently display. As the progress circle is
// animating, the mColorIndex moves by one to the next available color.
private int mColorIndex;
private float mStartingStartTrim;
private float mStartingEndTrim;
private float mStartingRotation;
private boolean mShowArrow;
private Path mArrow;
private float mArrowScale;
private double mRingCenterRadius;
private int mArrowWidth;
private int mArrowHeight;
private int mAlpha;
private final Paint mCirclePaint = new Paint();
private int mBackgroundColor;
public Ring(Callback callback) {
mCallback = callback;
mPaint.setStrokeCap(Paint.Cap.SQUARE);
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.STROKE);
mArrowPaint.setStyle(Style.FILL);
mArrowPaint.setAntiAlias(true);
}
public void setBackgroundColor(int color) {
mBackgroundColor = color;
}
/**
* Set the dimensions of the arrowhead.
*
* @param width Width of the hypotenuse of the arrow head
* @param height Height of the arrow point
*/
public void setArrowDimensions(float width, float height) {
mArrowWidth = (int) width;
mArrowHeight = (int) height;
}
/**
* Draw the progress spinner
*/
public void draw(Canvas c, Rect bounds) {
final RectF arcBounds = mTempBounds;
arcBounds.set(bounds);
arcBounds.inset(mStrokeInset, mStrokeInset);
final float startAngle = (mStartTrim + mRotation) * 360;
final float endAngle = (mEndTrim + mRotation) * 360;
float sweepAngle = endAngle - startAngle;
mPaint.setColor(mColors[mColorIndex]);
c.drawArc(arcBounds, startAngle, sweepAngle, false, mPaint);
drawTriangle(c, startAngle, sweepAngle, bounds);
if (mAlpha < 255) {
mCirclePaint.setColor(mBackgroundColor);
mCirclePaint.setAlpha(255 - mAlpha);
c.drawCircle(bounds.exactCenterX(), bounds.exactCenterY(), bounds.width() / 2,
mCirclePaint);
}
}
private void drawTriangle(Canvas c, float startAngle, float sweepAngle, Rect bounds) {
if (mShowArrow) {
if (mArrow == null) {
mArrow = new Path();
mArrow.setFillType(Path.FillType.EVEN_ODD);
} else {
mArrow.reset();
}
// Adjust the position of the triangle so that it is inset as
// much as the arc, but also centered on the arc.
float inset = (int) mStrokeInset / 2 * mArrowScale;
float x = (float) (mRingCenterRadius * Math.cos(0) + bounds.exactCenterX());
float y = (float) (mRingCenterRadius * Math.sin(0) + bounds.exactCenterY());
// Update the path each time. This works around an issue in SKIA
// where concatenating a rotation matrix to a scale matrix
// ignored a starting negative rotation. This appears to have
// been fixed as of API 21.
mArrow.moveTo(0, 0);
mArrow.lineTo(mArrowWidth * mArrowScale, 0);
mArrow.lineTo((mArrowWidth * mArrowScale / 2), (mArrowHeight
* mArrowScale));
mArrow.offset(x - inset, y);
mArrow.close();
// draw a triangle
mArrowPaint.setColor(mColors[mColorIndex]);
c.rotate(startAngle + sweepAngle - ARROW_OFFSET_ANGLE, bounds.exactCenterX(),
bounds.exactCenterY());
c.drawPath(mArrow, mArrowPaint);
}
}
/**
* Set the colors the progress spinner alternates between.
*
* @param colors Array of integers describing the colors. Must be non-null.
*/
public void setColors(@NonNull int[] colors) {
mColors = colors;
// if colors are reset, make sure to reset the color index as well
setColorIndex(0);
}
/**
* @param index Index into the color array of the color to display in
* the progress spinner.
*/
public void setColorIndex(int index) {
mColorIndex = index;
}
/**
* Proceed to the next available ring color. This will automatically
* wrap back to the beginning of colors.
*/
public void goToNextColor() {
mColorIndex = (mColorIndex + 1) % (mColors.length);
}
public void setColorFilter(ColorFilter filter) {
mPaint.setColorFilter(filter);
invalidateSelf();
}
/**
* @param alpha Set the alpha of the progress spinner and associated arrowhead.
*/
public void setAlpha(int alpha) {
mAlpha = alpha;
}
/**
* @return Current alpha of the progress spinner and arrowhead.
*/
public int getAlpha() {
return mAlpha;
}
/**
* @param strokeWidth Set the stroke width of the progress spinner in pixels.
*/
public void setStrokeWidth(float strokeWidth) {
mStrokeWidth = strokeWidth;
mPaint.setStrokeWidth(strokeWidth);
invalidateSelf();
}
@SuppressWarnings("unused")
public float getStrokeWidth() {
return mStrokeWidth;
}
@SuppressWarnings("unused")
public void setStartTrim(float startTrim) {
mStartTrim = startTrim;
invalidateSelf();
}
@SuppressWarnings("unused")
public float getStartTrim() {
return mStartTrim;
}
public float getStartingStartTrim() {
return mStartingStartTrim;
}
public float getStartingEndTrim() {
return mStartingEndTrim;
}
@SuppressWarnings("unused")
public void setEndTrim(float endTrim) {
mEndTrim = endTrim;
invalidateSelf();
}
@SuppressWarnings("unused")
public float getEndTrim() {
return mEndTrim;
}
@SuppressWarnings("unused")
public void setRotation(float rotation) {
mRotation = rotation;
invalidateSelf();
}
@SuppressWarnings("unused")
public float getRotation() {
return mRotation;
}
public void setInsets(int width, int height) {
final float minEdge = (float) Math.min(width, height);
float insets;
if (mRingCenterRadius <= 0 || minEdge < 0) {
insets = (float) Math.ceil(mStrokeWidth / 2.0f);
} else {
insets = (float) (minEdge / 2.0f - mRingCenterRadius);
}
mStrokeInset = insets;
}
@SuppressWarnings("unused")
public float getInsets() {
return mStrokeInset;
}
/**
* @param centerRadius Inner radius in px of the circle the progress
* spinner arc traces.
*/
public void setCenterRadius(double centerRadius) {
mRingCenterRadius = centerRadius;
}
public double getCenterRadius() {
return mRingCenterRadius;
}
/**
* @param show Set to true to show the arrow head on the progress spinner.
*/
public void setShowArrow(boolean show) {
if (mShowArrow != show) {
mShowArrow = show;
invalidateSelf();
}
}
/**
* @param scale Set the scale of the arrowhead for the spinner.
*/
public void setArrowScale(float scale) {
if (scale != mArrowScale) {
mArrowScale = scale;
invalidateSelf();
}
}
/**
* @return The amount the progress spinner is currently rotated, between [0..1].
*/
public float getStartingRotation() {
return mStartingRotation;
}
/**
* If the start / end trim are offset to begin with, store them so that
* animation starts from that offset.
*/
public void storeOriginals() {
mStartingStartTrim = mStartTrim;
mStartingEndTrim = mEndTrim;
mStartingRotation = mRotation;
}
/**
* Reset the progress spinner to default rotation, start and end angles.
*/
public void resetOriginals() {
mStartingStartTrim = 0;
mStartingEndTrim = 0;
mStartingRotation = 0;
setStartTrim(0);
setEndTrim(0);
setRotation(0);
}
private void invalidateSelf() {
mCallback.invalidateDrawable(null);
}
}
/**
* Squishes the interpolation curve into the second half of the animation.
*/
private static class EndCurveInterpolator extends AccelerateDecelerateInterpolator {
@Override
public float getInterpolation(float input) {
return super.getInterpolation(Math.max(0, (input - 0.5f) * 2.0f));
}
}
/**
* Squishes the interpolation curve into the first half of the animation.
*/
private static class StartCurveInterpolator extends AccelerateDecelerateInterpolator {
@Override
public float getInterpolation(float input) {
return super.getInterpolation(Math.min(1, input * 2.0f));
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/swipyrefresh/SwipyRefreshLayout.java
================================================
package com.htmessage.yichatopen.widget.swipyrefresh;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Build;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Transformation;
import android.widget.AbsListView;
import com.htmessage.yichatopen.R;
/**
* The SwipeRefreshLayout should be used whenever the user can refresh the
* contents of a view via a vertical swipe gesture. The activity that
* instantiates this view should add an OnRefreshListener to be notified
* whenever the swipe to refresh gesture is completed. The SwipeRefreshLayout
* will notify the listener each and every time the gesture is completed again;
* the listener is responsible for correctly determining when to actually
* initiate a refresh of its content. If the listener determines there should
* not be a refresh, it must call setRefreshing(false) to cancel any visual
* indication of a refresh. If an activity wishes to show just the progress
* animation, it should call setRefreshing(true). To disable the gesture and
* progress animation, call setEnabled(false) on the view.
*
* This layout should be made the parent of the view that will be refreshed as a
* result of the gesture and can only support one direct child. This view will
* also be made the target of the gesture and will be forced to match both the
* width and the height supplied in this layout. The SwipeRefreshLayout does not
* provide accessibility events; instead, a menu item must be provided to allow
* refresh of the content wherever this gesture is used.
*
*/
/**
* 下拉刷新、加载更多、分页索引
* @author xutao
*
*/
public class SwipyRefreshLayout extends ViewGroup {
/** 是不是下拉 **/
public boolean isTop;
/** 第一页 **/
public int firstIndex = 0;
/** 页数索引 **/
public int index = firstIndex;
// Maps to ProgressBar.Large style
public static final int LARGE = MaterialProgressDrawable.LARGE;
// Maps to ProgressBar default style
public static final int DEFAULT = MaterialProgressDrawable.DEFAULT;
private static final String LOG_TAG = SwipyRefreshLayout.class.getSimpleName();
private static final int MAX_ALPHA = 255;
private static final int STARTING_PROGRESS_ALPHA = (int) (.3f * MAX_ALPHA);
private static final int CIRCLE_DIAMETER = 40;
private static final int CIRCLE_DIAMETER_LARGE = 56;
private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;
private static final int INVALID_POINTER = -1;
private static final float DRAG_RATE = .5f;
// Max amount of circle that can be filled by progress during swipe gesture,
// where 1.0 is a full circle
private static final float MAX_PROGRESS_ANGLE = .8f;
private static final int SCALE_DOWN_DURATION = 150;
private static final int ALPHA_ANIMATION_DURATION = 300;
private static final int ANIMATE_TO_TRIGGER_DURATION = 200;
private static final int ANIMATE_TO_START_DURATION = 200;
// Default background for the progress spinner
private static final int CIRCLE_BG_LIGHT = 0xFFFAFAFA;
// Default offset in dips from the top of the view to where the progress spinner should stop
private static final int DEFAULT_CIRCLE_TARGET = 64;
private View mTarget; // the target of the gesture
private SwipyRefreshLayoutDirection mDirection;
private boolean mBothDirection;
private OnRefreshListener mListener;
private boolean mRefreshing = false;
private int mTouchSlop;
private float mTotalDragDistance = -1;
private int mMediumAnimationDuration;
private int mCurrentTargetOffsetTop;
// Whether or not the starting offset has been determined.
private boolean mOriginalOffsetCalculated = false;
private float mInitialMotionY;
private boolean mIsBeingDragged;
private int mActivePointerId = INVALID_POINTER;
// Whether this item is scaled up rather than clipped
private boolean mScale;
// Target is returning to its start offset because it was cancelled or a
// refresh was triggered.
private boolean mReturningToStart;
private final DecelerateInterpolator mDecelerateInterpolator;
private static final int[] LAYOUT_ATTRS = new int[]{
android.R.attr.enabled
};
private CircleImageView mCircleView;
private int mCircleViewIndex = -1;
protected int mFrom;
private float mStartingScale;
protected int mOriginalOffsetTop;
private MaterialProgressDrawable mProgress;
private Animation mScaleAnimation;
private Animation mScaleDownAnimation;
private Animation mAlphaStartAnimation;
private Animation mAlphaMaxAnimation;
private Animation mScaleDownToStartAnimation;
private float mSpinnerFinalOffset;
private boolean mNotify;
private int mCircleWidth;
private int mCircleHeight;
// Whether the client has set a custom starting position;
private boolean mUsingCustomStart;
private AnimationListener mRefreshListener = new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (mRefreshing) {
// Make sure the progress view is fully visible
mProgress.setAlpha(MAX_ALPHA);
mProgress.start();
if (mNotify) {
if (mListener != null) {
if (isTop) {
index = firstIndex;
mListener.onRefresh(index);
}else {
index ++;
mListener.onLoad(index);
}
}
}
} else {
mProgress.stop();
mCircleView.setVisibility(View.GONE);
setColorViewAlpha(MAX_ALPHA);
// Return the circle to its start position
if (mScale) {
setAnimationProgress(0 /* animation complete and view is hidden */);
} else {
setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCurrentTargetOffsetTop,
true /* requires update */);
}
}
mCurrentTargetOffsetTop = mCircleView.getTop();
}
};
private void setColorViewAlpha(int targetAlpha) {
mCircleView.getBackground().setAlpha(targetAlpha);
mProgress.setAlpha(targetAlpha);
}
/**
* The refresh indicator starting and resting position is always positioned
* near the top of the refreshing content. This position is a consistent
* location, but can be adjusted in either direction based on whether or not
* there is a toolbar or actionbar present.
*
* @param scale Set to true if there is no view at a higher z-order than
* where the progress spinner is set to appear.
* @param start The offset in pixels from the top of this view at which the
* progress spinner should appear.
* @param end The offset in pixels from the top of this view at which the
* progress spinner should come to rest after a successful swipe
* gesture.
*/
/*
public void setProgressViewOffset(boolean scale, int start, int end) {
mScale = scale;
mCircleView.setVisibility(View.GONE);
mOriginalOffsetTop = mCurrentTargetOffsetTop = start;
mSpinnerFinalOffset = end;
mUsingCustomStart = true;
mCircleView.invalidate();
}*/
/**
* The refresh indicator resting position is always positioned near the top
* of the refreshing content. This position is a consistent location, but
* can be adjusted in either direction based on whether or not there is a
* toolbar or actionbar present.
*
* @param scale Set to true if there is no view at a higher z-order than
* where the progress spinner is set to appear.
* @param end The offset in pixels from the top of this view at which the
* progress spinner should come to rest after a successful swipe
* gesture.
*/
/*
public void setProgressViewEndTarget(boolean scale, int end) {
mSpinnerFinalOffset = end;
mScale = scale;
mCircleView.invalidate();
}*/
/**
* One of DEFAULT, or LARGE.
*/
public void setSize(int size) {
if (size != MaterialProgressDrawable.LARGE && size != MaterialProgressDrawable.DEFAULT) {
return;
}
final DisplayMetrics metrics = getResources().getDisplayMetrics();
if (size == MaterialProgressDrawable.LARGE) {
mCircleHeight = mCircleWidth = (int) (CIRCLE_DIAMETER_LARGE * metrics.density);
} else {
mCircleHeight = mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);
}
// force the bounds of the progress circle inside the circle view to
// update by setting it to null before updating its size and then
// re-setting it
mCircleView.setImageDrawable(null);
mProgress.updateSizes(size);
mCircleView.setImageDrawable(mProgress);
}
/**
* Simple constructor to use when creating a SwipeRefreshLayout from code.
*
* @param context
*/
public SwipyRefreshLayout(Context context) {
this(context, null);
}
/**
* Constructor that is called when inflating SwipeRefreshLayout from XML.
*
* @param context
* @param attrs
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public SwipyRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMediumAnimationDuration = getResources().getInteger(
android.R.integer.config_mediumAnimTime);
setWillNotDraw(false);
mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
setEnabled(a.getBoolean(0, true));
a.recycle();
final TypedArray a2 = context.obtainStyledAttributes(attrs, R.styleable.SwipyRefreshLayout);
SwipyRefreshLayoutDirection direction
= SwipyRefreshLayoutDirection.getFromInt(a2.getInt(R.styleable.SwipyRefreshLayout_direction, 0));
if (direction != SwipyRefreshLayoutDirection.BOTH) {
mDirection = direction;
mBothDirection = false;
} else {
mDirection = SwipyRefreshLayoutDirection.TOP;
mBothDirection = true;
}
a2.recycle();
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);
mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);
createProgressView();
ViewCompat.setChildrenDrawingOrderEnabled(this, true);
// the absolute offset has to take into account that the circle starts at an offset
mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
mTotalDragDistance = mSpinnerFinalOffset;
//设置刷新动画颜色
setColorSchemeResources(android.R.color.holo_blue_light,
android.R.color.holo_red_light,
android.R.color.holo_orange_light,
android.R.color.holo_green_light);
}
protected int getChildDrawingOrder(int childCount, int i) {
if (mCircleViewIndex < 0) {
return i;
} else if (i == childCount - 1) {
// Draw the selected child last
return mCircleViewIndex;
} else if (i >= mCircleViewIndex) {
// Move the children after the selected child earlier one
return i + 1;
} else {
// Keep the children before the selected child the same
return i;
}
}
private void createProgressView() {
mCircleView = new CircleImageView(getContext(), CIRCLE_BG_LIGHT, CIRCLE_DIAMETER / 2);
mProgress = new MaterialProgressDrawable(getContext(), this);
mProgress.setBackgroundColor(CIRCLE_BG_LIGHT);
mCircleView.setImageDrawable(mProgress);
mCircleView.setVisibility(View.GONE);
addView(mCircleView);
}
/**
* Set the listener to be notified when a refresh is triggered via the swipe
* gesture.
*/
public void setOnRefreshListener(OnRefreshListener listener) {
mListener = listener;
}
/**
* Pre API 11, alpha is used to make the progress circle appear instead of scale.
*/
private boolean isAlphaUsedForScale() {
return Build.VERSION.SDK_INT < 11;
}
/**
* Notify the widget that refresh state has changed. Do not call this when
* refresh is triggered by a swipe gesture.
*
* @param refreshing Whether or not the view should show refresh progress.
*/
public void setRefreshing(boolean refreshing) {
if (refreshing && mRefreshing != refreshing) {
// scale and show
mRefreshing = refreshing;
int endTarget = 0;
if (!mUsingCustomStart) {
endTarget = (int) (mSpinnerFinalOffset + mOriginalOffsetTop);
} else {
endTarget = (int) mSpinnerFinalOffset;
}
setTargetOffsetTopAndBottom(endTarget - mCurrentTargetOffsetTop,
true /* requires update */);
mNotify = false;
startScaleUpAnimation(mRefreshListener);
} else {
setRefreshing(refreshing, false /* notify */);
}
}
private void startScaleUpAnimation(AnimationListener listener) {
mCircleView.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= 11) {
// Pre API 11, alpha is used in place of scale up to show the
// progress circle appearing.
// Don't adjust the alpha during appearance otherwise.
mProgress.setAlpha(MAX_ALPHA);
}
mScaleAnimation = new Animation() {
@Override
public void applyTransformation(float interpolatedTime, Transformation t) {
setAnimationProgress(interpolatedTime);
}
};
mScaleAnimation.setDuration(mMediumAnimationDuration);
if (listener != null) {
mCircleView.setAnimationListener(listener);
}
mCircleView.clearAnimation();
mCircleView.startAnimation(mScaleAnimation);
}
/**
* Pre API 11, this does an alpha animation.
*
* @param progress
*/
private void setAnimationProgress(float progress) {
if (isAlphaUsedForScale()) {
setColorViewAlpha((int) (progress * MAX_ALPHA));
} else {
ViewCompat.setScaleX(mCircleView, progress);
ViewCompat.setScaleY(mCircleView, progress);
}
}
private void setRefreshing(boolean refreshing, final boolean notify) {
if (mRefreshing != refreshing) {
mNotify = notify;
ensureTarget();
mRefreshing = refreshing;
if (mRefreshing) {
animateOffsetToCorrectPosition(mCurrentTargetOffsetTop, mRefreshListener);
} else {
startScaleDownAnimation(mRefreshListener);
}
}
}
private void startScaleDownAnimation(AnimationListener listener) {
mScaleDownAnimation = new Animation() {
@Override
public void applyTransformation(float interpolatedTime, Transformation t) {
setAnimationProgress(1 - interpolatedTime);
}
};
mScaleDownAnimation.setDuration(SCALE_DOWN_DURATION);
mCircleView.setAnimationListener(listener);
mCircleView.clearAnimation();
mCircleView.startAnimation(mScaleDownAnimation);
}
@SuppressLint("NewApi") private void startProgressAlphaStartAnimation() {
mAlphaStartAnimation = startAlphaAnimation(mProgress.getAlpha(), STARTING_PROGRESS_ALPHA);
}
@SuppressLint("NewApi") private void startProgressAlphaMaxAnimation() {
mAlphaMaxAnimation = startAlphaAnimation(mProgress.getAlpha(), MAX_ALPHA);
}
private Animation startAlphaAnimation(final int startingAlpha, final int endingAlpha) {
// Pre API 11, alpha is used in place of scale. Don't also use it to
// show the trigger point.
if (mScale && isAlphaUsedForScale()) {
return null;
}
Animation alpha = new Animation() {
@Override
public void applyTransformation(float interpolatedTime, Transformation t) {
mProgress
.setAlpha((int) (startingAlpha + ((endingAlpha - startingAlpha)
* interpolatedTime)));
}
};
alpha.setDuration(ALPHA_ANIMATION_DURATION);
// Clear out the previous animation listeners.
mCircleView.setAnimationListener(null);
mCircleView.clearAnimation();
mCircleView.startAnimation(alpha);
return alpha;
}
/**
* Set the background color of the progress spinner disc.
*
* @param colorRes Resource id of the color.
*/
public void setProgressBackgroundColor(int colorRes) {
mCircleView.setBackgroundColor(colorRes);
mProgress.setBackgroundColor(getResources().getColor(colorRes));
}
/**
* @deprecated Use {@link #setColorSchemeResources(int...)}
*/
@Deprecated
public void setColorScheme(int... colors) {
setColorSchemeResources(colors);
}
/**
* Set the color resources used in the progress animation from color resources.
* The first color will also be the color of the bar that grows in response
* to a user swipe gesture.
*
* @param colorResIds
*/
public void setColorSchemeResources(int... colorResIds) {
final Resources res = getResources();
int[] colorRes = new int[colorResIds.length];
for (int i = 0; i < colorResIds.length; i++) {
colorRes[i] = res.getColor(colorResIds[i]);
}
setColorSchemeColors(colorRes);
}
/**
* Set the colors used in the progress animation. The first
* color will also be the color of the bar that grows in response to a user
* swipe gesture.
*
* @param colors
*/
public void setColorSchemeColors(int... colors) {
ensureTarget();
mProgress.setColorSchemeColors(colors);
}
/**
* @return Whether the SwipeRefreshWidget is actively showing refresh
* progress.
*/
public boolean isRefreshing() {
return mRefreshing;
}
private void ensureTarget() {
// Don't bother getting the parent height if the parent hasn't been laid
// out yet.
if (mTarget == null) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (!child.equals(mCircleView)) {
mTarget = child;
break;
}
}
}
}
/**
* Set the distance to trigger a sync in dips
*
* @param distance
*/
public void setDistanceToTriggerSync(int distance) {
mTotalDragDistance = distance;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final int width = getMeasuredWidth();
final int height = getMeasuredHeight();
if (getChildCount() == 0) {
return;
}
if (mTarget == null) {
ensureTarget();
}
if (mTarget == null) {
return;
}
final View child = mTarget;
final int childLeft = getPaddingLeft();
final int childTop = getPaddingTop();
final int childWidth = width - getPaddingLeft() - getPaddingRight();
final int childHeight = height - getPaddingTop() - getPaddingBottom();
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
int circleWidth = mCircleView.getMeasuredWidth();
int circleHeight = mCircleView.getMeasuredHeight();
mCircleView.layout((width / 2 - circleWidth / 2), mCurrentTargetOffsetTop,
(width / 2 + circleWidth / 2), mCurrentTargetOffsetTop + circleHeight);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mTarget == null) {
ensureTarget();
}
if (mTarget == null) {
return;
}
mTarget.measure(MeasureSpec.makeMeasureSpec(
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));
mCircleView.measure(MeasureSpec.makeMeasureSpec(mCircleWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mCircleHeight, MeasureSpec.EXACTLY));
if (!mUsingCustomStart && !mOriginalOffsetCalculated) {
mOriginalOffsetCalculated = true;
switch (mDirection) {
case BOTTOM:
mCurrentTargetOffsetTop = mOriginalOffsetTop = getMeasuredHeight() - mCircleView.getMeasuredHeight();
break;
case TOP:
default:
mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();
break;
}
}
mCircleViewIndex = -1;
// Get the index of the circleview.
for (int index = 0; index < getChildCount(); index++) {
if (getChildAt(index) == mCircleView) {
mCircleViewIndex = index;
break;
}
}
}
/**
* @return Whether it is possible for the child view of this layout to
* scroll up. Override this if the child view is a custom view.
*/
public boolean canChildScrollUp() {
if (Build.VERSION.SDK_INT < 14) {
if (mTarget instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mTarget;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
.getTop() < absListView.getPaddingTop());
} else {
return mTarget.getScrollY() > 0;
}
} else {
return ViewCompat.canScrollVertically(mTarget, -1);
}
}
// public boolean canChildScrollUp() {
// if (android.os.Build.VERSION.SDK_INT < 14) {
// if (mTarget instanceof AbsListView) {
// final AbsListView absListView = (AbsListView) mTarget;
// if (absListView.getLastVisiblePosition() + 1 == absListView.getCount()) {
// int lastIndex = absListView.getLastVisiblePosition() - absListView.getFirstVisiblePosition();
//
// boolean res = absListView.getChildAt(lastIndex).getBottom() == absListView.getPaddingBottom();
//
// return res;
// }
// return true;
// } else {
// return mTarget.getScrollY() > 0;
// }
// } else {
// return ViewCompat.canScrollVertically(mTarget, 1);
// }
// }
public boolean canChildScrollDown() {
if (Build.VERSION.SDK_INT < 14) {
if (mTarget instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mTarget;
try {
if (absListView.getCount() > 0) {
if (absListView.getLastVisiblePosition() + 1 == absListView.getCount()) {
int lastIndex = absListView.getLastVisiblePosition() - absListView.getFirstVisiblePosition();
return absListView.getChildAt(lastIndex).getBottom() == absListView.getPaddingBottom();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
} else {
return true;
}
} else {
return ViewCompat.canScrollVertically(mTarget, 1);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
ensureTarget();
final int action = MotionEventCompat.getActionMasked(ev);
if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {
mReturningToStart = false;
}
switch (mDirection) {
case BOTTOM:
if (!isEnabled() || mReturningToStart || (!mBothDirection && canChildScrollDown()) || mRefreshing) {
// Fail fast if we're not in a state where a swipe is possible
return false;
}
break;
case TOP:
default:
if (!isEnabled() || mReturningToStart || (!mBothDirection && canChildScrollUp()) || mRefreshing) {
// Fail fast if we're not in a state where a swipe is possible
return false;
}
break;
}
switch (action) {
case MotionEvent.ACTION_DOWN:
setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCircleView.getTop(), true);
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
mIsBeingDragged = false;
final float initialMotionY = getMotionEventY(ev, mActivePointerId);
if (initialMotionY == -1) {
return false;
}
mInitialMotionY = initialMotionY;
case MotionEvent.ACTION_MOVE:
if (mActivePointerId == INVALID_POINTER) {
return false;
}
final float y = getMotionEventY(ev, mActivePointerId);
if (y == -1) {
return false;
}
if (mBothDirection) {
if (y > mInitialMotionY) {
setRawDirection(SwipyRefreshLayoutDirection.TOP);
} else if (y < mInitialMotionY) {
setRawDirection(SwipyRefreshLayoutDirection.BOTTOM);
}
if ((mDirection == SwipyRefreshLayoutDirection.BOTTOM && canChildScrollDown())
|| (mDirection == SwipyRefreshLayoutDirection.TOP && canChildScrollUp())) {
return false;
}
}
float yDiff;
switch (mDirection) {
case BOTTOM:
yDiff = mInitialMotionY - y;
break;
case TOP:
default:
yDiff = y - mInitialMotionY;
break;
}
if (yDiff > mTouchSlop && !mIsBeingDragged) {
mIsBeingDragged = true;
mProgress.setAlpha(STARTING_PROGRESS_ALPHA);
}
break;
case MotionEventCompat.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mIsBeingDragged = false;
mActivePointerId = INVALID_POINTER;
break;
}
return mIsBeingDragged;
}
private float getMotionEventY(MotionEvent ev, int activePointerId) {
final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);
if (index < 0) {
return -1;
}
return MotionEventCompat.getY(ev, index);
}
@Override
public void requestDisallowInterceptTouchEvent(boolean b) {
// Nope.
}
private boolean isAnimationRunning(Animation animation) {
return animation != null && animation.hasStarted() && !animation.hasEnded();
}
@SuppressLint("NewApi") @Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {
mReturningToStart = false;
}
switch (mDirection) {
case BOTTOM:
if (!isEnabled() || mReturningToStart || canChildScrollDown() || mRefreshing) {
// Fail fast if we're not in a state where a swipe is possible
return false;
}
break;
case TOP:
default:
if (!isEnabled() || mReturningToStart || canChildScrollUp() || mRefreshing) {
// Fail fast if we're not in a state where a swipe is possible
return false;
}
break;
}
switch (action) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
mIsBeingDragged = false;
break;
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
if (pointerIndex < 0) {
return false;
}
final float y = MotionEventCompat.getY(ev, pointerIndex);
float overscrollTop;
switch (mDirection) {
case BOTTOM:
overscrollTop = (mInitialMotionY - y) * DRAG_RATE;
break;
case TOP:
default:
overscrollTop = (y - mInitialMotionY) * DRAG_RATE;
break;
}
if (mIsBeingDragged) {
mProgress.showArrow(true);
float originalDragPercent = overscrollTop / mTotalDragDistance;
if (originalDragPercent < 0) {
return false;
}
float dragPercent = Math.min(1f, Math.abs(originalDragPercent));
float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3;
float extraOS = Math.abs(overscrollTop) - mTotalDragDistance;
float slingshotDist = mUsingCustomStart ? mSpinnerFinalOffset
- mOriginalOffsetTop : mSpinnerFinalOffset;
float tensionSlingshotPercent = Math.max(0,
Math.min(extraOS, slingshotDist * 2) / slingshotDist);
float tensionPercent = (float) ((tensionSlingshotPercent / 4) - Math.pow(
(tensionSlingshotPercent / 4), 2)) * 2f;
float extraMove = (slingshotDist) * tensionPercent * 2;
// int targetY = mOriginalOffsetTop + (int) ((slingshotDist * dragPercent) + extraMove);
int targetY;
if (mDirection == SwipyRefreshLayoutDirection.TOP) {
targetY = mOriginalOffsetTop + (int) ((slingshotDist * dragPercent) + extraMove);
} else {
targetY = mOriginalOffsetTop - (int) ((slingshotDist * dragPercent) + extraMove);
}
// where 1.0f is a full circle
if (mCircleView.getVisibility() != View.VISIBLE) {
mCircleView.setVisibility(View.VISIBLE);
}
if (!mScale) {
ViewCompat.setScaleX(mCircleView, 1f);
ViewCompat.setScaleY(mCircleView, 1f);
}
if (overscrollTop < mTotalDragDistance) {
if (mScale) {
setAnimationProgress(overscrollTop / mTotalDragDistance);
}
if (mProgress.getAlpha() > STARTING_PROGRESS_ALPHA
&& !isAnimationRunning(mAlphaStartAnimation)) {
// Animate the alpha
startProgressAlphaStartAnimation();
}
float strokeStart = (float) (adjustedPercent * .8f);
mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));
mProgress.setArrowScale(Math.min(1f, adjustedPercent));
} else {
if (mProgress.getAlpha() < MAX_ALPHA
&& !isAnimationRunning(mAlphaMaxAnimation)) {
// Animate the alpha
startProgressAlphaMaxAnimation();
}
}
float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f;
mProgress.setProgressRotation(rotation);
setTargetOffsetTopAndBottom(targetY - mCurrentTargetOffsetTop,
true /* requires update */);
}
break;
}
case MotionEventCompat.ACTION_POINTER_DOWN: {
final int index = MotionEventCompat.getActionIndex(ev);
mActivePointerId = MotionEventCompat.getPointerId(ev, index);
break;
}
case MotionEventCompat.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
if (mActivePointerId == INVALID_POINTER) {
if (action == MotionEvent.ACTION_UP) {
}
return false;
}
final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float y = MotionEventCompat.getY(ev, pointerIndex);
float overscrollTop;
switch (mDirection) {
case BOTTOM:
overscrollTop = (mInitialMotionY - y) * DRAG_RATE;
isTop = false;
break;
case TOP:
default:
overscrollTop = (y - mInitialMotionY) * DRAG_RATE;
isTop = true;
break;
}
mIsBeingDragged = false;
if (overscrollTop > mTotalDragDistance) {
setRefreshing(true, true /* notify */);
} else {
// cancel refresh
mRefreshing = false;
mProgress.setStartEndTrim(0f, 0f);
AnimationListener listener = null;
if (!mScale) {
listener = new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (!mScale) {
startScaleDownAnimation(null);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
}
animateOffsetToStartPosition(mCurrentTargetOffsetTop, listener);
mProgress.showArrow(false);
}
mActivePointerId = INVALID_POINTER;
return false;
}
}
return true;
}
private void animateOffsetToCorrectPosition(int from, AnimationListener listener) {
mFrom = from;
mAnimateToCorrectPosition.reset();
mAnimateToCorrectPosition.setDuration(ANIMATE_TO_TRIGGER_DURATION);
mAnimateToCorrectPosition.setInterpolator(mDecelerateInterpolator);
if (listener != null) {
mCircleView.setAnimationListener(listener);
}
mCircleView.clearAnimation();
mCircleView.startAnimation(mAnimateToCorrectPosition);
}
private void animateOffsetToStartPosition(int from, AnimationListener listener) {
if (mScale) {
// Scale the item back down
startScaleDownReturnToStartAnimation(from, listener);
} else {
mFrom = from;
mAnimateToStartPosition.reset();
mAnimateToStartPosition.setDuration(ANIMATE_TO_START_DURATION);
mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator);
if (listener != null) {
mCircleView.setAnimationListener(listener);
}
mCircleView.clearAnimation();
mCircleView.startAnimation(mAnimateToStartPosition);
}
}
private final Animation mAnimateToCorrectPosition = new Animation() {
@Override
public void applyTransformation(float interpolatedTime, Transformation t) {
int targetTop = 0;
int endTarget = 0;
if (!mUsingCustomStart) {
switch (mDirection) {
case BOTTOM:
endTarget = getMeasuredHeight() - (int) (mSpinnerFinalOffset);
break;
case TOP:
default:
endTarget = (int) (mSpinnerFinalOffset - Math.abs(mOriginalOffsetTop));
break;
}
} else {
endTarget = (int) mSpinnerFinalOffset;
}
targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime));
int offset = targetTop - mCircleView.getTop();
setTargetOffsetTopAndBottom(offset, false /* requires update */);
}
};
private void moveToStart(float interpolatedTime) {
int targetTop = 0;
targetTop = (mFrom + (int) ((mOriginalOffsetTop - mFrom) * interpolatedTime));
int offset = targetTop - mCircleView.getTop();
setTargetOffsetTopAndBottom(offset, false /* requires update */);
}
private final Animation mAnimateToStartPosition = new Animation() {
@Override
public void applyTransformation(float interpolatedTime, Transformation t) {
moveToStart(interpolatedTime);
}
};
@SuppressLint("NewApi") private void startScaleDownReturnToStartAnimation(int from,
AnimationListener listener) {
mFrom = from;
if (isAlphaUsedForScale()) {
mStartingScale = mProgress.getAlpha();
} else {
mStartingScale = ViewCompat.getScaleX(mCircleView);
}
mScaleDownToStartAnimation = new Animation() {
@Override
public void applyTransformation(float interpolatedTime, Transformation t) {
float targetScale = (mStartingScale + (-mStartingScale * interpolatedTime));
setAnimationProgress(targetScale);
moveToStart(interpolatedTime);
}
};
mScaleDownToStartAnimation.setDuration(SCALE_DOWN_DURATION);
if (listener != null) {
mCircleView.setAnimationListener(listener);
}
mCircleView.clearAnimation();
mCircleView.startAnimation(mScaleDownToStartAnimation);
}
private void setTargetOffsetTopAndBottom(int offset, boolean requiresUpdate) {
mCircleView.bringToFront();
mCircleView.offsetTopAndBottom(offset);
mCurrentTargetOffsetTop = mCircleView.getTop();
if (requiresUpdate && Build.VERSION.SDK_INT < 11) {
invalidate();
}
}
private void onSecondaryPointerUp(MotionEvent ev) {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
}
}
/**
* Classes that wish to be notified when the swipe gesture correctly
* triggers a refresh should implement this interface.
*/
public interface OnRefreshListener {
public void onRefresh(int index);
public void onLoad(int index);
}
public SwipyRefreshLayoutDirection getDirection() {
return mBothDirection ? SwipyRefreshLayoutDirection.BOTH : mDirection;
}
public void setDirection(SwipyRefreshLayoutDirection direction) {
if (direction == SwipyRefreshLayoutDirection.BOTH) {
mBothDirection = true;
} else {
mBothDirection = false;
mDirection = direction;
}
switch (mDirection) {
case BOTTOM:
mCurrentTargetOffsetTop = mOriginalOffsetTop = getMeasuredHeight() - mCircleView.getMeasuredHeight();
break;
case TOP:
default:
mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();
break;
}
}
// only TOP or Bottom
private void setRawDirection(SwipyRefreshLayoutDirection direction) {
if (mDirection == direction) {
return;
}
mDirection = direction;
switch (mDirection) {
case BOTTOM:
mCurrentTargetOffsetTop = mOriginalOffsetTop = getMeasuredHeight() - mCircleView.getMeasuredHeight();
break;
case TOP:
default:
mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();
break;
}
}
/**
* @return 获得从第一页开始索引
*/
public int getFirstIndex() {
return firstIndex;
}
/**
* 设置从第几页开始(默认值为0)
* @param firstIndex 第几页
*/
public void setFirstIndex(int firstIndex) {
this.firstIndex = firstIndex;
}
/**
* @return 获得当前索引
*/
public int getIndex() {
return index;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/swipyrefresh/SwipyRefreshLayoutDirection.java
================================================
package com.htmessage.yichatopen.widget.swipyrefresh;
/**
*
* @author xutao
*
*/
public enum SwipyRefreshLayoutDirection {
TOP(0), // 只有下拉刷新
BOTTOM(1), // 只有加载更多
BOTH(2);// 全都有
private int mValue;
SwipyRefreshLayoutDirection(int value) {
this.mValue = value;
}
public static SwipyRefreshLayoutDirection getFromInt(int value) {
for (SwipyRefreshLayoutDirection direction : SwipyRefreshLayoutDirection
.values()) {
if (direction.mValue == value) {
return direction;
}
}
return BOTH;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/activity/CaptureActivity.java
================================================
package com.htmessage.yichatopen.widget.zxing.activity;
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.widget.Toast;
import com.htmessage.yichatopen.widget.zxing.camera.CameraManager;
import com.htmessage.yichatopen.widget.zxing.decoding.CaptureActivityHandler;
import com.htmessage.yichatopen.widget.zxing.decoding.InactivityTimer;
import com.htmessage.yichatopen.widget.zxing.view.ViewfinderView;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import java.io.IOException;
import java.util.Vector;
public class CaptureActivity extends Activity implements Callback {
private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
private boolean hasSurface;
private Vector decodeFormats;
private String characterSet;
private InactivityTimer inactivityTimer;
private MediaPlayer mediaPlayer;
private boolean playBeep;
private static final float BEEP_VOLUME = 0.10f;
private boolean vibrate;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_camera);
// //ViewUtil.addTopView(getApplicationContext(), this, R.string.scan_card);
// CameraManager.init(getApplication(),false);
// viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
}
@SuppressWarnings("deprecation")
@Override
protected void onResume() {
super.onResume();
SurfaceView surfaceView = null;
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
} else {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
decodeFormats = null;
characterSet = null;
playBeep = true;
AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep = false;
}
initBeepSound();
vibrate = true;
}
@Override
protected void onPause() {
super.onPause();
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
CameraManager.get().closeDriver();
}
@Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
}
/**
* Handler scan result
* @param result
* @param barcode
*/
public void handleDecode(Result result, Bitmap barcode) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String resultString = result.getText();
//FIXME
if (resultString.equals("")) {
Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
}else {
// System.out.println("Result:"+resultString);
// Intent resultIntent = new Intent();
// Bundle bundle = new Bundle();
// bundle.putString("result", resultString);
// resultIntent.putExtras(bundle);
//this.setResult(RESULT_OK, resultIntent);
viewfinderView.drawResultBitmap(barcode);
String Qruid =result.getText().toString().trim();
//传值 gongfan
Intent intent = new Intent();
intent.putExtra("address", Qruid);
setResult(RESULT_OK,intent);
// intent.setClass(CaptureActivity.this,
// AddFriendsTwoActivity.class);
// startActivity(intent);
//查询用户
//
// searchUser(uid);
}
CaptureActivity.this.finish();
}
/* public void handleDecode(Result obj, Bitmap barcode) {
inactivityTimer.onActivity();
viewfinderView.drawResultBitmap(barcode);
playBeepSoundAndVibrate();
txtResult.setText(obj.getBarcodeFormat().toString() + ":"
+ obj.getText());
}*/
private void initCamera(SurfaceHolder surfaceHolder) {
try {
CameraManager.get().openDriver(surfaceHolder);
} catch (IOException ioe) {
return;
} catch (RuntimeException e) {
return;
}
if (handler == null) {
handler = new CaptureActivityHandler(this, decodeFormats,
characterSet);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
public ViewfinderView getViewfinderView() {
return viewfinderView;
}
public Handler getHandler() {
return handler;
}
public void drawViewfinder() {
viewfinderView.drawViewfinder();
}
private void initBeepSound() {
if (playBeep && mediaPlayer == null) {
// The volume on STREAM_SYSTEM is not adjustable, and users found it
// too loud,
// so we now play on the music stream.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(beepListener);
AssetFileDescriptor file =null;
try {
mediaPlayer.setDataSource(file.getFileDescriptor(),
file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
mediaPlayer.prepare();
} catch (IOException e) {
mediaPlayer = null;
}
}
}
private static final long VIBRATE_DURATION = 200L;
private void playBeepSoundAndVibrate() {
if (playBeep && mediaPlayer != null) {
mediaPlayer.start();
}
if (vibrate) {
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_DURATION);
}
}
/**
* When the beep has finished playing, rewind to queue up another one.
*/
private final OnCompletionListener beepListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
};
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/activity/DensityUtil.java
================================================
package com.htmessage.yichatopen.widget.zxing.activity;
import android.app.Activity;
import android.content.Context;
import android.util.DisplayMetrics;
/*
* 屏幕分辨率获取的类
*/
public class DensityUtil {
private static int[] deviceWidthHeight = new int[2];
public static int[] getDeviceInfo(Context context) {
if ((deviceWidthHeight[0] == 0) && (deviceWidthHeight[1] == 0)) {
DisplayMetrics metrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay()
.getMetrics(metrics);
deviceWidthHeight[0] = metrics.widthPixels;
deviceWidthHeight[1] = metrics.heightPixels;
}
return deviceWidthHeight;
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/AutoFocusCallback.java
================================================
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.camera;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
final class AutoFocusCallback implements Camera.AutoFocusCallback {
private static final String TAG = AutoFocusCallback.class.getSimpleName();
private static final long AUTOFOCUS_INTERVAL_MS = 1500L;
private Handler autoFocusHandler;
private int autoFocusMessage;
public boolean isFocusing;
void setHandler(Handler autoFocusHandler, int autoFocusMessage) {
this.autoFocusHandler = autoFocusHandler;
this.autoFocusMessage = autoFocusMessage;
}
public void onAutoFocus(boolean success, Camera camera) {
isFocusing = true;
if (autoFocusHandler != null) {
Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);
autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);
autoFocusHandler = null;
} else {
Log.d(TAG, "Got auto-focus callback, but no handler for it");
}
isFocusing = false;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/CameraConfigurationManager.java
================================================
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.camera;
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import java.util.regex.Pattern;
final class CameraConfigurationManager {
private static final String TAG = CameraConfigurationManager.class.getSimpleName();
private static final int TEN_DESIRED_ZOOM = 27;
private static final int DESIRED_SHARPNESS = 30;
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
private final Context context;
private Point screenResolution;
private Point cameraResolution;
private int previewFormat;
private String previewFormatString;
CameraConfigurationManager(Context context) {
this.context = context;
}
/**
* Reads, one time, values from the camera that are needed by the app.
*/
@SuppressWarnings("deprecation")
void initFromCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
previewFormat = parameters.getPreviewFormat();
previewFormatString = parameters.get("preview-format");
Log.d(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
screenResolution = new Point(display.getWidth(), display.getHeight());
Log.d(TAG, "Screen resolution: " + screenResolution);
cameraResolution = getCameraResolution(parameters, screenResolution);
Log.d(TAG, "Camera resolution: " + screenResolution);
}
/**
* Sets the camera up to take preview images which are used for both preview and decoding.
* We detect the preview format here so that buildLuminanceSource() can build an appropriate
* LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,
* and the planar Y can be used for barcode scanning without a copy in some cases.
*/
void setDesiredCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
Log.d(TAG, "Setting preview size: " + cameraResolution);
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
setFlash(parameters);
setZoom(parameters);
//setSharpness(parameters);
//modify here
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}
Point getCameraResolution() {
return cameraResolution;
}
Point getScreenResolution() {
return screenResolution;
}
int getPreviewFormat() {
return previewFormat;
}
String getPreviewFormatString() {
return previewFormatString;
}
private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
String previewSizeValueString = parameters.get("preview-size-values");
// saw this on Xperia
if (previewSizeValueString == null) {
previewSizeValueString = parameters.get("preview-size-value");
}
Point cameraResolution = null;
if (previewSizeValueString != null) {
Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);
cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);
}
if (cameraResolution == null) {
// Ensure that the camera resolution is a multiple of 8, as the screen may not be.
cameraResolution = new Point(
(screenResolution.x >> 3) << 3,
(screenResolution.y >> 3) << 3);
}
return cameraResolution;
}
private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
previewSize = previewSize.trim();
int dimPosition = previewSize.indexOf('x');
if (dimPosition < 0) {
Log.w(TAG, "Bad preview-size: " + previewSize);
continue;
}
int newX;
int newY;
try {
newX = Integer.parseInt(previewSize.substring(0, dimPosition));
newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad preview-size: " + previewSize);
continue;
}
int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
if (newDiff == 0) {
bestX = newX;
bestY = newY;
break;
} else if (newDiff < diff) {
bestX = newX;
bestY = newY;
diff = newDiff;
}
}
if (bestX > 0 && bestY > 0) {
return new Point(bestX, bestY);
}
return null;
}
private static int findBestMotZoomValue(CharSequence stringValues, int tenDesiredZoom) {
int tenBestValue = 0;
for (String stringValue : COMMA_PATTERN.split(stringValues)) {
stringValue = stringValue.trim();
double value;
try {
value = Double.parseDouble(stringValue);
} catch (NumberFormatException nfe) {
return tenDesiredZoom;
}
int tenValue = (int) (10.0 * value);
if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom - tenBestValue)) {
tenBestValue = tenValue;
}
}
return tenBestValue;
}
private void setFlash(Camera.Parameters parameters) {
// FIXME: This is a hack to turn the flash off on the Samsung Galaxy.
// And this is a hack-hack to work around a different value on the Behold II
// Restrict Behold II check to Cupcake, per Samsung's advice
//if (Build.MODEL.contains("Behold II") &&
// CameraManager.SDK_INT == Build.VERSION_CODES.CUPCAKE) {
if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) { // 3 = Cupcake
parameters.set("flash-value", 1);
} else {
parameters.set("flash-value", 2);
}
// This is the standard setting to turn the flash off that all devices should honor.
parameters.set("flash-mode", "off");
}
private void setZoom(Camera.Parameters parameters) {
String zoomSupportedString = parameters.get("zoom-supported");
if (zoomSupportedString != null && !Boolean.parseBoolean(zoomSupportedString)) {
return;
}
int tenDesiredZoom = TEN_DESIRED_ZOOM;
String maxZoomString = parameters.get("max-zoom");
if (maxZoomString != null) {
try {
int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad max-zoom: " + maxZoomString);
}
}
String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
if (takingPictureZoomMaxString != null) {
try {
int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad taking-picture-zoom-max: " + takingPictureZoomMaxString);
}
}
String motZoomValuesString = parameters.get("mot-zoom-values");
if (motZoomValuesString != null) {
tenDesiredZoom = findBestMotZoomValue(motZoomValuesString, tenDesiredZoom);
}
String motZoomStepString = parameters.get("mot-zoom-step");
if (motZoomStepString != null) {
try {
double motZoomStep = Double.parseDouble(motZoomStepString.trim());
int tenZoomStep = (int) (10.0 * motZoomStep);
if (tenZoomStep > 1) {
tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
}
} catch (NumberFormatException nfe) {
// continue
}
}
// Set zoom. This helps encourage the user to pull back.
// Some devices like the Behold have a zoom parameter
if (maxZoomString != null || motZoomValuesString != null) {
parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
}
// Most devices, like the Hero, appear to expose this zoom parameter.
// It takes on values like "27" which appears to mean 2.7x zoom
if (takingPictureZoomMaxString != null) {
parameters.set("taking-picture-zoom", tenDesiredZoom);
}
}
public static int getDesiredSharpness() {
return DESIRED_SHARPNESS;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/CameraManager.java
================================================
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.camera;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import com.htmessage.yichatopen.widget.zxing.activity.DensityUtil;
import java.io.IOException;
/**
* This object wraps the Camera service object and expects to be the only one talking to it. The
* implementation encapsulates the steps needed to take preview-sized images, which are used for
* both preview and decoding.
*
*/
@SuppressWarnings("deprecation")
public final class CameraManager {
private static final String TAG = CameraManager.class.getSimpleName();
private static final int MIN_FRAME_WIDTH = 340;
private static final int MIN_FRAME_HEIGHT = 340;
private static final int MAX_FRAME_WIDTH = 580;
private static final int MAX_FRAME_HEIGHT = 460;
private static CameraManager cameraManager;
static final int SDK_INT; // Later we can use Build.VERSION.SDK_INT
static {
int sdkInt;
try {
sdkInt = Integer.parseInt(Build.VERSION.SDK);
} catch (NumberFormatException nfe) {
// Just to be safe
sdkInt = 10000;
}
SDK_INT = sdkInt;
}
private final Context context;
private final CameraConfigurationManager configManager;
private Camera camera;
private Rect framingRect;
private Rect framingRectInPreview;
private boolean initialized;
private boolean previewing;
private final boolean useOneShotPreviewCallback;
private boolean is_top=false;
/**
* Preview frames are delivered here, which we pass on to the registered handler. Make sure to
* clear the handler so it will only receive one message.
*/
private final PreviewCallback previewCallback;
/** Autofocus callbacks arrive here, and are dispatched to the Handler which requested them. */
private final AutoFocusCallback autoFocusCallback;
/**
* Initializes this static object with the Context of the calling Activity.
*
* @param context The Activity which wants to use the camera.
*/
public static void init(Context context,boolean is_top) {
// if (cameraManager == null) {
cameraManager = new CameraManager(context,is_top);
// }
}
/**
* Gets the CameraManager singleton instance.
*
* @return A reference to the CameraManager singleton.
*/
public static CameraManager get() {
return cameraManager;
}
private CameraManager(Context context,boolean is_top) {
this.is_top=is_top;
this.context = context;
this.configManager = new CameraConfigurationManager(context);
// Camera.setOneShotPreviewCallback() has a race condition in Cupcake, so we use the older
// Camera.setPreviewCallback() on 1.5 and earlier. For Donut and later, we need to use
// the more efficient one shot callback, as the older one can swamp the system and cause it
// to run out of memory. We can't use SDK_INT because it was introduced in the Donut SDK.
//useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > Build.VERSION_CODES.CUPCAKE;
useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > 3; // 3 = Cupcake
previewCallback = new PreviewCallback(configManager, useOneShotPreviewCallback);
autoFocusCallback = new AutoFocusCallback();
}
/**
* Opens the camera driver and initializes the hardware parameters.
*
* @param holder The surface object which the camera will draw preview frames into.
* @throws IOException Indicates the camera driver failed to open.
*/
public void openDriver(SurfaceHolder holder) throws IOException {
if (camera == null) {
camera = Camera.open();
if (camera == null) {
throw new IOException();
}
camera.setPreviewDisplay(holder);
if (!initialized) {
initialized = true;
configManager.initFromCameraParameters(camera);
}
configManager.setDesiredCameraParameters(camera);
//FIXME
// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
//�Ƿ�ʹ��ǰ��
// if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
// FlashlightManager.enableFlashlight();
// }
FlashlightManager.enableFlashlight();
}
}
/**
* Closes the camera driver if still in use.
*/
public void closeDriver() {
if (camera != null) {
FlashlightManager.disableFlashlight();
camera.release();
camera = null;
}
}
/**
* Asks the camera hardware to begin drawing preview frames to the screen.
*/
public void startPreview() {
if (camera != null && !previewing) {
camera.startPreview();
previewing = true;
}
}
/**
* Tells the camera to stop drawing preview frames.
*/
public void stopPreview() {
if (camera != null && previewing) {
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
camera.stopPreview();
previewCallback.setHandler(null, 0);
autoFocusCallback.setHandler(null, 0);
previewing = false;
}
}
/**
* A single preview frame will be returned to the handler supplied. The data will arrive as byte[]
* in the message.obj field, with width and height encoded as message.arg1 and message.arg2,
* respectively.
*
* @param handler The handler to send the message to.
* @param message The what field of the message to be sent.
*/
public void requestPreviewFrame(Handler handler, int message) {
if (camera != null && previewing) {
previewCallback.setHandler(handler, message);
if (useOneShotPreviewCallback) {
camera.setOneShotPreviewCallback(previewCallback);
} else {
camera.setPreviewCallback(previewCallback);
}
}
}
/**
* Asks the camera hardware to perform an autofocus.
*
* @param handler The Handler to notify when the autofocus completes.
* @param message The message to deliver.
*/
public void requestAutoFocus(Handler handler, int message) {
if (camera != null && previewing ) {
autoFocusCallback.setHandler(handler, message);
//Log.d(TAG, "Requesting auto-focus callback");
try {
camera.autoFocus(autoFocusCallback);
} catch (Exception e) {
}
}
}
/**
* Calculates the framing rect which the UI should draw to show the user where to place the
* barcode. This target helps with alignment as well as forces the user to hold the device
* far enough away to ensure the image will be in focus.
*
* @return The rectangle to draw on screen in window coordinates.
*/
public Rect getFramingRect() {
Point screenResolution = configManager.getScreenResolution();
if (framingRect == null) {
if (camera == null) {
return null;
}
int width = screenResolution.x * 3 / 4;
if (width < MIN_FRAME_WIDTH) {
width = MIN_FRAME_WIDTH;
} else if (width > MAX_FRAME_WIDTH) {
width = MAX_FRAME_WIDTH;
}
int height = screenResolution.y * 3 / 4;
if (height < MIN_FRAME_HEIGHT) {
height = MIN_FRAME_HEIGHT;
} else if (height > MAX_FRAME_HEIGHT) {
height = MAX_FRAME_HEIGHT;
}
int leftOffset = (screenResolution.x - width) / 2;
int topOffset=(screenResolution.y - height) / 2;
if(is_top){
topOffset= DensityUtil.dip2px(getContext(),80);
}
framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
Log.d(TAG, "Calculated framing rect: " + framingRect);
}
return framingRect;
}
/**
* Like {@link #getFramingRect} but coordinates are in terms of the preview frame,
* not UI / screen.
*/
public Rect getFramingRectInPreview() {
if (framingRectInPreview == null) {
Rect rect = new Rect(getFramingRect());
Point cameraResolution = configManager.getCameraResolution();
Point screenResolution = configManager.getScreenResolution();
//modify here
// rect.left = rect.left * cameraResolution.x / screenResolution.x;
// rect.right = rect.right * cameraResolution.x / screenResolution.x;
// rect.top = rect.top * cameraResolution.y / screenResolution.y;
// rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
rect.left = rect.left * cameraResolution.y / screenResolution.x;
rect.right = rect.right * cameraResolution.y / screenResolution.x;
rect.top = rect.top * cameraResolution.x / screenResolution.y;
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
framingRectInPreview = rect;
}
return framingRectInPreview;
}
/**
* Converts the result points from still resolution coordinates to screen coordinates.
*
* @param points The points returned by the Reader subclass through Result.getResultPoints().
* @return An array of Points scaled to the size of the framing rect and offset appropriately
* so they can be drawn in screen coordinates.
*/
/*
public Point[] convertResultPoints(ResultPoint[] points) {
Rect frame = getFramingRectInPreview();
int count = points.length;
Point[] output = new Point[count];
for (int x = 0; x < count; x++) {
output[x] = new Point();
output[x].x = frame.left + (int) (points[x].getX() + 0.5f);
output[x].y = frame.top + (int) (points[x].getY() + 0.5f);
}
return output;
}
*/
/**
* A factory method to build the appropriate LuminanceSource object based on the format
* of the preview buffers, as described by Camera.Parameters.
*
* @param data A preview frame.
* @param width The width of the image.
* @param height The height of the image.
* @return A PlanarYUVLuminanceSource instance.
*/
public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
Rect rect = getFramingRectInPreview();
int previewFormat = configManager.getPreviewFormat();
String previewFormatString = configManager.getPreviewFormatString();
switch (previewFormat) {
// This is the standard Android format which all devices are REQUIRED to support.
// In theory, it's the only one we should ever care about.
case PixelFormat.YCbCr_420_SP:
// This format has never been seen in the wild, but is compatible as we only care
// about the Y channel, so allow it.
case PixelFormat.YCbCr_422_SP:
return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
rect.width(), rect.height());
default:
// The Samsung Moment incorrectly uses this variant instead of the 'sp' version.
// Fortunately, it too has all the Y data up front, so we can read it.
if ("yuv420p".equals(previewFormatString)) {
return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
rect.width(), rect.height());
}
}
throw new IllegalArgumentException("Unsupported picture format: " +
previewFormat + '/' + previewFormatString);
}
public Context getContext() {
return context;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/FlashlightManager.java
================================================
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.camera;
import android.os.IBinder;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* This class is used to activate the weak light on some camera phones (not flash)
* in order to illuminate surfaces for scanning. There is no official way to do this,
* but, classes which allow access to this function still exist on some devices.
* This therefore proceeds through a great deal of reflection.
*
* See
* http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/ and
*
* http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java.
* Thanks to Ryan Alford for pointing out the availability of this class.
*/
final class FlashlightManager {
private static final String TAG = FlashlightManager.class.getSimpleName();
private static final Object iHardwareService;
private static final Method setFlashEnabledMethod;
static {
iHardwareService = getHardwareService();
setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService);
if (iHardwareService == null) {
Log.v(TAG, "This device does supports control of a flashlight");
} else {
Log.v(TAG, "This device does not support control of a flashlight");
}
}
private FlashlightManager() {
}
//FIXME
static void enableFlashlight() {
setFlashlight(false);
}
static void disableFlashlight() {
setFlashlight(false);
}
private static Object getHardwareService() {
Class> serviceManagerClass = maybeForName("android.os.ServiceManager");
if (serviceManagerClass == null) {
return null;
}
Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class);
if (getServiceMethod == null) {
return null;
}
Object hardwareService = invoke(getServiceMethod, null, "hardware");
if (hardwareService == null) {
return null;
}
Class> iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub");
if (iHardwareServiceStubClass == null) {
return null;
}
Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface", IBinder.class);
if (asInterfaceMethod == null) {
return null;
}
return invoke(asInterfaceMethod, null, hardwareService);
}
private static Method getSetFlashEnabledMethod(Object iHardwareService) {
if (iHardwareService == null) {
return null;
}
Class> proxyClass = iHardwareService.getClass();
return maybeGetMethod(proxyClass, "setFlashlightEnabled", boolean.class);
}
private static Class> maybeForName(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException cnfe) {
// OK
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while finding class " + name, re);
return null;
}
}
private static Method maybeGetMethod(Class> clazz, String name, Class>... argClasses) {
try {
return clazz.getMethod(name, argClasses);
} catch (NoSuchMethodException nsme) {
// OK
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while finding method " + name, re);
return null;
}
}
private static Object invoke(Method method, Object instance, Object... args) {
try {
return method.invoke(instance, args);
} catch (IllegalAccessException e) {
Log.w(TAG, "Unexpected error while invoking " + method, e);
return null;
} catch (InvocationTargetException e) {
Log.w(TAG, "Unexpected error while invoking " + method, e.getCause());
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while invoking " + method, re);
return null;
}
}
private static void setFlashlight(boolean active) {
if (iHardwareService != null) {
invoke(setFlashEnabledMethod, iHardwareService, active);
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/PlanarYUVLuminanceSource.java
================================================
/*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.camera;
import android.graphics.Bitmap;
import com.google.zxing.LuminanceSource;
/**
* This object extends LuminanceSource around an array of YUV data returned from the camera driver,
* with the option to crop to a rectangle within the full data. This can be used to exclude
* superfluous pixels around the perimeter and speed up decoding.
*
* It works for any pixel format where the Y channel is planar and appears first, including
* YCbCr_420_SP and YCbCr_422_SP.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public final class PlanarYUVLuminanceSource extends LuminanceSource {
private final byte[] yuvData;
private final int dataWidth;
private final int dataHeight;
private final int left;
private final int top;
public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top,
int width, int height) {
super(width, height);
if (left + width > dataWidth || top + height > dataHeight) {
throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
}
this.yuvData = yuvData;
this.dataWidth = dataWidth;
this.dataHeight = dataHeight;
this.left = left;
this.top = top;
}
@Override
public byte[] getRow(int y, byte[] row) {
if (y < 0 || y >= getHeight()) {
throw new IllegalArgumentException("Requested row is outside the image: " + y);
}
int width = getWidth();
if (row == null || row.length < width) {
row = new byte[width];
}
int offset = (y + top) * dataWidth + left;
System.arraycopy(yuvData, offset, row, 0, width);
return row;
}
@Override
public byte[] getMatrix() {
int width = getWidth();
int height = getHeight();
// If the caller asks for the entire underlying image, save the copy and give them the
// original data. The docs specifically warn that result.length must be ignored.
if (width == dataWidth && height == dataHeight) {
return yuvData;
}
int area = width * height;
byte[] matrix = new byte[area];
int inputOffset = top * dataWidth + left;
// If the width matches the full width of the underlying data, perform a single copy.
if (width == dataWidth) {
System.arraycopy(yuvData, inputOffset, matrix, 0, area);
return matrix;
}
// Otherwise copy one cropped row at a time.
byte[] yuv = yuvData;
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
System.arraycopy(yuv, inputOffset, matrix, outputOffset, width);
inputOffset += dataWidth;
}
return matrix;
}
@Override
public boolean isCropSupported() {
return true;
}
public int getDataWidth() {
return dataWidth;
}
public int getDataHeight() {
return dataHeight;
}
public Bitmap renderCroppedGreyscaleBitmap() {
int width = getWidth();
int height = getHeight();
int[] pixels = new int[width * height];
byte[] yuv = yuvData;
int inputOffset = top * dataWidth + left;
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
for (int x = 0; x < width; x++) {
int grey = yuv[inputOffset + x] & 0xff;
pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);
}
inputOffset += dataWidth;
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/PreviewCallback.java
================================================
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.camera;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
final class PreviewCallback implements Camera.PreviewCallback {
private static final String TAG = PreviewCallback.class.getSimpleName();
private final CameraConfigurationManager configManager;
private final boolean useOneShotPreviewCallback;
private Handler previewHandler;
private int previewMessage;
PreviewCallback(CameraConfigurationManager configManager, boolean useOneShotPreviewCallback) {
this.configManager = configManager;
this.useOneShotPreviewCallback = useOneShotPreviewCallback;
}
void setHandler(Handler previewHandler, int previewMessage) {
this.previewHandler = previewHandler;
this.previewMessage = previewMessage;
}
public void onPreviewFrame(byte[] data, Camera camera) {
Point cameraResolution = configManager.getCameraResolution();
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
if (previewHandler != null) {
Message message = previewHandler.obtainMessage(previewMessage, cameraResolution.x,
cameraResolution.y, data);
message.sendToTarget();
previewHandler = null;
} else {
Log.d(TAG, "Got preview callback, but no handler for it");
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/CaptureActivityHandler.java
================================================
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.decoding;
import android.os.Handler;
import android.os.Message;
import com.htmessage.yichatopen.widget.zxing.activity.CaptureActivity;
import com.htmessage.yichatopen.widget.zxing.camera.CameraManager;
import com.htmessage.yichatopen.widget.zxing.view.ViewfinderResultPointCallback;
import com.google.zxing.BarcodeFormat;
import java.util.Vector;
/**
* This class handles all the messaging which comprises the state machine for capture.
*/
public final class CaptureActivityHandler extends Handler {
private static final String TAG = CaptureActivityHandler.class.getSimpleName();
private final CaptureActivity activity;
private final DecodeThread decodeThread;
private State state;
private enum State {
PREVIEW,
SUCCESS,
DONE
}
public CaptureActivityHandler(CaptureActivity activity, Vector decodeFormats,
String characterSet) {
this.activity = activity;
decodeThread = new DecodeThread(activity, decodeFormats, characterSet,
new ViewfinderResultPointCallback(activity.getViewfinderView()));
decodeThread.start();
state = State.SUCCESS;
// Start ourselves capturing previews and decoding.
CameraManager.get().startPreview();
restartPreviewAndDecode();
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
}
}
public void quitSynchronously() {
state = State.DONE;
CameraManager.get().stopPreview();
Message quit = null;
quit.sendToTarget();
try {
decodeThread.join();
} catch (InterruptedException e) {
// continue
}
// Be absolutely sure we don't send any queued up messages
// removeMessages(R.id.decode_succeeded);
// removeMessages(R.id.decode_failed);
}
private void restartPreviewAndDecode() {
if (state == State.SUCCESS) {
state = State.PREVIEW;
// CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
// CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
activity.drawViewfinder();
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/DecodeFormatManager.java
================================================
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.decoding;
import android.content.Intent;
import android.net.Uri;
import com.google.zxing.BarcodeFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.regex.Pattern;
final class DecodeFormatManager {
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
static final Vector PRODUCT_FORMATS;
static final Vector ONE_D_FORMATS;
static final Vector QR_CODE_FORMATS;
static final Vector DATA_MATRIX_FORMATS;
static {
PRODUCT_FORMATS = new Vector(5);
PRODUCT_FORMATS.add(BarcodeFormat.UPC_A);
PRODUCT_FORMATS.add(BarcodeFormat.UPC_E);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_13);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_8);
PRODUCT_FORMATS.add(BarcodeFormat.RSS14);
ONE_D_FORMATS = new Vector(PRODUCT_FORMATS.size() + 4);
ONE_D_FORMATS.addAll(PRODUCT_FORMATS);
ONE_D_FORMATS.add(BarcodeFormat.CODE_39);
ONE_D_FORMATS.add(BarcodeFormat.CODE_93);
ONE_D_FORMATS.add(BarcodeFormat.CODE_128);
ONE_D_FORMATS.add(BarcodeFormat.ITF);
QR_CODE_FORMATS = new Vector(1);
QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE);
DATA_MATRIX_FORMATS = new Vector(1);
DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX);
}
private DecodeFormatManager() {}
static Vector parseDecodeFormats(Intent intent) {
List scanFormats = null;
String scanFormatsString = intent.getStringExtra(Intents.Scan.SCAN_FORMATS);
if (scanFormatsString != null) {
scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString));
}
return parseDecodeFormats(scanFormats, intent.getStringExtra(Intents.Scan.MODE));
}
static Vector parseDecodeFormats(Uri inputUri) {
List formats = inputUri.getQueryParameters(Intents.Scan.SCAN_FORMATS);
if (formats != null && formats.size() == 1 && formats.get(0) != null){
formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0)));
}
return parseDecodeFormats(formats, inputUri.getQueryParameter(Intents.Scan.MODE));
}
private static Vector parseDecodeFormats(Iterable scanFormats,
String decodeMode) {
if (scanFormats != null) {
Vector formats = new Vector();
try {
for (String format : scanFormats) {
formats.add(BarcodeFormat.valueOf(format));
}
return formats;
} catch (IllegalArgumentException iae) {
// ignore it then
}
}
if (decodeMode != null) {
if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) {
return PRODUCT_FORMATS;
}
if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) {
return QR_CODE_FORMATS;
}
if (Intents.Scan.DATA_MATRIX_MODE.equals(decodeMode)) {
return DATA_MATRIX_FORMATS;
}
if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) {
return ONE_D_FORMATS;
}
}
return null;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/DecodeHandler.java
================================================
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.decoding;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.htmessage.yichatopen.widget.zxing.activity.CaptureActivity;
import com.htmessage.yichatopen.widget.zxing.camera.CameraManager;
import com.htmessage.yichatopen.widget.zxing.camera.PlanarYUVLuminanceSource;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import java.util.Hashtable;
final class DecodeHandler extends Handler {
private static final String TAG = DecodeHandler.class.getSimpleName();
private final CaptureActivity activity;
private final MultiFormatReader multiFormatReader;
DecodeHandler(CaptureActivity activity, Hashtable hints) {
multiFormatReader = new MultiFormatReader();
multiFormatReader.setHints(hints);
this.activity = activity;
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
}
}
/**
* Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
* reuse the same reader objects from one decode to the next.
*
* @param data The YUV preview frame.
* @param width The width of the preview frame.
* @param height The height of the preview frame.
*/
private void decode(byte[] data, int width, int height) {
long start = System.currentTimeMillis();
Result rawResult = null;
//modify here
byte[] rotatedData = new byte[data.length];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
rotatedData[x * height + height - y - 1] = data[x + y * width];
}
int tmp = width; // Here we are swapping, that's the difference to #11
width = height;
height = tmp;
PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
rawResult = multiFormatReader.decodeWithState(bitmap);
} catch (ReaderException re) {
// continue
} finally {
multiFormatReader.reset();
}
if (rawResult != null) {
long end = System.currentTimeMillis();
Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n" + rawResult.toString());
Message message =null;
Bundle bundle = new Bundle();
bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
message.setData(bundle);
//Log.d(TAG, "Sending decode succeeded message...");
message.sendToTarget();
} else {
Message message = Message.obtain(activity.getHandler(),null);
message.sendToTarget();
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/DecodeThread.java
================================================
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.decoding;
import android.os.Handler;
import android.os.Looper;
import com.htmessage.yichatopen.widget.zxing.activity.CaptureActivity;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.ResultPointCallback;
import java.util.Hashtable;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
/**
* This thread does all the heavy lifting of decoding the images.
*/
final class DecodeThread extends Thread {
public static final String BARCODE_BITMAP = "barcode_bitmap";
private final CaptureActivity activity;
private final Hashtable hints;
private Handler handler;
private final CountDownLatch handlerInitLatch;
DecodeThread(CaptureActivity activity,
Vector decodeFormats,
String characterSet,
ResultPointCallback resultPointCallback) {
this.activity = activity;
handlerInitLatch = new CountDownLatch(1);
hints = new Hashtable(3);
if (decodeFormats == null || decodeFormats.isEmpty()) {
decodeFormats = new Vector();
decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
}
hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
if (characterSet != null) {
hints.put(DecodeHintType.CHARACTER_SET, characterSet);
}
hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
}
Handler getHandler() {
try {
handlerInitLatch.await();
} catch (InterruptedException ie) {
// continue?
}
return handler;
}
@Override
public void run() {
Looper.prepare();
handler = new DecodeHandler(activity, hints);
handlerInitLatch.countDown();
Looper.loop();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/FinishListener.java
================================================
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.decoding;
import android.app.Activity;
import android.content.DialogInterface;
/**
* Simple listener used to exit the app in a few cases.
*
*/
public final class FinishListener
implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable {
private final Activity activityToFinish;
public FinishListener(Activity activityToFinish) {
this.activityToFinish = activityToFinish;
}
public void onCancel(DialogInterface dialogInterface) {
run();
}
public void onClick(DialogInterface dialogInterface, int i) {
run();
}
public void run() {
activityToFinish.finish();
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/InactivityTimer.java
================================================
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.decoding;
import android.app.Activity;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* Finishes an activity after a period of inactivity.
*/
public final class InactivityTimer {
private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;
private final ScheduledExecutorService inactivityTimer =
Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
private final Activity activity;
private ScheduledFuture> inactivityFuture = null;
public InactivityTimer(Activity activity) {
this.activity = activity;
onActivity();
}
public void onActivity() {
cancel();
inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),
INACTIVITY_DELAY_SECONDS,
TimeUnit.SECONDS);
}
private void cancel() {
if (inactivityFuture != null) {
inactivityFuture.cancel(true);
inactivityFuture = null;
}
}
public void shutdown() {
cancel();
inactivityTimer.shutdown();
}
private static final class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable);
thread.setDaemon(true);
return thread;
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/Intents.java
================================================
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.decoding;
/**
* This class provides the constants to use when sending an Intent to Barcode Scanner.
* These strings are effectively API and cannot be changed.
*/
public final class Intents {
private Intents() {
}
public static final class Scan {
/**
* Send this intent to open the Barcodes app in scanning mode, find a barcode, and return
* the results.
*/
public static final String ACTION = "com.google.zxing.client.android.SCAN";
/**
* By default, sending Scan.ACTION will decode all barcodes that we understand. However it
* may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with
* one of the values below ({@link #PRODUCT_MODE}, {@link #ONE_D_MODE}, {@link #QR_CODE_MODE}).
* Optional.
*
* Setting this is effectively shorthnad for setting explicit formats with {@link #SCAN_FORMATS}.
* It is overridden by that setting.
*/
public static final String MODE = "SCAN_MODE";
/**
* Comma-separated list of formats to scan for. The values must match the names of
* {@link com.google.zxing.BarcodeFormat}s, such as {@link com.google.zxing.BarcodeFormat#EAN_13}.
* Example: "EAN_13,EAN_8,QR_CODE"
*
* This overrides {@link #MODE}.
*/
public static final String SCAN_FORMATS = "SCAN_FORMATS";
/**
* @see com.google.zxing.DecodeHintType#CHARACTER_SET
*/
public static final String CHARACTER_SET = "CHARACTER_SET";
/**
* Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get
* prices, reviews, etc. for products.
*/
public static final String PRODUCT_MODE = "PRODUCT_MODE";
/**
* Decode only 1D barcodes (currently UPC, EAN, Code 39, and Code 128).
*/
public static final String ONE_D_MODE = "ONE_D_MODE";
/**
* Decode only QR codes.
*/
public static final String QR_CODE_MODE = "QR_CODE_MODE";
/**
* Decode only Data Matrix codes.
*/
public static final String DATA_MATRIX_MODE = "DATA_MATRIX_MODE";
/**
* If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which
* requested the scan via startSubActivity(). The barcodes contents can be retrieved with
* intent.getStringExtra(RESULT). If the user presses Back, the result code will be
* RESULT_CANCELED.
*/
public static final String RESULT = "SCAN_RESULT";
/**
* Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found.
* See Contents.Format for possible values.
*/
public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT";
/**
* Setting this to false will not save scanned codes in the history.
*/
public static final String SAVE_HISTORY = "SAVE_HISTORY";
private Scan() {
}
}
public static final class Encode {
/**
* Send this intent to encode a piece of data as a QR code and display it full screen, so
* that another person can scan the barcode from your screen.
*/
public static final String ACTION = "com.google.zxing.client.android.ENCODE";
/**
* The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a
* Bundle, depending on the type and format specified. Non-QR Code formats should
* just use a String here. For QR Code, see Contents for details.
*/
public static final String DATA = "ENCODE_DATA";
/**
* The type of data being supplied if the format is QR Code. Use
* Intent.putExtra(TYPE, type) with one of Contents.Type.
*/
public static final String TYPE = "ENCODE_TYPE";
/**
* The barcode format to be displayed. If this isn't specified or is blank,
* it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where
* format is one of Contents.Format.
*/
public static final String FORMAT = "ENCODE_FORMAT";
private Encode() {
}
}
public static final class SearchBookContents {
/**
* Use Google Book Search to search the contents of the book provided.
*/
public static final String ACTION = "com.google.zxing.client.android.SEARCH_BOOK_CONTENTS";
/**
* The book to search, identified by ISBN number.
*/
public static final String ISBN = "ISBN";
/**
* An optional field which is the text to search for.
*/
public static final String QUERY = "QUERY";
private SearchBookContents() {
}
}
public static final class WifiConnect {
/**
* Internal intent used to trigger connection to a wi-fi network.
*/
public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String SSID = "SSID";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String TYPE = "TYPE";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String PASSWORD = "PASSWORD";
private WifiConnect() {
}
}
public static final class Share {
/**
* Give the user a choice of items to encode as a barcode, then render it as a QR Code and
* display onscreen for a friend to scan with their phone.
*/
public static final String ACTION = "com.google.zxing.client.android.SHARE";
private Share() {
}
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/encoding/EncodingHandler.java
================================================
package com.htmessage.yichatopen.widget.zxing.encoding;
import android.graphics.Bitmap;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import java.util.Hashtable;
/**
* @author Ryan Tang
*
*/
public final class EncodingHandler {
private static final int BLACK = 0xff000000;
public static Bitmap createQRCode(String str,int widthAndHeight) throws WriterException {
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix matrix = new MultiFormatWriter().encode(str,
BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight);
int width = matrix.getWidth();
int height = matrix.getHeight();
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (matrix.get(x, y)) {
pixels[y * width + x] = BLACK;
}
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/view/ViewfinderResultPointCallback.java
================================================
/*
* Copyright (C) 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.view;
import com.google.zxing.ResultPoint;
import com.google.zxing.ResultPointCallback;
public final class ViewfinderResultPointCallback implements ResultPointCallback {
private final ViewfinderView viewfinderView;
public ViewfinderResultPointCallback(ViewfinderView viewfinderView) {
this.viewfinderView = viewfinderView;
}
public void foundPossibleResultPoint(ResultPoint point) {
viewfinderView.addPossibleResultPoint(point);
}
}
================================================
FILE: app/src/main/java/com/htmessage/yichatopen/widget/zxing/view/ViewfinderView.java
================================================
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.htmessage.yichatopen.widget.zxing.view;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import com.htmessage.yichatopen.widget.zxing.camera.CameraManager;
import com.google.zxing.ResultPoint;
import java.util.Collection;
import java.util.HashSet;
/**
* This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial
* transparency outside it, as well as the laser scanner animation and result points.
* �Զ����View������ʱ�м���ʾ��
*/
public final class ViewfinderView extends View {
private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
private static final long ANIMATION_DELAY = 100L;
private static final int OPAQUE = 0xFF;
private final Paint paint;
private Bitmap resultBitmap;
private final int maskColor;
private final int resultColor;
private final int frameColor;
private final int laserColor;
private final int resultPointColor;
private int scannerAlpha;
private Collection possibleResultPoints;
private Collection lastPossibleResultPoints;
// This constructor is used when the class is built from an XML resource.
public ViewfinderView(Context context, AttributeSet attrs) {
super(context, attrs);
// Initialize these once for performance rather than calling them every time in onDraw().
paint = new Paint();
Resources resources = getResources();
maskColor = 0;
resultColor =0;
frameColor = 0;
laserColor = 0;
resultPointColor =0;
scannerAlpha = 0;
possibleResultPoints = new HashSet(5);
}
@Override
public void onDraw(Canvas canvas) {
Rect frame = CameraManager.get().getFramingRect();
if (frame == null) {
return;
}
int width = canvas.getWidth();
int height = canvas.getHeight();
// Draw the exterior (i.e. outside the framing rect) darkened
paint.setColor(resultBitmap != null ? resultColor : maskColor);
canvas.drawRect(0, 0, width, frame.top, paint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
canvas.drawRect(0, frame.bottom + 1, width, height, paint);
if (resultBitmap != null) {
// Draw the opaque result bitmap over the scanning rectangle
paint.setAlpha(OPAQUE);
canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
} else {
// Draw a two pixel solid black border inside the framing rect
paint.setColor(frameColor);
canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);
canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);
// Draw a red "laser scanner" line through the middle to show decoding is active
paint.setColor(laserColor);
paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
int middle = frame.height() / 2 + frame.top;
canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
Collection currentPossible = possibleResultPoints;
Collection currentLast = lastPossibleResultPoints;
if (currentPossible.isEmpty()) {
lastPossibleResultPoints = null;
} else {
possibleResultPoints = new HashSet(5);
lastPossibleResultPoints = currentPossible;
paint.setAlpha(OPAQUE);
paint.setColor(resultPointColor);
for (ResultPoint point : currentPossible) {
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
}
}
if (currentLast != null) {
paint.setAlpha(OPAQUE / 2);
paint.setColor(resultPointColor);
for (ResultPoint point : currentLast) {
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint);
}
}
// Request another update at the animation interval, but only repaint the laser line,
// not the entire viewfinder mask.
postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom);
}
}
public void drawViewfinder() {
resultBitmap = null;
invalidate();
}
/**
* Draw a bitmap with the result points highlighted instead of the live scanning display.
*
* @param barcode An image of the decoded barcode.
*/
public void drawResultBitmap(Bitmap barcode) {
resultBitmap = barcode;
invalidate();
}
public void addPossibleResultPoint(ResultPoint point) {
possibleResultPoints.add(point);
}
}
================================================
FILE: app/src/main/res/anim/fade_in.xml
================================================
================================================
FILE: app/src/main/res/anim/fade_out.xml
================================================
================================================
FILE: app/src/main/res/anim/head_in.xml
================================================
================================================
FILE: app/src/main/res/anim/head_out.xml
================================================
================================================
FILE: app/src/main/res/anim/hold.xml
================================================
================================================
FILE: app/src/main/res/anim/loading_animation.xml
================================================
================================================
FILE: app/src/main/res/anim/push_bottom_in.xml
================================================
================================================
FILE: app/src/main/res/anim/push_bottom_out.xml
================================================
================================================
FILE: app/src/main/res/anim/push_top_in.xml
================================================
================================================
FILE: app/src/main/res/anim/push_top_in2.xml
================================================
================================================
FILE: app/src/main/res/anim/push_top_out.xml
================================================
================================================
FILE: app/src/main/res/anim/push_top_out2.xml
================================================
================================================
FILE: app/src/main/res/anim/slide_in_from_left.xml
================================================
================================================
FILE: app/src/main/res/anim/slide_in_from_right.xml
================================================
================================================
FILE: app/src/main/res/anim/slide_out_to_left.xml
================================================
================================================
FILE: app/src/main/res/anim/slide_out_to_right.xml
================================================
================================================
FILE: app/src/main/res/anim/voice_from_icon.xml
================================================
================================================
FILE: app/src/main/res/anim/voice_to_icon.xml
================================================
================================================
FILE: app/src/main/res/color/login_btn_text_color.xml
================================================
================================================
FILE: app/src/main/res/color/main_botton_text_color.xml
================================================
================================================
FILE: app/src/main/res/drawable/bg_btn_gray.xml
================================================
================================================
FILE: app/src/main/res/drawable/bg_btn_green.xml
================================================
================================================
FILE: app/src/main/res/drawable/bg_dialog.xml
================================================
================================================
FILE: app/src/main/res/drawable/bg_et.xml
================================================
================================================
FILE: app/src/main/res/drawable/btn_bottom_selector.xml
================================================
================================================
FILE: app/src/main/res/drawable/btn_more_type_msg.xml
================================================
================================================
FILE: app/src/main/res/drawable/chat_error_item_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/chat_image_selector.xml
================================================
================================================
FILE: app/src/main/res/drawable/chat_press_speak_btn.xml
================================================
================================================
FILE: app/src/main/res/drawable/chat_takepic_selector.xml
================================================
================================================
FILE: app/src/main/res/drawable/chatfrom_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/chatting_setmode_keyboard_btn.xml
================================================
================================================
FILE: app/src/main/res/drawable/chatting_setmode_voice_btn.xml
================================================
================================================
FILE: app/src/main/res/drawable/chatto_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/divider_horizontal.xml
================================================
================================================
FILE: app/src/main/res/drawable/divider_vertical.xml
================================================
================================================
FILE: app/src/main/res/drawable/dot_emoji.xml
================================================
================================================
FILE: app/src/main/res/drawable/edit_text_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/emoji_bottom_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/item_pre_videocall_selector.xml
================================================
================================================
FILE: app/src/main/res/drawable/list_item_bg_gray.xml
================================================
================================================
FILE: app/src/main/res/drawable/list_item_bg_white.xml
================================================
================================================
FILE: app/src/main/res/drawable/msg_state_failed_resend.xml
================================================
================================================
FILE: app/src/main/res/drawable/progressbar_white.xml
================================================
================================================
FILE: app/src/main/res/drawable/recording_hint_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/recording_text_hint_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/register_phone_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/sidebar_background_pressed.xml
================================================
================================================
FILE: app/src/main/res/drawable/sign_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/tab_chat_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/tab_contact_list_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/tab_find_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/tab_profile_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/timestampe_bg.xml
================================================
================================================
FILE: app/src/main/res/drawable/top_bar_back.xml
================================================
================================================
FILE: app/src/main/res/drawable/topbar_back.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_addfriends_final.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_addfriends_next.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_addfriends_pre.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_base.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_base_input.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_base_main.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_chat_setting_single.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_check_people.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_new_friends.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_people_recently.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_psw_reset.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_qrcode_generate.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_region.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_show_big_image.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_splash.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_update_info.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_userinfo.xml
================================================
================================================
FILE: app/src/main/res/layout/chat_menu_item.xml
================================================
================================================
FILE: app/src/main/res/layout/chat_neterror_item.xml
================================================
================================================
FILE: app/src/main/res/layout/coogame_country_item.xml
================================================
================================================
FILE: app/src/main/res/layout/dialog_alert.xml
================================================
================================================
FILE: app/src/main/res/layout/emoji_gridview.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_chat.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_contactlist.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_conversation_settings.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_emoji.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_find.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_home.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_login.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_profile.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_profile_info.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_register.xml
================================================
================================================
FILE: app/src/main/res/layout/item_contact_list.xml
================================================
================================================
FILE: app/src/main/res/layout/item_contact_list_footer.xml
================================================
================================================
FILE: app/src/main/res/layout/item_contact_list_header.xml
================================================
================================================
FILE: app/src/main/res/layout/item_conversation_single.xml
================================================
================================================
FILE: app/src/main/res/layout/item_dialog_gridview.xml
================================================
================================================
FILE: app/src/main/res/layout/item_diaolog_gridview.xml
================================================
================================================
FILE: app/src/main/res/layout/item_newfriend_msg.xml
================================================
================================================
FILE: app/src/main/res/layout/item_people_recently.xml
================================================
================================================
FILE: app/src/main/res/layout/item_region.xml
================================================
================================================
FILE: app/src/main/res/layout/latout_pre_videocall_item.xml
================================================
================================================
FILE: app/src/main/res/layout/layout_alert_dialog_delete.xml
================================================
================================================
FILE: app/src/main/res/layout/layout_pup.xml
================================================
================================================
FILE: app/src/main/res/layout/layout_title_bar.xml
================================================
================================================
FILE: app/src/main/res/layout/loading_dialog.xml
================================================
================================================
FILE: app/src/main/res/layout/row_big_expression.xml
================================================
================================================
FILE: app/src/main/res/layout/row_expression.xml
================================================
================================================
FILE: app/src/main/res/layout/row_received_message.xml
================================================
================================================
FILE: app/src/main/res/layout/row_received_picture.xml
================================================
================================================
FILE: app/src/main/res/layout/row_received_voice.xml
================================================
================================================
FILE: app/src/main/res/layout/row_sent_message.xml
================================================
================================================
FILE: app/src/main/res/layout/row_sent_picture.xml
================================================
================================================
FILE: app/src/main/res/layout/row_sent_voice.xml
================================================
================================================
FILE: app/src/main/res/layout/widget_input_view.xml
================================================
================================================
FILE: app/src/main/res/layout/widget_main_button.xml
================================================
================================================
FILE: app/src/main/res/layout/widget_switch_button.xml
================================================
================================================
FILE: app/src/main/res/layout/widget_voice_recorder.xml
================================================
================================================
FILE: app/src/main/res/layout/widget_zbar_scan_capture.xml
================================================
"
================================================
FILE: app/src/main/res/menu/menu_main.xml
================================================
================================================
FILE: app/src/main/res/values/arrays.xml
================================================
Angola *+244 Afghanistan *+93 Albania *+355 Algeria *+213 Andorra *+376 Anguilla *+1264 Antigua and Barbuda *+1268 Argentina *+54 Armenia *+374 Ascension *+247 Australia *+61 Austria *+43 Azerbaijan *+994 Bahamas *+1242 Bahrain *+973 Bangladesh *+880 Barbados *+1246 Belarus *+375 Belgium *+32 Belize *+501 Benin *+229 BermudaIs. *+1441 Bolivia *+591 Botswana *+267 Brazil *+55 Brunei *+673 Bulgaria *+359 Burkina-faso *+226 Burma *+95 Burundi *+257 Cameroon *+237 Canada *+1 Cayman Is. *+1345 Central African Republic *+236 Chad *+235 Chile *+56 China *+86 Colombia *+57 Congo *+242 Cook Is. *+682 Costa Rica *+506 Cuba *+53 Cyprus *+357 Czech Republic *+420 Denmark *+45 Djibouti *+253 Dominica Rep. *+1890 Ecuador *+593 Egypt *+20 EISalvador *+503 Estonia *+372 Ethiopia *+251 Fiji *+679 Finland *+358 France *+33 French Guiana *+594 Gabon *+241 Gambia *+220 Georgia *+995 Germany *+49 Ghana *+233 Gibraltar *+350 Greece *+30 Grenada *+1809 Guam *+1671 Guatemala *+502 Guinea *+224 Guyana *+592 Haiti *+509 Honduras *+504 Hongkong *+852 Hungary *+36 Iceland *+354 India *+91 Indonesia *+62 Iran *+98 Iraq *+964 Ireland *+353 Israel *+972 Italy *+39 IvoryCoast *+225 Jamaica *+1876 Japan *+81 Jordan *+962 Kampuchea (Cambodia ) *+855 Kazakstan *+327 Kenya *+254 Korea *+82 Kuwait *+965 Kyrgyzstan *+331 Laos *+856 Latvia *+371 Lebanon *+961 Lesotho *+266 Liberia *+231 Libya *+218 Liechtenstein *+423 Lithuania *+370 Luxembourg *+352 Macao *+853 Madagascar *+261 Malawi *+265 Malaysia *+60 Maldives *+960 Mali *+223 Malta *+356 Mariana Is *+1670 Martinique *+596 Mauritius *+230 Mexico *+52 Moldova, Republic of *+373 Monaco *+377 Mongolia *+976 Montserrat Is *+1664 Morocco *+212 Mozambique *+258 Namibia *+264 Nauru *+674 Nepal *+977 Netheriands Antilles *+599 Netherlands *+31 NewZealand *+64 Nicaragua *+505 Niger *+227 Nigeria *+234 North Korea *+850 Norway *+47 Oman *+968 Pakistan *+92 Panama *+507 Papua New Cuinea *+675 Paraguay *+595 Peru *+51 Philippines *+63 Poland *+48 French Polynesia *+689 Portugal *+351 PuertoRico *+1787 Qatar *+974 Reunion *+262 Romania *+40 Russia *+7 Saint Lueia *+1758 Saint Vincent *+1784 Samoa Eastern *+684 Samoa Western *+685 San Marino *+378 Sao Tome and Principe *+239 Saudi Arabia *+966 Senegal *+221 Seychelles *+248 Sierra Leone *+232 Singapore *+65 Slovakia *+421 Slovenia *+386 Solomon Is *+677 Somali *+252 South Africa *+27 Spain *+34 Sri Lanka *+94 St.Lucia *+1758 St.Vincent *+1784 Sudan *+249 Suriname *+597 Swaziland *+268 Sweden *+46 Switzerland *+41 Syriaw *+963 Taiwan *+886 Tajikstan *+992 Tanzania *+255 Thailand *+66 Togo *+228 Tonga *+676 Trinidad and Tobago *+1809 Tunisia *+216 Turkey *+90 Turkmenistan *+993 Uganda *+256 Ukraine *+380 United Arab Emirates *+971 United Kiongdom *+44 United States of America *+1 Uruguay *+598 Uzbekistan *+233 Venezuela *+58 Vietnam *+84 Yemen *+967 Yugoslavia *+381 South Africa *+27 Zimbabwe *+263 Zaire *+243 Zambia *+260 安哥拉 *+244 阿富汗 *+93 阿尔巴尼亚 *+355 阿尔及利亚 *+213 安道尔共和国 *+376 安圭拉岛 *+1264 安提瓜和巴布达 *+1268 阿根廷 *+54 亚美尼亚 *+374 阿森松 *+247 澳大利亚 *+61 奥地利 *+43 阿塞拜疆 *+994 巴哈马 *+1242 巴林 *+973 孟加拉国 *+880 巴巴多斯 *+1246 白俄罗斯 *+375 比利时 *+32 伯利兹 *+501 贝宁 *+229 百慕大群岛 *+1441 玻利维亚 *+591 博茨瓦纳 *+267 巴西 *+55 文莱 *+673 保加利亚 *+359 布基纳法索 *+226 缅甸 *+95 布隆迪 *+257 喀麦隆 *+237 加拿大 *+1 开曼群岛 *+1345 中非共和国 *+236 乍得 *+235 智利 *+56 中国 *+86 哥伦比亚 *+57 刚果 *+242 库克群岛 *+682 哥斯达黎加 *+506 古巴 *+53 塞浦路斯 *+357 捷克 *+420 丹麦 *+45 吉布提 *+253 多米尼加共和国 *+1890 厄瓜多尔 *+593 埃及 *+20 萨尔瓦多 *+503 爱沙尼亚 *+372 埃塞俄比亚 *+251 斐济 *+679 芬兰 *+358 法国 *+33 法属圭亚那 *+594 加蓬 *+241 冈比亚 *+220 格鲁吉亚 *+995 德国 *+49 加纳 *+233 直布罗陀 *+350 希腊 *+30 格林纳达 *+1809 关岛 *+1671 危地马拉 *+502 几内亚 *+224 圭亚那 *+592 海地 *+509 洪都拉斯 *+504 香港 *+852 匈牙利 *+36 冰岛 *+354 印度 *+91 印度尼西亚 *+62 伊朗 *+98 伊拉克 *+964 爱尔兰 *+353 以色列 *+972 意大利 *+39 科特迪瓦 *+225 牙买加 *+1876 日本 *+81 约旦 *+962 柬埔寨 *+855 哈萨克斯坦 *+327 肯尼亚 *+254 韩国 *+82 科威特 *+965 吉尔吉斯坦 *+331 老挝 *+856 拉脱维亚 *+371 黎巴嫩 *+961 莱索托 *+266 利比里亚 *+231 利比亚 *+218 列支敦士登 *+423 立陶宛 *+370 卢森堡 *+352 澳门 *+853 马达加斯加 *+261 马拉维 *+265 马来西亚 *+60 马尔代夫 *+960 马里 *+223 马耳他 *+356 马里亚那群岛 *+1670 马提尼克 *+596 毛里求斯 *+230 墨西哥 *+52 摩尔多瓦 *+373 摩纳哥 *+377 蒙古 *+976 蒙特塞拉特岛 *+1664 摩洛哥 *+212 莫桑比克 *+258 纳米比亚 *+264 瑙鲁 *+674 尼泊尔 *+977 荷属安的列斯 *+599 荷兰 *+31 新西兰 *+64 尼加拉瓜 *+505 尼日尔 *+227 尼日利亚 *+234 朝鲜 *+850 挪威 *+47 阿曼 *+968 巴基斯坦 *+92 巴拿马 *+507 巴布亚新几内亚 *+675 巴拉圭 *+595 秘鲁 *+51 菲律宾 *+63 波兰 *+48 法属玻利尼西亚 *+689 葡萄牙 *+351 波多黎各 *+1787 卡塔尔 *+974 留尼旺 *+262 罗马尼亚 *+40 俄罗斯 *+7 圣卢西亚 *+1758 圣文森特岛 *+1784 东萨摩亚(美) *+684 西萨摩亚 *+685 圣马力诺 *+378 圣多美和普林西比 *+239 沙特阿拉伯 *+966 塞内加尔 *+221 塞舌尔 *+248 塞拉利昂 *+232 新加坡 *+65 斯洛伐克 *+421 斯洛文尼亚 *+386 所罗门群岛 *+677 索马里 *+252 南非 *+27 西班牙 *+34 斯里兰卡 *+94 圣卢西亚 *+1758 圣文森特 *+1784 苏丹 *+249 苏里南 *+597 斯威士兰 *+268 瑞典 *+46 瑞士 *+41 叙利亚 *+963 台湾省 *+886 塔吉克斯坦 *+992 坦桑尼亚 *+255 泰国 *+66 多哥 *+228 汤加 *+676 特立尼达和多巴哥 *+1809 突尼斯 *+216 土耳其 *+90 土库曼斯坦 *+993 乌干达 *+256 乌克兰 *+380 阿拉伯联合酋长国 *+971 英国 *+44 美国 *+1 乌拉圭 *+598 乌兹别克斯坦 *+233 委内瑞拉 *+58 越南 *+84 也门 *+967 南斯拉夫 *+381 南非 *+27 津巴布韦 *+263 扎伊尔 *+243 赞比亚 *+260
>北京河北山东上海广东安徽福建甘肃广西贵州海南河南黑龙江湖北湖南吉林江苏江西辽宁内蒙古宁夏青海山西陕西四川天津西藏新疆云南浙江重庆台湾香港澳门西城区东城区昌平区海淀区崇文区宣武区顺义区大兴区怀柔区延庆县朝阳区丰台区石景山区门头沟区房山区通州区平谷区密云县保定邯郸沧州邢台廊坊承德张家口衡水秦皇岛石家庄唐山邹城济南青岛烟台淄博枣庄滨州德州聊城临沂菏泽莱芜东营潍坊济宁泰安威海日照黄浦区浦东新区徐汇区长宁区静安区卢湾区嘉定区金山区松江区青浦区奉贤区崇明县普陀区闸北区虹口区杨浦区闵行区宝山区深圳广州东莞珠海汕头佛山潮州揭阳云浮梅州汕尾河源阳江清远中山韶关湛江肇庆江门茂名惠州合肥芜湖蚌埠淮南安庆阜阳亳州巢湖六安铜陵马鞍山滁州黄山宿州淮北福安福清晋江石狮福州长乐龙岩宁德厦门莆田三明泉州漳州南平庆阳张掖兰州金昌白银天水酒泉柳州桂林梧州北海防城港钦州崇左南宁贵港玉林百色贺州河池来宾六盘水遵义安顺铜仁毕节贵阳海口三亚郑州平顶山洛阳商丘安阳三门峡周口驻马店南阳信阳灵宝新乡许昌鹤壁焦作濮阳漯河齐齐哈尔牡丹江佳木斯大庆鸡西双鸭山伊春七台河鹤岗黑河绥化哈尔滨武汉黄石十堰荆州宜昌襄阳汉口襄樊鄂州荆门孝感黄冈咸宁随州长沙株洲湘潭衡阳邵阳永州怀化岳阳张家界益阳常德娄底郴州吉林四平辽源通化白山延边延吉长春松原白城南京苏州常州无锡徐州南通吴江宜兴张家港宿迁常熟江阴靖江昆山太仓连云港淮安盐城扬州镇江泰州南昌上饶九江萍乡新余鹰潭赣州宜春景德镇吉安抚州沈阳大连鞍山抚顺本溪丹东朝阳葫芦岛锦州营口阜新辽阳盘锦铁岭包头乌海赤峰通辽鄂尔多斯呼伦贝尔巴彦淖尔乌兰察布兴安盟 锡林郭勒盟 阿拉善盟 呼和浩特银川石嘴山吴忠固原中卫西宁玉树藏族自...海西蒙古族...海北藏族自...黄南藏族自...海南藏族自... 果洛藏族自...太原大同阳泉长治晋城朔州晋中运城忻州临汾吕梁西安宝鸡咸阳渭南铜川延安榆林汉中安康商洛成都自贡攀枝花泸州德阳绵阳阿坝藏族羌... 甘孜藏族自...凉山彝族自... 眉山广安达州雅安巴中资阳广元遂宁内江乐山南充宜宾和平区河东区河西区南开区河北区红桥区静海县蓟县东丽区西青区北辰区武清区宝坻区宁河县昌都地区林芝地区 山南地区 日喀则地区 那曲地区阿里地区 拉萨克拉玛依吐鲁番地区哈密地区阿克苏地区喀什地区 和田地区巴州昌吉奎屯石河子伊犁乌鲁木齐阿勒泰地区昌吉回族自...博尔塔拉蒙...巴音郭楞蒙...克孜勒苏柯...伊犁哈萨克...昆明曲靖玉溪保山昭通丽江西双版纳德宏怒江迪庆普洱临沧楚雄大理红河文山杭州宁波温州嘉兴湖州绍兴嵊州温岭萧山义乌永康诸暨富阳海宁乐清临海瑞安上虞金华衢州舟山台州丽水东阳渝中区大渡口区江北区沙坪坝区合川区渝北区秀山县巫溪县巫山县奉节县武隆县云阳县石柱县城口县彭水县梁平县酉阳县开县大足区荣昌县璧山县垫江县丰都县忠县南岸区长寿区江津区綦江区潼南县铜梁县永川区南川区九龙坡区万州区涪陵区黔江区台北台南高雄台湾香港澳门
================================================
FILE: app/src/main/res/values/attrs.xml
================================================
================================================
FILE: app/src/main/res/values/colors.xml
================================================
#B6DA53#393A3F#F6EBE6#fcfcfc#c0c0c0#666667#D4D4D4#AD9149#88AD9149#d4d4d4#b5b5b6#FF000000#ff99cc00#00000000#ff000000#ffffffff#666666#f3f3f3#666666#1a000000#77000000#ffbebebe#3F51B5#303030#FF4081#D3B548#fcfcfc#D4D4D4
================================================
FILE: app/src/main/res/values/dimens.xml
================================================
48dp48dp5dp17dp12sp18sp18sp
================================================
FILE: app/src/main/res/values/strings.xml
================================================
[条]YiChatLite会话已读送达按住说话发送图片拍照通讯录手指上滑,取消发送松开手指,取消发送退出登录确定取消提示搜录音失败,请重试!同一帐号已在其他设备登录设置新消息提醒开启新消息通知新消息设置常用设置声音震动聊天设置使用扬声器播放语音通讯录黑名单诊断iOS离线推送昵称SD卡不存在,不能拍照找不到图片发送语音需要sdcard支持无录音权限录音时间太短发送失败,请检测服务器是否连接登录失败下线通知正在退出登录..正在下载语音,稍后点击[有人@我] 允许聊天室群主离开个人资料天前小时前刚刚复制删除当前网络不可用,请检查网络设置退出群组时删除聊天数据自动同意群组加群邀请视频自适应码率编码连麦发送登录中...账号不存在密码不正确账号已被禁用服务器繁忙请重试...登录成功手机号不能为空密码不能为空请输入正确的手机号码!手机号码格式不正确!我是点击上面的按钮,即表示你同意《YiChat软件许可及服务协议》登录密码用户注册确认密码昵称验证码已经发送获取验证码两次输入的密码不一致,请重新输入!正在注册...注册成功!注册失败!+86正在重置密码...密码重置成功!密码重置失败!新密码不能为空!手机号不能为空该手机号码已被注册...相册发起群聊扫一扫新的朋友添加好友我发现YiChat号/手机号国家中国你的手机号码填写密码找回密码使用手机号登录例如:陈晨验证码新密码头像性别男女个性签名更改名字详细资料手机号发送消息添加到通讯录你需要发送验证申请,等对方通过群聊发送请求成功,等待对方验证请求添加好友失败!已拒绝移入黑名单成功移入黑名单失败正在删除...删除失败:正在移入黑名单...正在发送请求...连接不到聊天服务器移入到黑名单?已同意你的好友请求请求加你为好友正在同意...删除联系人更新成功YiChat号:我的YiChat号:未设置地区国家或地区YiChat号正在加载资料...正在查找联系人...用户不存在 服务器繁忙请重试...搜索正在更新...更新失败,code:未填写修改昵称修改YiChat号修改个人签名YiChat名不能包含中文不能超过30个字符"二维码/条码 扫描"扫描中...无效二维码扫面二维码图片重置扫描我的身份二维码可进行二维码或条形码扫描\n请使用下方扫描框对准商户终端二维码\n或者机具条形码进行扫描请求加为好友同意好友成功!同意好友失败已拒绝你的好友申请申请理由:已添加接受被拒绝保存好名字可以让你的好朋友更容易记得你退出登录失败!检查更新正在查询更新...有新版本已经是最新版本了!现在升级以后再说朋友圈重置密码请输入登录手机号正在加载....删除成功!聊天信息体验Pro版Github开源地址开源中国开源地址码云开源地址现在升级(强制更新)转发撤回确定复制并发送这条消息吗?正在撤回...撤回失败!超过2分钟的消息不支持撤回!正在复制...复制成功!复制失败!请选择联系人!确定转发给1人吗?确定转发这条消息?获取转发信息中....重新发送这条消息吗?置顶会话取消置顶暂无更多消息!get the permission successfull 获取权限失败未授权的权限找一找加载失败,请重试!暂无更多数据!关闭YiChat退出当前账号15分钟前30分钟前1小时前个联系人Open source version only single chat, no group chat!Waiting to do somethings!对方撤回了一条消息你撤回了一条消息%s撤回了一条消息
================================================
FILE: app/src/main/res/values/styles.xml
================================================
================================================
FILE: app/src/main/res/values-hdpi/dimens.xml
================================================
14sp19sp
================================================
FILE: app/src/main/res/values-v21/styles.xml
================================================
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Fri Jun 09 16:25:15 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
================================================
FILE: gradle.properties
================================================
## Project-wide Gradle settings.
#
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Tue May 23 16:51:55 CST 2017
systemProp.http.proxyHost=127.0.0.1
org.gradle.jvmargs=-Xmx1536m
systemProp.http.proxyPort=1080
android.useDeprecatedNdk=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: settings.gradle
================================================
include ':app'