version:2.3

fix:
update:接口优化,更换图标,增加可折叠TextView
This commit is contained in:
2023-01-09 10:01:19 +08:00
parent 39d0f0b597
commit 6540365e9f
17 changed files with 453 additions and 216 deletions

View File

@@ -110,7 +110,7 @@ public class MainActivity extends BaseActivity implements MainContact.MainView {
mFragments.add(mCustomFragment);
mMainPresenter.getSystemSettings();
mMainPresenter.getAdminSnSetting();
ArrayList<DesktopIcon> desktopIcons = ApkUtils.queryFilterAppInfo(this);
int x = 0;
for (int i = 0; i <= desktopIcons.size(); i++) {
@@ -318,7 +318,6 @@ public class MainActivity extends BaseActivity implements MainContact.MainView {
}
addData();
mMainPresenter.sendRunningInfo();
mMainPresenter.getAdminSnSetting();
}
private static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";

View File

@@ -183,25 +183,19 @@ public class AppListFragment extends BaseFragment {
ToastUtil.show("电话功能被禁用");
return;
} else {
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName());
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName(), desktopIcon.getClassName());
AppUsedTimeUtils.getInstance().setAppPackageName(desktopIcon.getPackageName());
AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis());
SendRunningApp(getActivity());
}
break;
default:
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName());
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName(), desktopIcon.getClassName());
AppUsedTimeUtils.getInstance().setAppPackageName(desktopIcon.getPackageName());
AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis());
SendRunningApp(getActivity());
}
}
if (desktopIcon != null) {
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName());
AppUsedTimeUtils.getInstance().setAppPackageName(desktopIcon.getPackageName());
AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis());
SendRunningApp(getActivity());
}
}
@Override

View File

@@ -521,7 +521,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
cl_appstore.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ApkUtils.openApp(mContext, "com.uiuios.appstore");
ApkUtils.openPackage(mContext, "com.uiuios.appstore");
}
});
cl_wifi.setOnClickListener(new View.OnClickListener() {
@@ -624,31 +624,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
}
private void checkContact() {
NetInterfaceManager.getInstance().getContactList(new NetInterfaceManager.ContactCallback() {
@Override
public void setContact(List<Contact> contactList) {
// if (contactList == null || contactList.size() == 0) {
// showNoData("温馨提示", "请在小程序上设置通讯录");
// } else {
//
// }
}
@Override
public void setEmergencyContact(List<Contact> emergencyContact) {
}
@Override
public void setEmpty() {
// showNoData("温馨提示", "请在小程序上设置通讯录");
}
@Override
public void onComplete() {
startActivity(new Intent(mContext, ContactActivity.class));
}
});
startActivity(new Intent(mContext, ContactActivity.class));
}
private void initData() {
@@ -681,7 +657,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
}
});
initAmap();
// getAlarmClock();
getAlarmClock();
}
@Override
@@ -698,7 +674,6 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
public void onResume() {
super.onResume();
// setAlarm();
getAlarmClock();
setSosNumber();
setQuickApp();
checkActivation();
@@ -707,8 +682,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
private void checkActivation() {
int activation = Settings.Global.getInt(mContext.getContentResolver(), "uiui_activation", 0);
if (activation == 0) {
tv_name.setText("" +
"激活");
tv_name.setText("激活");
} else {
tv_name.setText("已激活");
}
@@ -763,7 +737,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
dialog.setMessage("绑定手机才能使用");
dialog.show();
} else {
ApkUtils.openApp(mContext, "com.uiui.health");
ApkUtils.openPackage(mContext, "com.uiui.health");
SchemeUtils.openScheme(mContext, uri);
}
}

View File

