Compare commits
11 Commits
contacts-v
...
contacts-v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3535df8b3e | ||
|
|
bd4ba7b291 | ||
|
|
9ff8b1ed80 | ||
|
|
859238a173 | ||
|
|
53eced104e | ||
|
|
b45119b487 | ||
|
|
fdddde33b5 | ||
|
|
f263733609 | ||
|
|
51a1cf1e26 | ||
|
|
093772c824 | ||
|
|
bf3e9bdc91 |
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Sun Mar 02 18:48:57 HKT 2025
|
#Wed Mar 05 17:21:57 HKT 2025
|
||||||
stageCount=6
|
stageCount=10
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=1.0
|
baseVersion=1.0
|
||||||
publishVersion=1.0.5
|
publishVersion=1.0.9
|
||||||
buildCount=0
|
buildCount=0
|
||||||
baseBetaVersion=1.0.6
|
baseBetaVersion=1.0.10
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ import cc.winboll.studio.libappbase.bean.APPInfo;
|
|||||||
import com.hjq.toast.ToastUtils;
|
import com.hjq.toast.ToastUtils;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import cc.winboll.studio.contacts.beans.SettingsModel;
|
||||||
|
import cc.winboll.studio.contacts.views.DuInfoTextView;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
|
||||||
public class SettingsActivity extends AppCompatActivity implements IWinBollActivity {
|
public class SettingsActivity extends AppCompatActivity implements IWinBollActivity {
|
||||||
|
|
||||||
@@ -49,11 +52,21 @@ public class SettingsActivity extends AppCompatActivity implements IWinBollActiv
|
|||||||
int mnStreamMaxVolume;
|
int mnStreamMaxVolume;
|
||||||
int mnStreamVolume;
|
int mnStreamVolume;
|
||||||
Switch mswMainService;
|
Switch mswMainService;
|
||||||
|
static DuInfoTextView _DuInfoTextView;
|
||||||
|
|
||||||
|
// 云盾防御层数量
|
||||||
|
EditText etDunTotalCount;
|
||||||
|
// 防御层恢复时间间隔(秒钟)
|
||||||
|
EditText etDunResumeSecondCount;
|
||||||
|
// 每次恢复防御层数
|
||||||
|
EditText etDunResumeCount;
|
||||||
|
// 是否启用云盾
|
||||||
|
Switch swIsEnableDun;
|
||||||
|
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private PhoneConnectRuleAdapter adapter;
|
private PhoneConnectRuleAdapter adapter;
|
||||||
private List<PhoneConnectRuleModel> ruleList;
|
private List<PhoneConnectRuleModel> ruleList;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public APPInfo getAppInfo() {
|
public APPInfo getAppInfo() {
|
||||||
return null;
|
return null;
|
||||||
@@ -104,13 +117,14 @@ public class SettingsActivity extends AppCompatActivity implements IWinBollActiv
|
|||||||
mswMainService.setOnClickListener(new View.OnClickListener(){
|
mswMainService.setOnClickListener(new View.OnClickListener(){
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View arg0) {
|
public void onClick(View arg0) {
|
||||||
|
LogUtils.d(TAG, "mswMainService onClick");
|
||||||
// TODO: Implement this method
|
// TODO: Implement this method
|
||||||
if (mswMainService.isChecked()) {
|
if (mswMainService.isChecked()) {
|
||||||
//ToastUtils.show("Is Checked");
|
//ToastUtils.show("Is Checked");
|
||||||
MainService.startMainService(SettingsActivity.this);
|
MainService.startMainServiceAndSaveStatus(SettingsActivity.this);
|
||||||
} else {
|
} else {
|
||||||
//ToastUtils.show("Not Checked");
|
//ToastUtils.show("Not Checked");
|
||||||
MainService.stopMainService(SettingsActivity.this);
|
MainService.stopMainServiceAndSaveStatus(SettingsActivity.this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -156,15 +170,58 @@ public class SettingsActivity extends AppCompatActivity implements IWinBollActiv
|
|||||||
// 当停止拖动SeekBar时的操作
|
// 当停止拖动SeekBar时的操作
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
recyclerView = findViewById(R.id.recycler_view);
|
recyclerView = findViewById(R.id.recycler_view);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
|
|
||||||
ruleList = Rules.getInstance(this).getPhoneBlacRuleBeanList();
|
ruleList = Rules.getInstance(this).getPhoneBlacRuleBeanList();
|
||||||
|
|
||||||
adapter = new PhoneConnectRuleAdapter(this, ruleList);
|
adapter = new PhoneConnectRuleAdapter(this, ruleList);
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
|
// 设置参数云盾
|
||||||
|
_DuInfoTextView = findViewById(R.id.tv_DunInfo);
|
||||||
|
etDunTotalCount = findViewById(R.id.et_DunTotalCount);
|
||||||
|
etDunResumeSecondCount = findViewById(R.id.et_DunResumeSecondCount);
|
||||||
|
etDunResumeCount = findViewById(R.id.et_DunResumeCount);
|
||||||
|
swIsEnableDun = findViewById(R.id.sw_IsEnableDun);
|
||||||
|
SettingsModel settingsModel = Rules.getInstance(this).getSettingsModel();
|
||||||
|
|
||||||
|
etDunTotalCount.setText(Integer.toString(settingsModel.getDunTotalCount()));
|
||||||
|
etDunResumeSecondCount.setText(Integer.toString(settingsModel.getDunResumeSecondCount()));
|
||||||
|
etDunResumeCount.setText(Integer.toString(settingsModel.getDunResumeCount()));
|
||||||
|
swIsEnableDun.setChecked(settingsModel.isEnableDun());
|
||||||
|
|
||||||
|
boolean isEnableDun = settingsModel.isEnableDun();
|
||||||
|
etDunTotalCount.setEnabled(!isEnableDun);
|
||||||
|
etDunResumeSecondCount.setEnabled(!isEnableDun);
|
||||||
|
etDunResumeCount.setEnabled(!isEnableDun);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifyDunInfoUpdate() {
|
||||||
|
if (_DuInfoTextView != null) {
|
||||||
|
_DuInfoTextView.notifyInfoUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSW_IsEnableDun(View view) {
|
||||||
|
LogUtils.d(TAG, "onSW_IsEnableDun");
|
||||||
|
boolean isEnableDun = swIsEnableDun.isChecked();
|
||||||
|
etDunTotalCount.setEnabled(!isEnableDun);
|
||||||
|
etDunResumeSecondCount.setEnabled(!isEnableDun);
|
||||||
|
etDunResumeCount.setEnabled(!isEnableDun);
|
||||||
|
|
||||||
|
SettingsModel settingsModel = Rules.getInstance(this).getSettingsModel();
|
||||||
|
if (isEnableDun) {
|
||||||
|
settingsModel.setDunTotalCount(Integer.parseInt(etDunTotalCount.getText().toString()));
|
||||||
|
settingsModel.setDunResumeSecondCount(Integer.parseInt(etDunResumeSecondCount.getText().toString()));
|
||||||
|
settingsModel.setDunResumeCount(Integer.parseInt(etDunResumeCount.getText().toString()));
|
||||||
|
}
|
||||||
|
settingsModel.setIsEnableDun(isEnableDun);
|
||||||
|
Rules.getInstance(this).saveDun();
|
||||||
|
Rules.getInstance(this).reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateStreamVolumeTextView() {
|
void updateStreamVolumeTextView() {
|
||||||
@@ -175,6 +232,12 @@ public class SettingsActivity extends AppCompatActivity implements IWinBollActiv
|
|||||||
Intent intent = new Intent(this, UnitTestActivity.class);
|
Intent intent = new Intent(this, UnitTestActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onAddNewConnectionRule(View view) {
|
||||||
|
Rules.getInstance(this).getPhoneBlacRuleBeanList().add(new PhoneConnectRuleModel());
|
||||||
|
Rules.getInstance(this).saveRules();
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
public void onDefaultPhone(View view) {
|
public void onDefaultPhone(View view) {
|
||||||
Intent intent = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
|
Intent intent = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
|
||||||
@@ -198,10 +261,14 @@ public class SettingsActivity extends AppCompatActivity implements IWinBollActiv
|
|||||||
public void run() {
|
public void run() {
|
||||||
if (tomCat.downloadBoBullToon()) {
|
if (tomCat.downloadBoBullToon()) {
|
||||||
ToastUtils.show("BoBullToon downlaod OK!");
|
ToastUtils.show("BoBullToon downlaod OK!");
|
||||||
|
MainService.restartMainService(SettingsActivity.this);
|
||||||
|
Rules.getInstance(SettingsActivity.this).reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void onSearchBoBullToonPhone(View view) {
|
public void onSearchBoBullToonPhone(View view) {
|
||||||
TomCat tomCat = TomCat.getInstance(this);
|
TomCat tomCat = TomCat.getInstance(this);
|
||||||
|
|||||||
@@ -19,7 +19,12 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
import cc.winboll.studio.contacts.R;
|
import cc.winboll.studio.contacts.R;
|
||||||
import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel;
|
import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel;
|
||||||
import cc.winboll.studio.contacts.dun.Rules;
|
import cc.winboll.studio.contacts.dun.Rules;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.widget.HorizontalScrollView;
|
||||||
|
import cc.winboll.studio.contacts.views.LeftScrollView;
|
||||||
|
|
||||||
public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
|
|
||||||
@@ -42,10 +47,10 @@ public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.V
|
|||||||
LayoutInflater inflater = LayoutInflater.from(context);
|
LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
if (viewType == VIEW_TYPE_SIMPLE) {
|
if (viewType == VIEW_TYPE_SIMPLE) {
|
||||||
View view = inflater.inflate(R.layout.view_phone_connect_rule_simple, parent, false);
|
View view = inflater.inflate(R.layout.view_phone_connect_rule_simple, parent, false);
|
||||||
return new SimpleViewHolder(view);
|
return new SimpleViewHolder(parent, view);
|
||||||
} else {
|
} else {
|
||||||
View view = inflater.inflate(R.layout.view_phone_connect_rule, parent, false);
|
View view = inflater.inflate(R.layout.view_phone_connect_rule, parent, false);
|
||||||
return new EditViewHolder(view);
|
return new EditViewHolder(parent, view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,15 +58,80 @@ public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.V
|
|||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
|
||||||
final PhoneConnectRuleModel model = ruleList.get(position);
|
final PhoneConnectRuleModel model = ruleList.get(position);
|
||||||
if (holder instanceof SimpleViewHolder) {
|
if (holder instanceof SimpleViewHolder) {
|
||||||
SimpleViewHolder simpleViewHolder = (SimpleViewHolder) holder;
|
final SimpleViewHolder simpleViewHolder = (SimpleViewHolder) holder;
|
||||||
simpleViewHolder.textView.setText(model.getRuleText());
|
String szView = model.getRuleText().trim().equals("")?"[NULL]":model.getRuleText();
|
||||||
simpleViewHolder.button.setOnClickListener(new View.OnClickListener() {
|
simpleViewHolder.tvRuleText.setText(szView);
|
||||||
|
simpleViewHolder.scrollView.setOnActionListener(new LeftScrollView.OnActionListener(){
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onEdit() {
|
||||||
|
simpleViewHolder.scrollView.smoothScrollTo(0, 0);
|
||||||
model.setIsSimpleView(false);
|
model.setIsSimpleView(false);
|
||||||
notifyItemChanged(position);
|
notifyDataSetChanged();
|
||||||
|
//notifyItemChanged(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDelete() {
|
||||||
|
simpleViewHolder.scrollView.smoothScrollTo(0, 0);
|
||||||
|
model.setIsSimpleView(true);
|
||||||
|
ArrayList<PhoneConnectRuleModel> list = Rules.getInstance(context).getPhoneBlacRuleBeanList();
|
||||||
|
list.remove(position);
|
||||||
|
Rules.getInstance(context).saveRules();
|
||||||
|
notifyDataSetChanged();
|
||||||
|
//notifyItemChanged(position);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// simpleViewHolder.editButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
// @Override
|
||||||
|
// public void onClick(View v) {
|
||||||
|
// model.setIsSimpleView(false);
|
||||||
|
// notifyItemChanged(position);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// simpleViewHolder.deleteButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
// @Override
|
||||||
|
// public void onClick(View v) {
|
||||||
|
// model.setIsSimpleView(false);
|
||||||
|
// ArrayList<PhoneConnectRuleModel> list = Rules.getInstance(context).getPhoneBlacRuleBeanList();
|
||||||
|
// list.remove(position);
|
||||||
|
// Rules.getInstance(context).saveRules();
|
||||||
|
// notifyItemChanged(position);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// // 触摸事件处理
|
||||||
|
// simpleViewHolder.contentLayout.setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
// @Override
|
||||||
|
// public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
// switch (event.getAction()) {
|
||||||
|
// case MotionEvent.ACTION_DOWN:
|
||||||
|
// simpleViewHolder.startX = event.getX();
|
||||||
|
// simpleViewHolder.isSwiping = true;
|
||||||
|
// break;
|
||||||
|
// case MotionEvent.ACTION_MOVE:
|
||||||
|
// if (simpleViewHolder.isSwiping) {
|
||||||
|
// float deltaX = simpleViewHolder.startX - event.getX();
|
||||||
|
// if (deltaX > 0) { // 左滑
|
||||||
|
// float translationX = Math.max(-simpleViewHolder.actionLayout.getWidth(), -deltaX);
|
||||||
|
// simpleViewHolder.contentLayout.setTranslationX(translationX);
|
||||||
|
// simpleViewHolder.actionLayout.setVisibility(View.VISIBLE);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case MotionEvent.ACTION_UP:
|
||||||
|
// simpleViewHolder.isSwiping = false;
|
||||||
|
// if (simpleViewHolder.contentLayout.getTranslationX() < -simpleViewHolder.actionLayout.getWidth() / 2) {
|
||||||
|
// // 保持按钮显示
|
||||||
|
// simpleViewHolder.contentLayout.setTranslationX(-actionLayout.getWidth());
|
||||||
|
// } else {
|
||||||
|
// // 恢复原状
|
||||||
|
// simpleViewHolder.contentLayout.animate().translationX(0).setDuration(200).start();
|
||||||
|
// simpleViewHolder.actionLayout.setVisibility(View.INVISIBLE);
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
} else if (holder instanceof EditViewHolder) {
|
} else if (holder instanceof EditViewHolder) {
|
||||||
final EditViewHolder editViewHolder = (EditViewHolder) holder;
|
final EditViewHolder editViewHolder = (EditViewHolder) holder;
|
||||||
editViewHolder.editText.setText(model.getRuleText());
|
editViewHolder.editText.setText(model.getRuleText());
|
||||||
@@ -95,14 +165,21 @@ public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.V
|
|||||||
}
|
}
|
||||||
|
|
||||||
static class SimpleViewHolder extends RecyclerView.ViewHolder {
|
static class SimpleViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView textView;
|
|
||||||
Button button;
|
|
||||||
|
|
||||||
public SimpleViewHolder(@NonNull View itemView) {
|
private final LeftScrollView scrollView;
|
||||||
|
private final TextView tvRuleText;
|
||||||
|
|
||||||
|
|
||||||
|
public SimpleViewHolder(@NonNull ViewGroup parent, @NonNull View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
textView = itemView.findViewById(R.id.text_view);
|
scrollView = itemView.findViewById(R.id.scrollView);
|
||||||
button = itemView.findViewById(R.id.button);
|
//tvRuleText = itemView.findViewById(R.id.ruletext_tv);
|
||||||
|
tvRuleText = new TextView(itemView.getContext());
|
||||||
|
scrollView.setContentWidth(parent.getWidth());
|
||||||
|
//scrollView.setContentWidth(600);
|
||||||
|
scrollView.addContentLayout(tvRuleText);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class EditViewHolder extends RecyclerView.ViewHolder {
|
static class EditViewHolder extends RecyclerView.ViewHolder {
|
||||||
@@ -111,7 +188,7 @@ public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.V
|
|||||||
CheckBox checkBoxEnable;
|
CheckBox checkBoxEnable;
|
||||||
Button buttonConfirm;
|
Button buttonConfirm;
|
||||||
|
|
||||||
public EditViewHolder(@NonNull View itemView) {
|
public EditViewHolder(@NonNull ViewGroup parent, @NonNull View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
editText = itemView.findViewById(R.id.edit_text);
|
editText = itemView.findViewById(R.id.edit_text);
|
||||||
checkBoxAllow = itemView.findViewById(R.id.checkbox_allow);
|
checkBoxAllow = itemView.findViewById(R.id.checkbox_allow);
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package cc.winboll.studio.contacts.beans;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author ZhanGSKen@AliYun.Com
|
||||||
|
* @Date 2025/03/02 19:51:40
|
||||||
|
* @Describe SettingsModel
|
||||||
|
*/
|
||||||
|
import android.util.JsonReader;
|
||||||
|
import android.util.JsonWriter;
|
||||||
|
import cc.winboll.studio.libappbase.BaseBean;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class SettingsModel extends BaseBean {
|
||||||
|
|
||||||
|
public static final String TAG = "SettingsModel";
|
||||||
|
|
||||||
|
// 云盾防御层数量
|
||||||
|
int dunTotalCount;
|
||||||
|
// 当前云盾防御层
|
||||||
|
int dunCurrentCount;
|
||||||
|
// 防御层恢复时间间隔(秒钟)
|
||||||
|
int dunResumeSecondCount;
|
||||||
|
// 每次恢复防御层数
|
||||||
|
int dunResumeCount;
|
||||||
|
// 是否启用云盾
|
||||||
|
boolean isEnableDun;
|
||||||
|
|
||||||
|
public SettingsModel() {
|
||||||
|
this.dunTotalCount = 6;
|
||||||
|
this.dunCurrentCount = 6;
|
||||||
|
this.dunResumeSecondCount = 60;
|
||||||
|
this.dunResumeCount = 1;
|
||||||
|
this.isEnableDun = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SettingsModel(int dunTotalCount, int dunCurrentCount, int dunResumeSecondCount, int dunResumeCount, boolean isEnableDun) {
|
||||||
|
this.dunTotalCount = dunTotalCount;
|
||||||
|
this.dunCurrentCount = dunCurrentCount;
|
||||||
|
this.dunResumeSecondCount = dunResumeSecondCount;
|
||||||
|
this.dunResumeCount = dunResumeCount;
|
||||||
|
this.isEnableDun = isEnableDun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDunTotalCount(int dunTotalCount) {
|
||||||
|
this.dunTotalCount = dunTotalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDunTotalCount() {
|
||||||
|
return dunTotalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDunCurrentCount(int dunCurrentCount) {
|
||||||
|
this.dunCurrentCount = dunCurrentCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDunCurrentCount() {
|
||||||
|
return dunCurrentCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDunResumeSecondCount(int dunResumeSecondCount) {
|
||||||
|
this.dunResumeSecondCount = dunResumeSecondCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDunResumeSecondCount() {
|
||||||
|
return dunResumeSecondCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDunResumeCount(int dunResumeCount) {
|
||||||
|
this.dunResumeCount = dunResumeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDunResumeCount() {
|
||||||
|
return dunResumeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsEnableDun(boolean isEnableDun) {
|
||||||
|
this.isEnableDun = isEnableDun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnableDun() {
|
||||||
|
return isEnableDun;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return SettingsModel.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||||
|
super.writeThisToJsonWriter(jsonWriter);
|
||||||
|
jsonWriter.name("dunTotalCount").value(getDunTotalCount());
|
||||||
|
jsonWriter.name("dunCurrentCount").value(getDunCurrentCount());
|
||||||
|
jsonWriter.name("dunResumeSecondCount").value(getDunResumeSecondCount());
|
||||||
|
jsonWriter.name("dunResumeCount").value(getDunResumeCount());
|
||||||
|
jsonWriter.name("isEnableDun").value(isEnableDun());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
|
||||||
|
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
|
||||||
|
if (name.equals("dunTotalCount")) {
|
||||||
|
setDunTotalCount(jsonReader.nextInt());
|
||||||
|
} else if (name.equals("dunCurrentCount")) {
|
||||||
|
setDunCurrentCount(jsonReader.nextInt());
|
||||||
|
} else if (name.equals("dunResumeSecondCount")) {
|
||||||
|
setDunResumeSecondCount(jsonReader.nextInt());
|
||||||
|
} else if (name.equals("dunResumeCount")) {
|
||||||
|
setDunResumeCount(jsonReader.nextInt());
|
||||||
|
} else if (name.equals("isEnableDun")) {
|
||||||
|
setIsEnableDun(jsonReader.nextBoolean());
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
|
||||||
|
jsonReader.beginObject();
|
||||||
|
while (jsonReader.hasNext()) {
|
||||||
|
String name = jsonReader.nextName();
|
||||||
|
if (!initObjectsFromJsonReader(jsonReader, name)) {
|
||||||
|
jsonReader.skipValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 结束 JSON 对象
|
||||||
|
jsonReader.endObject();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,24 +48,29 @@ public class TomCat {
|
|||||||
.url(zipUrl)
|
.url(zipUrl)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
try {
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
if (!response.isSuccessful()) {
|
if (!response.isSuccessful()) {
|
||||||
throw new IOException("Unexpected code " + response);
|
throw new IOException("Unexpected code " + response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下载 ZIP 文件到临时位置
|
// 下载 ZIP 文件到临时位置
|
||||||
File tempZipFile = File.createTempFile("temp", ".zip");
|
File tempZipFile = File.createTempFile("temp", ".zip");
|
||||||
try (InputStream inputStream = response.body().byteStream();
|
try {
|
||||||
FileOutputStream outputStream = new FileOutputStream(tempZipFile)) {
|
InputStream inputStream = response.body().byteStream();
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(tempZipFile);
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int length;
|
int length;
|
||||||
while ((length = inputStream.read(buffer)) > 0) {
|
while ((length = inputStream.read(buffer)) > 0) {
|
||||||
outputStream.write(buffer, 0, length);
|
outputStream.write(buffer, 0, length);
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解压 ZIP 文件到指定文件夹
|
// 解压 ZIP 文件到指定文件夹
|
||||||
try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(tempZipFile.toPath()))) {
|
try {
|
||||||
|
ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(tempZipFile.toPath()));
|
||||||
ZipEntry zipEntry;
|
ZipEntry zipEntry;
|
||||||
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
|
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
|
||||||
Path targetFilePath = Paths.get(destinationFolder, zipEntry.getName());
|
Path targetFilePath = Paths.get(destinationFolder, zipEntry.getName());
|
||||||
@@ -83,10 +88,15 @@ public class TomCat {
|
|||||||
}
|
}
|
||||||
zipInputStream.closeEntry();
|
zipInputStream.closeEntry();
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除临时 ZIP 文件
|
// 删除临时 ZIP 文件
|
||||||
tempZipFile.delete();
|
tempZipFile.delete();
|
||||||
|
LogUtils.d(TAG, "已更新 BoBullToon 数据");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +104,15 @@ public class TomCat {
|
|||||||
String zipUrl = "https://gitea.winboll.cc//Studio/BoBullToon/archive/main.zip"; // 替换为实际的 ZIP 文件 URL
|
String zipUrl = "https://gitea.winboll.cc//Studio/BoBullToon/archive/main.zip"; // 替换为实际的 ZIP 文件 URL
|
||||||
String destinationFolder = getWorkingFolder().getPath(); // 替换为实际的目标文件夹路径
|
String destinationFolder = getWorkingFolder().getPath(); // 替换为实际的目标文件夹路径
|
||||||
try {
|
try {
|
||||||
|
// 删除旧文件
|
||||||
|
File fOldFolder = new File(destinationFolder);
|
||||||
|
if (fOldFolder.exists()) {
|
||||||
|
deleteFolderRecursive(fOldFolder);
|
||||||
|
fOldFolder.mkdirs();
|
||||||
|
LogUtils.d(TAG, "已清空 BoBullToon 数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新新文件
|
||||||
downloadAndExtractZip(zipUrl, destinationFolder);
|
downloadAndExtractZip(zipUrl, destinationFolder);
|
||||||
LogUtils.d(TAG, "ZIP 文件下载并解压成功。");
|
LogUtils.d(TAG, "ZIP 文件下载并解压成功。");
|
||||||
return true;
|
return true;
|
||||||
@@ -103,6 +122,23 @@ public class TomCat {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 递归删除文件夹及其内容的方法
|
||||||
|
public static void deleteFolderRecursive(File file) {
|
||||||
|
// 判断是否为文件夹
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
// 列出文件夹中的所有文件和子文件夹
|
||||||
|
File[] files = file.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
// 遍历并递归删除每个文件和子文件夹
|
||||||
|
for (File f : files) {
|
||||||
|
deleteFolderRecursive(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 删除文件或空文件夹
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
|
||||||
File getWorkingFolder() {
|
File getWorkingFolder() {
|
||||||
return mContext.getExternalFilesDir(TAG);
|
return mContext.getExternalFilesDir(TAG);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,17 @@ package cc.winboll.studio.contacts.dun;
|
|||||||
* @Describe 云盾防御规则
|
* @Describe 云盾防御规则
|
||||||
*/
|
*/
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import cc.winboll.studio.contacts.activities.SettingsActivity;
|
||||||
import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel;
|
import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel;
|
||||||
|
import cc.winboll.studio.contacts.beans.RingTongBean;
|
||||||
|
import cc.winboll.studio.contacts.beans.SettingsModel;
|
||||||
import cc.winboll.studio.contacts.services.MainService;
|
import cc.winboll.studio.contacts.services.MainService;
|
||||||
import cc.winboll.studio.contacts.utils.RegexPPiUtils;
|
import cc.winboll.studio.contacts.utils.RegexPPiUtils;
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class Rules {
|
public class Rules {
|
||||||
@@ -20,11 +26,13 @@ public class Rules {
|
|||||||
ArrayList<PhoneConnectRuleModel> _PhoneConnectRuleModelList;
|
ArrayList<PhoneConnectRuleModel> _PhoneConnectRuleModelList;
|
||||||
static volatile Rules _Rules;
|
static volatile Rules _Rules;
|
||||||
Context mContext;
|
Context mContext;
|
||||||
|
SettingsModel mSettingsModel;
|
||||||
|
Timer mDunResumeTimer;
|
||||||
|
|
||||||
Rules(Context context) {
|
Rules(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
_PhoneConnectRuleModelList = new ArrayList<PhoneConnectRuleModel>();
|
_PhoneConnectRuleModelList = new ArrayList<PhoneConnectRuleModel>();
|
||||||
loadRules();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized Rules getInstance(Context context) {
|
public static synchronized Rules getInstance(Context context) {
|
||||||
@@ -34,40 +42,143 @@ public class Rules {
|
|||||||
return _Rules;
|
return _Rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reload() {
|
||||||
|
LogUtils.d(TAG, "reload()");
|
||||||
|
loadRules();
|
||||||
|
loadDun();
|
||||||
|
setDunResumTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDunResumTimer() {
|
||||||
|
if (mDunResumeTimer != null) {
|
||||||
|
mDunResumeTimer.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 盾牌恢复定时器
|
||||||
|
mDunResumeTimer = new Timer();
|
||||||
|
mDunResumeTimer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (mSettingsModel.getDunCurrentCount() != mSettingsModel.getDunTotalCount()) {
|
||||||
|
LogUtils.d(TAG, String.format("当前防御值为%d,最大防御值为%d", mSettingsModel.getDunCurrentCount(), mSettingsModel.getDunTotalCount()));
|
||||||
|
int newDunCount = mSettingsModel.getDunCurrentCount() + mSettingsModel.getDunResumeCount();
|
||||||
|
// 设置盾值在[0,DunTotalCount]之内其他值一律重置为 DunTotalCount。
|
||||||
|
newDunCount = (newDunCount > mSettingsModel.getDunTotalCount()) ?mSettingsModel.getDunTotalCount(): newDunCount;
|
||||||
|
mSettingsModel.setDunCurrentCount(newDunCount);
|
||||||
|
LogUtils.d(TAG, String.format("设置防御值为%d", newDunCount));
|
||||||
|
saveDun();
|
||||||
|
SettingsActivity.notifyDunInfoUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000, mSettingsModel.getDunResumeSecondCount() * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
public void loadRules() {
|
public void loadRules() {
|
||||||
_PhoneConnectRuleModelList.clear();
|
_PhoneConnectRuleModelList.clear();
|
||||||
PhoneConnectRuleModel.loadBeanList(mContext, _PhoneConnectRuleModelList, PhoneConnectRuleModel.class);
|
PhoneConnectRuleModel.loadBeanList(mContext, _PhoneConnectRuleModelList, PhoneConnectRuleModel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveRules() {
|
public void saveRules() {
|
||||||
|
LogUtils.d(TAG, String.format("saveRules()"));
|
||||||
PhoneConnectRuleModel.saveBeanList(mContext, _PhoneConnectRuleModelList, PhoneConnectRuleModel.class);
|
PhoneConnectRuleModel.saveBeanList(mContext, _PhoneConnectRuleModelList, PhoneConnectRuleModel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAllowed(String phoneNumber) {
|
public void loadDun() {
|
||||||
// 正则运算预防针
|
mSettingsModel = SettingsModel.loadBean(mContext, SettingsModel.class);
|
||||||
if (!RegexPPiUtils.isPPiOK(phoneNumber)) {
|
if (mSettingsModel == null) {
|
||||||
LogUtils.d(TAG, "RegexPPiUtils.isPPiOK return false.");
|
mSettingsModel = new SettingsModel();
|
||||||
return false;
|
SettingsModel.saveBean(mContext, mSettingsModel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveDun() {
|
||||||
|
LogUtils.d(TAG, String.format("saveDun()"));
|
||||||
|
SettingsModel.saveBean(mContext, mSettingsModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllowed(String phoneNumber) {
|
||||||
|
// 没有启用云盾,默认允许接通任何电话
|
||||||
|
if (!mSettingsModel.isEnableDun()) {
|
||||||
|
LogUtils.d(TAG, String.format("没有启用云盾,默认允许接通任何电话。isAllowed(...) return true"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 以下是云盾防御体系
|
||||||
|
boolean isDefend = false; // 盾牌是否生效
|
||||||
|
boolean isConnect = true; // 防御结果是否连接
|
||||||
|
|
||||||
|
// 如果盾值小于1,则解除防御
|
||||||
|
if (!isDefend && mSettingsModel.getDunCurrentCount() < 1) {
|
||||||
|
// 盾层为1以下,防御解除
|
||||||
|
LogUtils.d(TAG, "盾层为1以下,防御解除");
|
||||||
|
isDefend = true;
|
||||||
|
isConnect = true;
|
||||||
|
LogUtils.d(TAG, String.format("isDefend == %s\nisConnect == %s", isDefend, isConnect));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正则运算预防针
|
||||||
|
if (!isDefend && !RegexPPiUtils.isPPiOK(phoneNumber)) {
|
||||||
|
LogUtils.d(TAG, "正则运算预防针生效。");
|
||||||
|
isDefend = true;
|
||||||
|
isConnect = false;
|
||||||
|
LogUtils.d(TAG, String.format("isDefend == %s\nisConnect == %s", isDefend, isConnect));
|
||||||
|
}
|
||||||
|
|
||||||
// 检验拨不通号码群
|
// 检验拨不通号码群
|
||||||
if (MainService.isPhoneInBoBullToon(phoneNumber)) {
|
if (!isDefend && MainService.isPhoneInBoBullToon(phoneNumber)) {
|
||||||
LogUtils.d(TAG, String.format("PhoneNumber %s\n Is In BoBullToon", phoneNumber));
|
LogUtils.d(TAG, String.format("PhoneNumber %s\n Is In BoBullToon", phoneNumber));
|
||||||
return false;
|
isDefend = true;
|
||||||
|
isConnect = false;
|
||||||
|
LogUtils.d(TAG, String.format("isDefend == %s\nisConnect == %s", isDefend, isConnect));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 正则匹配规则名单校验
|
// 正则匹配规则名单校验
|
||||||
for (int i = 0; i < _PhoneConnectRuleModelList.size(); i++) {
|
if (!isDefend) {
|
||||||
if (_PhoneConnectRuleModelList.get(i).isEnable()) {
|
for (int i = 0; i < _PhoneConnectRuleModelList.size(); i++) {
|
||||||
String regex = _PhoneConnectRuleModelList.get(i).getRuleText();
|
if (_PhoneConnectRuleModelList.get(i).isEnable()) {
|
||||||
if (Pattern.matches(regex, phoneNumber)) {
|
String regex = _PhoneConnectRuleModelList.get(i).getRuleText();
|
||||||
LogUtils.d(TAG, String.format("phoneNumber :%s \nisAllowConnection %s By Rule : %s", phoneNumber, _PhoneConnectRuleModelList.get(i).isAllowConnection(), _PhoneConnectRuleModelList.get(i)));
|
if (Pattern.matches(regex, phoneNumber)) {
|
||||||
return _PhoneConnectRuleModelList.get(i).isAllowConnection();
|
LogUtils.d(TAG, String.format("Phone Number [%s] is matched by rule : %s", phoneNumber, _PhoneConnectRuleModelList.get(i)));
|
||||||
|
isDefend = true;
|
||||||
|
isConnect = _PhoneConnectRuleModelList.get(i).isAllowConnection();
|
||||||
|
LogUtils.d(TAG, String.format("isDefend == %s\nisConnect == %s", isDefend, isConnect));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其他默认接收
|
if (isConnect) {
|
||||||
return true;
|
// 如果防御结果为连接,则恢复防御盾牌最大值层数
|
||||||
|
mSettingsModel.setDunCurrentCount(mSettingsModel.getDunTotalCount());
|
||||||
|
LogUtils.d(TAG, String.format("防御结果为连接,恢复防御盾牌最大值层数 %d", mSettingsModel.getDunTotalCount()));
|
||||||
|
saveDun();
|
||||||
|
SettingsActivity.notifyDunInfoUpdate();
|
||||||
|
} else if (isDefend) {
|
||||||
|
// 如果触发了以上某个防御模块,
|
||||||
|
// 就减少防御盾牌层数。
|
||||||
|
// 每校验一次规则,云盾防御层数减1
|
||||||
|
// 当云盾防御层数为0时,再次进行以下程序段则恢复满值防御。
|
||||||
|
int newDunCount = mSettingsModel.getDunCurrentCount() - 1;
|
||||||
|
LogUtils.d(TAG, String.format("新的防御层数预计为 %d", newDunCount));
|
||||||
|
|
||||||
|
// 保证盾值在[0,DunTotalCount]之内其他值一律重置为 DunTotalCount。
|
||||||
|
if (newDunCount < 0 || newDunCount > mSettingsModel.getDunTotalCount()) {
|
||||||
|
mSettingsModel.setDunCurrentCount(mSettingsModel.getDunTotalCount());
|
||||||
|
LogUtils.d(TAG, String.format("盾值不在[0,%d]区间,恢复防御最大值%d", mSettingsModel.getDunTotalCount(), mSettingsModel.getDunTotalCount()));
|
||||||
|
} else {
|
||||||
|
mSettingsModel.setDunCurrentCount(newDunCount);
|
||||||
|
LogUtils.d(TAG, String.format("设置防御层数为 %d", newDunCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
saveDun();
|
||||||
|
SettingsActivity.notifyDunInfoUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回校验结果
|
||||||
|
LogUtils.d(TAG, String.format("返回校验结果 isConnect == %s", isConnect));
|
||||||
|
return isConnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(String szPhoneConnectRule, boolean isAllowConnection, boolean isEnable) {
|
public void add(String szPhoneConnectRule, boolean isAllowConnection, boolean isEnable) {
|
||||||
@@ -77,4 +188,8 @@ public class Rules {
|
|||||||
public ArrayList<PhoneConnectRuleModel> getPhoneBlacRuleBeanList() {
|
public ArrayList<PhoneConnectRuleModel> getPhoneBlacRuleBeanList() {
|
||||||
return _PhoneConnectRuleModelList;
|
return _PhoneConnectRuleModelList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SettingsModel getSettingsModel() {
|
||||||
|
return mSettingsModel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ public class MainService extends Service {
|
|||||||
mMainReceiver.registerAction(this);
|
mMainReceiver.registerAction(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rules.getInstance(this);
|
Rules.getInstance(this).loadRules();
|
||||||
|
|
||||||
startPhoneCallListener();
|
startPhoneCallListener();
|
||||||
|
|
||||||
@@ -273,14 +273,40 @@ public class MainService extends Service {
|
|||||||
|
|
||||||
public static void stopMainService(Context context) {
|
public static void stopMainService(Context context) {
|
||||||
LogUtils.d(TAG, "stopMainService");
|
LogUtils.d(TAG, "stopMainService");
|
||||||
|
context.stopService(new Intent(context, MainService.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startMainService(Context context) {
|
||||||
|
LogUtils.d(TAG, "startMainService");
|
||||||
|
context.startService(new Intent(context, MainService.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void restartMainService(Context context) {
|
||||||
|
LogUtils.d(TAG, "restartMainService");
|
||||||
|
|
||||||
|
MainServiceBean bean = MainServiceBean.loadBean(context, MainServiceBean.class);
|
||||||
|
if (bean != null && bean.isEnable()) {
|
||||||
|
context.stopService(new Intent(context, MainService.class));
|
||||||
|
// try {
|
||||||
|
// Thread.sleep(1000);
|
||||||
|
// } catch (InterruptedException e) {
|
||||||
|
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||||
|
// }
|
||||||
|
context.startService(new Intent(context, MainService.class));
|
||||||
|
LogUtils.d(TAG, "已重启 MainService");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopMainServiceAndSaveStatus(Context context) {
|
||||||
|
LogUtils.d(TAG, "stopMainServiceAndSaveStatus");
|
||||||
MainServiceBean bean = new MainServiceBean();
|
MainServiceBean bean = new MainServiceBean();
|
||||||
bean.setIsEnable(false);
|
bean.setIsEnable(false);
|
||||||
MainServiceBean.saveBean(context, bean);
|
MainServiceBean.saveBean(context, bean);
|
||||||
context.stopService(new Intent(context, MainService.class));
|
context.stopService(new Intent(context, MainService.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startMainService(Context context) {
|
public static void startMainServiceAndSaveStatus(Context context) {
|
||||||
LogUtils.d(TAG, "startMainService");
|
LogUtils.d(TAG, "startMainServiceAndSaveStatus");
|
||||||
MainServiceBean bean = new MainServiceBean();
|
MainServiceBean bean = new MainServiceBean();
|
||||||
bean.setIsEnable(true);
|
bean.setIsEnable(true);
|
||||||
MainServiceBean.saveBean(context, bean);
|
MainServiceBean.saveBean(context, bean);
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package cc.winboll.studio.contacts.views;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author ZhanGSKen@AliYun.Com
|
||||||
|
* @Date 2025/03/02 21:11:03
|
||||||
|
* @Describe 云盾防御信息
|
||||||
|
*/
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import cc.winboll.studio.contacts.beans.SettingsModel;
|
||||||
|
import cc.winboll.studio.contacts.dun.Rules;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
|
||||||
|
public class DuInfoTextView extends TextView {
|
||||||
|
|
||||||
|
public static final String TAG = "DuInfoTextView";
|
||||||
|
|
||||||
|
public static final int MSG_NOTIFY_INFO_UPDATE = 0;
|
||||||
|
|
||||||
|
Context mContext;
|
||||||
|
|
||||||
|
public DuInfoTextView(android.content.Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DuInfoTextView(android.content.Context context, android.util.AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
initView(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DuInfoTextView(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DuInfoTextView(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initView(android.content.Context context) {
|
||||||
|
mContext = context;
|
||||||
|
updateInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateInfo() {
|
||||||
|
LogUtils.d(TAG, "updateInfo()");
|
||||||
|
SettingsModel settingsModel = Rules.getInstance(mContext).getSettingsModel();
|
||||||
|
String info = String.format("(云盾防御值【%d/%d】)", settingsModel.getDunCurrentCount(), settingsModel.getDunTotalCount());
|
||||||
|
setText(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
Handler mHandler = new Handler(){
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
super.handleMessage(msg);
|
||||||
|
if(msg.what == MSG_NOTIFY_INFO_UPDATE) {
|
||||||
|
updateInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
public void notifyInfoUpdate() {
|
||||||
|
LogUtils.d(TAG, "notifyInfoUpdate()");
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(MSG_NOTIFY_INFO_UPDATE));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
package cc.winboll.studio.contacts.views;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author ZhanGSKen@AliYun.Com
|
||||||
|
* @Date 2025/03/04 10:51:50
|
||||||
|
* @Describe CustomHorizontalScrollView
|
||||||
|
*/
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.HorizontalScrollView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import cc.winboll.studio.contacts.R;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
|
||||||
|
public class LeftScrollView extends HorizontalScrollView {
|
||||||
|
|
||||||
|
public static final String TAG = "LeftScrollView";
|
||||||
|
|
||||||
|
private LinearLayout contentLayout;
|
||||||
|
private LinearLayout toolLayout;
|
||||||
|
private TextView textView;
|
||||||
|
private Button editButton;
|
||||||
|
private Button deleteButton;
|
||||||
|
private float mLastX;
|
||||||
|
private boolean isScrolling = false;
|
||||||
|
|
||||||
|
public LeftScrollView(Context context) {
|
||||||
|
super(context);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LeftScrollView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LeftScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addContentLayout(TextView textView) {
|
||||||
|
contentLayout.addView(textView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentWidth(int contentWidth) {
|
||||||
|
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) contentLayout.getLayoutParams();
|
||||||
|
layoutParams.width = contentWidth;
|
||||||
|
contentLayout.setLayoutParams(layoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
View viewMain = inflate(getContext(), R.layout.view_left_scroll, null);
|
||||||
|
|
||||||
|
// 创建内容布局
|
||||||
|
contentLayout = viewMain.findViewById(R.id.content_layout);
|
||||||
|
toolLayout = viewMain.findViewById(R.id.action_layout);
|
||||||
|
|
||||||
|
//LogUtils.d(TAG, String.format("getWidth() %d", getWidth()));
|
||||||
|
|
||||||
|
addView(viewMain);
|
||||||
|
|
||||||
|
// 创建编辑按钮
|
||||||
|
editButton = viewMain.findViewById(R.id.edit_btn);
|
||||||
|
// 创建删除按钮
|
||||||
|
deleteButton = viewMain.findViewById(R.id.delete_btn);
|
||||||
|
|
||||||
|
// 编辑按钮点击事件
|
||||||
|
editButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (onActionListener != null) {
|
||||||
|
onActionListener.onEdit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 删除按钮点击事件
|
||||||
|
deleteButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (onActionListener != null) {
|
||||||
|
onActionListener.onDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
LogUtils.d(TAG, "ACTION_DOWN");
|
||||||
|
mLastX = event.getX();
|
||||||
|
isScrolling = false;
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
//LogUtils.d(TAG, "ACTION_MOVE");
|
||||||
|
float currentX = event.getX();
|
||||||
|
float deltaX = mLastX - currentX;
|
||||||
|
mLastX = currentX;
|
||||||
|
if (Math.abs(deltaX) > 0) {
|
||||||
|
isScrolling = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
case MotionEvent.ACTION_CANCEL:
|
||||||
|
LogUtils.d(TAG, "ACTION_UP");
|
||||||
|
if (isScrolling) {
|
||||||
|
LogUtils.d(TAG, String.format("isScrolling \ngetScrollX() %d\neditButton.getWidth() %d", getScrollX(), editButton.getWidth()));
|
||||||
|
int scrollX = getScrollX();
|
||||||
|
if (scrollX > editButton.getWidth()) {
|
||||||
|
// 获取HorizontalScrollView的子视图
|
||||||
|
View childView = getChildAt(0);
|
||||||
|
if (childView != null) {
|
||||||
|
// 计算需要滑动到最右边的距离
|
||||||
|
int scrollToX = childView.getWidth() - getWidth();
|
||||||
|
// 确保滑动距离不小于0
|
||||||
|
final int scrollToX2 = Math.max(0, scrollToX);
|
||||||
|
// 平滑滑动到最右边
|
||||||
|
post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
smoothScrollTo(scrollToX2, 0);
|
||||||
|
LogUtils.d(TAG, "smoothScrollTo(0, 0);");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
LogUtils.d(TAG, "smoothScrollTo(scrollToX, 0);");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 恢复原状
|
||||||
|
// 在手指抬起时,使用 post 方法调用 smoothScrollTo(0, 0)
|
||||||
|
post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
smoothScrollTo(0, 0);
|
||||||
|
LogUtils.d(TAG, "smoothScrollTo(0, 0);");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//toolLayout.setTranslationX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置文本内容
|
||||||
|
public void setText(CharSequence text) {
|
||||||
|
textView.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义回调接口
|
||||||
|
public interface OnActionListener {
|
||||||
|
void onEdit();
|
||||||
|
void onDelete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnActionListener onActionListener;
|
||||||
|
|
||||||
|
public void setOnActionListener(OnActionListener listener) {
|
||||||
|
this.onActionListener = listener;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,176 +1,290 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<ScrollView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/activitymainToolbar1"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="wrap_content">
|
||||||
android:layout_weight="1.0">
|
|
||||||
|
|
||||||
<TextView
|
<androidx.appcompat.widget.Toolbar
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="服务设置:"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<Switch
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="主要服务"
|
|
||||||
android:id="@+id/sw_mainservice"
|
|
||||||
android:layout_margin="10dp"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="应用权限设置:"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="right">
|
android:id="@+id/activitymainToolbar1"/>
|
||||||
|
|
||||||
<Button
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="悬浮窗设置"
|
|
||||||
android:id="@+id/activitysettingsButton2"
|
|
||||||
android:onClick="onCanDrawOverlays"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="默认拨号设置"
|
|
||||||
android:id="@+id/activitysettingsButton1"
|
|
||||||
android:onClick="onDefaultPhone"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="音量设置:"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="10dp"
|
|
||||||
android:id="@+id/tv_volume"/>
|
|
||||||
|
|
||||||
<SeekBar
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:max="100"
|
|
||||||
android:id="@+id/bellvolume"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="拨不通电话记录查询:"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:gravity="right"
|
android:layout_weight="1.0">
|
||||||
android:layout_margin="10dp">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="下载 BoBullToon"
|
|
||||||
android:onClick="onDownloadBoBullToon"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="right|center_vertical"
|
|
||||||
android:layout_margin="10dp">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="查询电话:"/>
|
android:text="服务设置:"/>
|
||||||
|
|
||||||
<EditText
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:orientation="horizontal"
|
||||||
android:inputType="phone"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="主要服务"
|
||||||
|
android:id="@+id/sw_mainservice"
|
||||||
|
android:layout_margin="5dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="云盾设置:"/>
|
||||||
|
|
||||||
|
<cc.winboll.studio.contacts.views.DuInfoTextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/tv_DunInfo"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="是否启用云盾防御"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:id="@+id/sw_IsEnableDun"
|
||||||
|
android:onClick="onSW_IsEnableDun"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ems="10"
|
android:gravity="center_vertical">
|
||||||
android:layout_weight="1.0"
|
|
||||||
android:id="@+id/activitysettingsEditText1"/>
|
|
||||||
|
|
||||||
<Button
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="初始防御层的叠加数量:"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:inputType="number"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ems="10"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:id="@+id/et_DunTotalCount"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="防御层每次恢复的时间间隔(秒钟):"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:inputType="number"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ems="10"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:id="@+id/et_DunResumeSecondCount"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="防御层每次恢复的叠加数量:"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:inputType="number"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ems="10"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:id="@+id/et_DunResumeCount"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="查询记录"
|
android:text="应用权限设置:"/>
|
||||||
android:onClick="onSearchBoBullToonPhone"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="right">
|
||||||
|
|
||||||
<TextView
|
<Button
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Phone Connect Rule :"/>
|
android:text="悬浮窗设置"
|
||||||
|
android:id="@+id/activitysettingsButton2"
|
||||||
|
android:onClick="onCanDrawOverlays"/>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<Button
|
||||||
android:id="@+id/recycler_view"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="0dp"
|
android:text="默认拨号设置"
|
||||||
android:layout_weight="1.0"
|
android:id="@+id/activitysettingsButton1"
|
||||||
android:background="@drawable/recycler_view_border"
|
android:onClick="onDefaultPhone"/>
|
||||||
android:layout_margin="5dp"/>
|
|
||||||
|
|
||||||
<TextView
|
</LinearLayout>
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="单元测试:"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
<TextView
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="right">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Unit Test"
|
android:text="音量设置:"/>
|
||||||
android:onClick="onUnitTest"/>
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:id="@+id/tv_volume"/>
|
||||||
|
|
||||||
|
<SeekBar
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:max="100"
|
||||||
|
android:id="@+id/bellvolume"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="拨不通电话记录查询:"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="right"
|
||||||
|
android:layout_margin="10dp">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="下载 BoBullToon"
|
||||||
|
android:onClick="onDownloadBoBullToon"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="right|center_vertical"
|
||||||
|
android:layout_margin="10dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="查询电话:"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:inputType="phone"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ems="10"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:id="@+id/activitysettingsEditText1"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="查询记录"
|
||||||
|
android:onClick="onSearchBoBullToonPhone"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Phone Connect Rule :"
|
||||||
|
android:layout_weight="1.0"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="添加新规则"
|
||||||
|
android:onClick="onAddNewConnectionRule"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="300dp"
|
||||||
|
android:background="@drawable/recycler_view_border"
|
||||||
|
android:layout_margin="5dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="单元测试:"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="right">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Unit Test"
|
||||||
|
android:onClick="onUnitTest"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</ScrollView>
|
||||||
|
|
||||||
|
|||||||
41
contacts/src/main/res/layout/view_left_scroll.xml
Normal file
41
contacts/src/main/res/layout/view_left_scroll.xml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<!-- 内容区域 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/content_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:background="@color/white">
|
||||||
|
<!-- 这里放置你的列表项内容 -->
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/action_layout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="@color/lightgray">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/edit_btn"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="编辑"
|
||||||
|
android:background="@color/blue" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/delete_btn"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="删除"
|
||||||
|
android:background="@color/red" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
@@ -2,24 +2,15 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="16dp"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical">
|
android:padding="2dp">
|
||||||
|
|
||||||
<TextView
|
<cc.winboll.studio.contacts.views.LeftScrollView
|
||||||
android:id="@+id/text_view"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:id="@+id/scrollView"/>
|
||||||
android:textSize="16sp"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="编辑"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<HorizontalScrollView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:id="@+id/scrollView">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<!-- 内容区域 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/content_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:background="@color/white">
|
||||||
|
<!-- 这里放置你的列表项内容 -->
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_view"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:textSize="16sp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/action_layout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="@color/lightgray">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/edit_btn"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="编辑"
|
||||||
|
android:background="@color/blue" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/delete_btn"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="删除"
|
||||||
|
android:background="@color/red" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</HorizontalScrollView>
|
||||||
@@ -4,4 +4,9 @@
|
|||||||
<color name="colorPrimary">#FF196ABC</color>
|
<color name="colorPrimary">#FF196ABC</color>
|
||||||
<color name="colorPrimaryDark">#FF002B57</color>
|
<color name="colorPrimaryDark">#FF002B57</color>
|
||||||
<color name="colorAccent">#FF80BFFF</color>
|
<color name="colorAccent">#FF80BFFF</color>
|
||||||
|
<color name="blue">#FF379AFF</color>
|
||||||
|
<color name="red">#FFE55151</color>
|
||||||
|
<color name="white">#FFFFFFFF</color>
|
||||||
|
<color name="lightgray">#FFE0E0E0</color>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user