@@ -355,7 +355,7 @@ public class NetInterfaceManager {
public void getActivityList(boolean refresh, BehaviorSubject<FragmentEvent> lifecycle, ActivitiesListCallback callback) {
ConnectMode connectMode = ConnectMode.ONE_MINUTE;
if (refresh) {
connectMode = ConnectMode.DEFAULT;
connectMode = ConnectMode.ONE_MINUTE;
}
if (ConnectManager.getInstance().isNeedConnect(URLAddress.GET_ACTIVITY_LIST, connectMode)) {
getActivityList(lifecycle, callback);
@@ -463,9 +463,9 @@ public class NetInterfaceManager {
}
public void getDemandList(boolean refresh, BehaviorSubject<FragmentEvent> lifecycle, DemandListCallback callback) {
ConnectMode connectMode = ConnectMode.ONE_MINUTE;
ConnectMode connectMode = ConnectMode.ONE_HOUR;
if (refresh) {
connectMode = ConnectMode.DEFAULT;
connectMode = ConnectMode.ONE_MINUTE;
}
if (ConnectManager.getInstance().isNeedConnect(URLAddress.GET_DEMAND_LIST, connectMode)) {
getDemandList(lifecycle, callback);
@@ -581,9 +581,9 @@ public class NetInterfaceManager {
}
public void getHealthCode(boolean refresh, BehaviorSubject<ActivityEvent> lifecycle, HealthCodeCallback callback) {
ConnectMode connectMode = ConnectMode.ONE_MINUTE;
ConnectMode connectMode = ConnectMode.ONE_HOUR;
if (refresh) {
connectMode = ConnectMode.DEFAULT;
connectMode = ConnectMode.ONE_MINUTE;
}
if (ConnectManager.getInstance().isNeedConnect(URLAddress.GET_HEALTH_CODE, connectMode)) {
getHealthCode(lifecycle, callback);

View File

@@ -13,9 +13,14 @@ import java.util.concurrent.ConcurrentHashMap;
import okhttp3.Interceptor;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
/**
* v1.0 2022-07-15 16:16:52
*/
public class RepeatRequestInterceptor implements Interceptor {
private static final String TAG = RepeatRequestInterceptor.class.getSimpleName();
@@ -26,13 +31,18 @@ public class RepeatRequestInterceptor implements Interceptor {
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
ResponseBody responseBody = response.body();
Response response = chain.proceed(chain.request());
String content = response.body().string();
if (BuildConfig.DEBUG)
Log.e(TAG, "请求体返回:| Response:" + content);
//会消费请求,导致请求多次
String content = responseBody.string();
// Response copy = response.newBuilder().body(responseBody).build();
ResponseBody copy = ResponseBody.create(responseBody.contentType(), content);
if (BuildConfig.DEBUG) {
// Log.e(TAG, "请求体返回:| Response: " + request.url().encodedPath() + "\t body: " + content);
}
//相同的请求
String requestKey = MD5Util.getUpperMD5Str(request.method() + request.url().toString() + request.body());
String requestKey = MD5Util.getUpperMD5Str(request.method() + request.url().toString() + requestBodyToString(request.body()));
long time = System.currentTimeMillis();//请求时间
try {
if (requestIdsMap.size() > 0 && requestIdsMap.containsKey(requestKey)) {
@@ -48,7 +58,7 @@ public class RepeatRequestInterceptor implements Interceptor {
log("注册请求:", requestKey, request);
// RepeatRequestInterceptor.Builder builder = request.newBuilder();
// builder.addHeader("header", jsonObject.toString());
return chain.proceed(request);
return response.newBuilder().body(copy).build();
} catch (IOException e) {
Log.e(TAG, "intercept: " + e.getMessage());
throw e;
@@ -78,8 +88,20 @@ public class RepeatRequestInterceptor implements Interceptor {
}
return buffer.readUtf8();
} catch (Exception e) {
return "-" + e.getMessage();
return "-";
}
}
private static String requestBodyToString(RequestBody body) {
try {
final Buffer buffer = new Buffer();
body.writeTo(buffer);
if (buffer.size() > 4096) {
return "-too long";
}
return buffer.readUtf8();
} catch (Exception e) {
return "-";
}
}
}

View File

@@ -23,9 +23,9 @@ import com.uiuios.aios.bean.AlarmClockData;
import com.uiuios.aios.bean.BaseResponse;
import com.uiuios.aios.network.NetInterfaceManager;
import com.uiuios.aios.utils.ApkUtils;
import com.uiuios.aios.utils.AppUsedTimeUtils;
import com.uiuios.aios.utils.CmdUtil;
import com.uiuios.aios.utils.ForegroundAppUtil;
import com.uiuios.aios.utils.AppUsedTimeUtils;
import com.uiuios.aios.utils.ToastUtil;
import com.uiuios.aios.utils.Utils;
@@ -110,6 +110,9 @@ public class MainService extends BaseService implements MainSContact.MainSView,
if (mTimeChangedReceiver != null) {
unregisterReceiver(mTimeChangedReceiver);
}
if (lockScreenReceiver != null) {
unregisterReceiver(lockScreenReceiver);
}
}
@Override
@@ -418,7 +421,7 @@ public class MainService extends BaseService implements MainSContact.MainSView,
@Download.onTaskComplete
void taskComplete(DownloadTask task) {
//在这里处理任务完成的状态
Log.e(TAG, "taskComplete: "+task.getFilePath() );
Log.e(TAG, "taskComplete: " + task.getFilePath());
}
@Download.onTaskFail

View File

@@ -327,6 +327,20 @@ public class ApkUtils {
return false;
}
public static boolean openPackage(Context context, String packageName, String className) {
if (TextUtils.isEmpty(className)) {
return openPackage(context, packageName);
}
ComponentName cn = new ComponentName(packageName, className);
Intent intent = new Intent();
intent.setComponent(cn);
if (context != null) {
context.startActivity(intent);
return true;
}
return false;
}
public static Context getPackageContext(Context context, String packageName) {
Context pkgContext = null;
if (context.getPackageName().equals(packageName)) {

View File

@@ -1,135 +0,0 @@
package com.uiuios.aios.view;
import android.content.Context;
import android.graphics.Rect;
import android.text.Layout;
import android.text.StaticLayout;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
public class ExpandTextView extends AppCompatTextView {
/**
* true展开false收起
*/
boolean mExpanded;
/**
* 状态回调
*/
Callback mCallback;
/**
* 源文字内容
*/
String mText = "";
/**
* 最多展示的行数
*/
final int maxLineCount = 3;
/**
* 省略文字
*/
final String ellipsizeText = "...";
public ExpandTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 文字计算辅助工具
StaticLayout sl = new StaticLayout(mText, getPaint(), getMeasuredWidth() - getPaddingLeft() - getPaddingRight()
, Layout.Alignment.ALIGN_CENTER, 1, 0, true);
// 总计行数
int lineCount = sl.getLineCount();
if (lineCount > maxLineCount) {
if (mExpanded) {
setText(mText);
mCallback.onExpand();
} else {
lineCount = maxLineCount;
// 省略文字的宽度
float dotWidth = getPaint().measureText(ellipsizeText);
// 找出第 showLineCount 行的文字
int start = sl.getLineStart(lineCount - 1);
int end = sl.getLineEnd(lineCount - 1);
String lineText = mText.substring(start, end);
// 将第 showLineCount 行最后的文字替换为 ellipsizeText
int endIndex = 0;
for (int i = lineText.length() - 1; i >= 0; i--) {
String str = lineText.substring(i, lineText.length());
// 找出文字宽度大于 ellipsizeText 的字符
if (getPaint().measureText(str) >= dotWidth) {
endIndex = i;
break;
}
}
// 新的第 showLineCount 的文字
String newEndLineText = lineText.substring(0, endIndex) + ellipsizeText;
// 最终显示的文字
setText(mText.substring(0, start) + newEndLineText);
mCallback.onCollapse();
}
} else {
setText(mText);
mCallback.onLoss();
}
// 重新计算高度
int lineHeight = 0;
for (int i = 0; i < lineCount; i++) {
Rect lineBound = new Rect();
sl.getLineBounds(i, lineBound);
lineHeight += lineBound.height();
}
lineHeight += getPaddingTop() + getPaddingBottom();
setMeasuredDimension(getMeasuredWidth(), lineHeight);
}
/**
* 设置要显示的文字以及状态
* @param text
* @param expanded true展开false收起
* @param callback
*/
public void setText(String text, boolean expanded, Callback callback) {
mText = text;
mExpanded = expanded;
mCallback = callback;
// 设置要显示的文字,这一行必须要,否则 onMeasure 宽度测量不正确
setText(text);
}
/**
* 展开收起状态变化
* @param expanded
*/
public void setChanged(boolean expanded) {
mExpanded = expanded;
requestLayout();
}
public interface Callback {
/**
* 展开状态
*/
void onExpand();
/**
* 收起状态
*/
void onCollapse();
/**
* 行数小于最小行数,不满足展开或者收起条件
*/
void onLoss();
}
}

View File

@@ -0,0 +1,358 @@
package com.uiuios.aios.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver;
import android.widget.TextView;
import androidx.appcompat.widget.AppCompatTextView;
import com.uiuios.aios.R;
/**
* Created by zhangzhihao on 2018/6/28 10:26.
* 折叠textView
*/
public class FoldTextView extends AppCompatTextView {
private static final String TAG = "FoldTextView";
private static final String ELLIPSIZE_END = "...";
private static final int MAX_LINE = 4;
private static final String EXPAND_TIP_TEXT = " 收起全文";
private static final String FOLD_TIP_TEXT = "全文";
private static final int TIP_COLOR = 0xFFFFFFFF;
/**
* 全文显示的位置
*/
private static final int END = 0;
private int mShowMaxLine;
/**
* 折叠文本
*/
private String mFoldText;
/**
* 展开文本
*/
private String mExpandText;
/**
* 原始文本
*/
private CharSequence mOriginalText;
/**
* 是否展开
*/
private boolean isExpand;
/**
* 全文显示的位置
*/
private int mTipGravity;
/**
* 全文文字的颜色
*/
private int mTipColor;
/**
* 全文是否可点击
*/
private boolean mTipClickable;
private boolean flag;
private Paint mPaint;
/**
* 展开后是否显示文字提示
*/
private boolean isShowTipAfterExpand;
/**
* 提示文字坐标
*/
float minX;
float maxX;
float minY;
float maxY;
/**
* 收起全文不在一行显示时
*/
float middleY;
/**
* 原始文本的行数
*/
int originalLineCount;
/**
* 点击时间
*/
private long clickTime;
/**
* 是否超过最大行数
*/
private boolean isOverMaxLine;
private onTipClickListener onTipClickListener;
public FoldTextView(Context context) {
this(context, null);
}
public FoldTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@Override
public void setTextColor(int color) {
super.setTextColor(color);
}
public FoldTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mShowMaxLine = MAX_LINE;
if (attrs != null) {
TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.FoldTextView);
mShowMaxLine = arr.getInt(R.styleable.FoldTextView_showMaxLine, MAX_LINE);
mTipGravity = arr.getInt(R.styleable.FoldTextView_tipGravity, END);
mTipColor = arr.getColor(R.styleable.FoldTextView_tipColor, TIP_COLOR);
mTipClickable = arr.getBoolean(R.styleable.FoldTextView_tipClickable, false);
mFoldText = arr.getString(R.styleable.FoldTextView_foldText);
mExpandText = arr.getString(R.styleable.FoldTextView_expandText);
isShowTipAfterExpand = arr.getBoolean(R.styleable.FoldTextView_showTipAfterExpand, false);
arr.recycle();
}
if (TextUtils.isEmpty(mExpandText)) {
mExpandText = EXPAND_TIP_TEXT;
}
if (TextUtils.isEmpty(mFoldText)) {
mFoldText = FOLD_TIP_TEXT;
}
if (mTipGravity == END) {
mFoldText = " ".concat(mFoldText);
}
mPaint = new Paint();
mPaint.setTextSize(getTextSize());
mPaint.setColor(mTipColor);
}
@Override
public void setText(final CharSequence text, final TextView.BufferType type) {
mOriginalText = text;
if (TextUtils.isEmpty(text) || mShowMaxLine == 0) {
super.setText(text, type);
} else if (isExpand) {
//文字展开
SpannableStringBuilder spannable = new SpannableStringBuilder(mOriginalText);
if (isShowTipAfterExpand) {
spannable.append(mExpandText);
spannable.setSpan(new ForegroundColorSpan(mTipColor), spannable.length() - mExpandText.length(), spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
super.setText(spannable, type);
int mLineCount = getLineCount();
Layout layout = getLayout();
minX = getPaddingLeft() + layout.getPrimaryHorizontal(spannable.toString().lastIndexOf(mExpandText.charAt(0)) - 1);
maxX = getPaddingLeft() + layout.getSecondaryHorizontal(spannable.toString().lastIndexOf(mExpandText.charAt(mExpandText.length() - 1)) + 1);
Rect bound = new Rect();
if (mLineCount > originalLineCount) {
//不在同一行
layout.getLineBounds(originalLineCount - 1, bound);
minY = getPaddingTop() + bound.top;
middleY = minY + getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent;
maxY = middleY + getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent;
} else {
//同一行
layout.getLineBounds(originalLineCount - 1, bound);
minY = getPaddingTop() + bound.top;
maxY = minY + getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent;
}
} else {
if (!flag) {
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
getViewTreeObserver().removeOnPreDrawListener(this);
flag = true;
formatText(text, type);
return true;
}
});
} else {
formatText(text, type);
}
}
}
private void formatText(CharSequence text, final TextView.BufferType type) {
Layout layout = getLayout();
if (layout == null || !layout.getText().equals(mOriginalText)) {
super.setText(mOriginalText, type);
layout = getLayout();
}
if (layout == null) {
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
translateText(getLayout(), type);
}
});
} else {
translateText(layout, type);
}
}
private void translateText(Layout layout, TextView.BufferType type) {
originalLineCount = layout.getLineCount();
if (layout.getLineCount() > mShowMaxLine) {
isOverMaxLine = true;
SpannableStringBuilder span = new SpannableStringBuilder();
int start = layout.getLineStart(mShowMaxLine - 1);
int end = layout.getLineEnd(mShowMaxLine - 1);
if (mTipGravity == END) {
TextPaint paint = getPaint();
StringBuilder builder = new StringBuilder(ELLIPSIZE_END).append(mFoldText);
end -= paint.breakText(mOriginalText, start, end, false, paint.measureText(builder.toString()), null);
float x = getWidth() - getPaddingLeft() - getPaddingRight() - getTextWidth(mFoldText);
while (layout.getPrimaryHorizontal(end - 1) + getTextWidth(mOriginalText.subSequence(end - 1, end).toString()) < x) {
end++;
}
end--;
} else {
end--;
}
CharSequence ellipsize = mOriginalText.subSequence(0, end);
span.append(ellipsize);
span.append(ELLIPSIZE_END);
if (mTipGravity != END) {
span.append("\n");
}
super.setText(span, type);
} else {
isOverMaxLine = false;
}
}
public void setShowMaxLine(int mShowMaxLine) {
this.mShowMaxLine = mShowMaxLine;
}
public void setFoldText(String mFoldText) {
this.mFoldText = mFoldText;
}
public void setExpandText(String mExpandText) {
this.mExpandText = mExpandText;
}
public void setTipGravity(int mTipGravity) {
this.mTipGravity = mTipGravity;
}
public void setTipColor(int mTipColor) {
this.mTipColor = mTipColor;
}
public void setTipClickable(boolean mTipClickable) {
this.mTipClickable = mTipClickable;
}
public void setShowTipAfterExpand(boolean showTipAfterExpand) {
isShowTipAfterExpand = showTipAfterExpand;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isOverMaxLine && !isExpand) {
//折叠
if (mTipGravity == END) {
minX = getWidth() - getPaddingLeft() - getPaddingRight() - getTextWidth(mFoldText);
maxX = getWidth() - getPaddingLeft() - getPaddingRight();
minY = getHeight() - (getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent) - getPaddingBottom();
maxY = getHeight() - getPaddingBottom();
canvas.drawText(mFoldText, minX,
getHeight() - getPaint().getFontMetrics().descent - getPaddingBottom(), mPaint);
} else {
minX = getPaddingLeft();
maxX = minX + getTextWidth(mFoldText);
minY = getHeight() - (getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent) - getPaddingBottom();
maxY = getHeight() - getPaddingBottom();
canvas.drawText(mFoldText, minX, getHeight() - getPaint().getFontMetrics().descent - getPaddingBottom(), mPaint);
}
}
}
private float getTextWidth(String text) {
Paint paint = getPaint();
return paint.measureText(text);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mTipClickable) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
clickTime = System.currentTimeMillis();
if (!isClickable()) {
if (isInRange(event.getX(), event.getY())) {
return true;
}
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
long delTime = System.currentTimeMillis() - clickTime;
clickTime = 0L;
if (delTime < ViewConfiguration.getTapTimeout() && isInRange(event.getX(), event.getY())) {
isExpand = !isExpand;
setText(mOriginalText);
if (onTipClickListener != null) {
onTipClickListener.onTipClick(isExpand);
}
return true;
}
break;
default:
break;
}
}
return super.onTouchEvent(event);
}
private boolean isInRange(float x, float y) {
if (minX < maxX) {
return x >= minX && x <= maxX && y >= minY && y <= maxY;
} else {
return x <= maxX && y >= middleY && y <= maxY || x >= minX && y >= minY && y <= middleY;
}
}
public FoldTextView setExpand(boolean expand) {
isExpand = expand;
return this;
}
public FoldTextView setOnTipClickListener(FoldTextView.onTipClickListener onTipClickListener) {
this.onTipClickListener = onTipClickListener;
return this;
}
public interface onTipClickListener {
void onTipClick(boolean flag);
}
}