Compare commits
10 Commits
mymessagem
...
mymessagem
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
870e9a94fb | ||
|
|
2421ecb943 | ||
|
|
687fff7216 | ||
|
|
3795cf8631 | ||
|
|
b374f3117a | ||
|
|
6d9adc124e | ||
|
|
52f738b45b | ||
|
|
9ece6778b7 | ||
|
|
e13c8e7af0 | ||
|
|
a4988b5b68 |
@@ -45,15 +45,17 @@ android {
|
||||
|
||||
dependencies {
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
api 'cc.winboll.studio:libaes:15.9.2'
|
||||
api 'cc.winboll.studio:libapputils:15.8.4'
|
||||
api 'cc.winboll.studio:libappbase:15.8.4'
|
||||
api 'cc.winboll.studio:libaes:15.9.3'
|
||||
api 'cc.winboll.studio:libapputils:15.8.5'
|
||||
api 'cc.winboll.studio:libappbase:15.9.5'
|
||||
|
||||
api 'io.github.medyo:android-about-page:2.0.0'
|
||||
api 'com.github.getActivity:ToastUtils:10.5'
|
||||
api 'com.jcraft:jsch:0.1.55'
|
||||
api 'org.jsoup:jsoup:1.13.1'
|
||||
api 'com.squareup.okhttp3:okhttp:4.4.1'
|
||||
|
||||
api 'com.belerweb:pinyin4j:2.5.1'
|
||||
|
||||
// 权限请求框架:https://github.com/getActivity/XXPermissions
|
||||
api 'com.github.getActivity:XXPermissions:18.63'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sat Aug 23 13:40:21 HKT 2025
|
||||
stageCount=3
|
||||
#Sun Aug 31 06:13:45 CST 2025
|
||||
stageCount=7
|
||||
libraryProject=
|
||||
baseVersion=15.3
|
||||
publishVersion=15.3.2
|
||||
publishVersion=15.3.6
|
||||
buildCount=0
|
||||
baseBetaVersion=15.3.3
|
||||
baseBetaVersion=15.3.7
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package cc.winboll.studio.mymessagemanager.activitys;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@188.com>
|
||||
* @Date 2025/08/30 14:32
|
||||
* @Describe 联系人查询与短信发送窗口
|
||||
*/
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
@@ -11,13 +16,17 @@ import android.widget.RelativeLayout;
|
||||
import android.widget.SimpleAdapter;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
|
||||
import cc.winboll.studio.mymessagemanager.R;
|
||||
import cc.winboll.studio.mymessagemanager.activitys.ComposeSMSActivity;
|
||||
import cc.winboll.studio.mymessagemanager.beans.PhoneBean;
|
||||
import cc.winboll.studio.mymessagemanager.utils.PhoneUtil;
|
||||
import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -26,166 +35,282 @@ import java.util.Map;
|
||||
public class ComposeSMSActivity extends BaseActivity {
|
||||
|
||||
public static String TAG = "ComposeSMSActivity";
|
||||
|
||||
public static String EXTRA_SMSBODY = "sms_body";
|
||||
private static final String MAP_NAME = "NAME";
|
||||
private static final String MAP_PHONE = "PHONE";
|
||||
|
||||
static String MAP_NAME = "NAME";
|
||||
static String MAP_PHONE = "PHONE";
|
||||
|
||||
String mszSMSBody;
|
||||
String mszScheme;
|
||||
String mszPhoneTo;
|
||||
EditText metTO;
|
||||
EditText metSMSBody;
|
||||
SimpleAdapter mSimpleAdapter;
|
||||
List<Map<String,Object>> mAdapterData = new ArrayList<>();
|
||||
ListView mlvContracts;
|
||||
List<PhoneBean> mListPhoneBeanContracts;
|
||||
Toolbar mToolbar;
|
||||
AOHPCTCSeekBar mAOHPCTCSeekBar;
|
||||
RelativeLayout mrlContracts;
|
||||
private String mszSMSBody;
|
||||
private String mszScheme;
|
||||
private String mszPhoneTo;
|
||||
private TextView mtvTOName;
|
||||
private EditText metTONameSearch;
|
||||
private EditText metTO;
|
||||
private EditText metSMSBody;
|
||||
private SimpleAdapter mSimpleAdapter;
|
||||
private List<Map<String, Object>> mAdapterData = new ArrayList<Map<String, Object>>();
|
||||
private ListView mlvContracts;
|
||||
private List<PhoneBean> mListPhoneBeanContracts;
|
||||
private Toolbar mToolbar;
|
||||
private AOHPCTCSeekBar mAOHPCTCSeekBar;
|
||||
private RelativeLayout mrlContracts;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_composesms);
|
||||
mszSMSBody = getIntent().getStringExtra(EXTRA_SMSBODY);
|
||||
mszScheme = getIntent().getData().getScheme();
|
||||
mszPhoneTo = getIntent().getData().getSchemeSpecificPart();
|
||||
if (!mszScheme.equals("smsto")) {
|
||||
// 其他方式未支持就退出
|
||||
finish();
|
||||
|
||||
// 初始化Intent数据(增加空判断,避免NullPointerException)
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
mszSMSBody = intent.getStringExtra(EXTRA_SMSBODY);
|
||||
if (intent.getData() != null) {
|
||||
mszScheme = intent.getData().getScheme();
|
||||
mszPhoneTo = intent.getData().getSchemeSpecificPart();
|
||||
}
|
||||
}
|
||||
// 初始化视图
|
||||
|
||||
// 校验启动方式,非smsto则退出
|
||||
if (mszScheme == null || !"smsto".equals(mszScheme)) {
|
||||
ToastUtils.show("不支持的启动方式");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
initView();
|
||||
// 设置适配器
|
||||
initAdapter();
|
||||
// 设置搜索到的匹配位置
|
||||
setListViewPrePosition();
|
||||
initAdapter(null); // 初始加载所有联系人
|
||||
setListViewPrePositionByPhone();
|
||||
}
|
||||
|
||||
//
|
||||
// 初始化视图
|
||||
//
|
||||
void initView() {
|
||||
//Drawable drawableFrame = AppCompatResources.getDrawable(this, R.drawable.bg_frame);
|
||||
|
||||
private void initView() {
|
||||
// 初始化标题栏
|
||||
mToolbar = findViewById(R.id.activitycomposesmsASupportToolbar1);
|
||||
mToolbar = (Toolbar) findViewById(R.id.activitycomposesmsASupportToolbar1);
|
||||
mToolbar.setSubtitle(getString(R.string.activity_name_composesms));
|
||||
setActionBar(mToolbar);
|
||||
|
||||
// 初始化联系人栏目框
|
||||
mrlContracts = findViewById(R.id.activitycomposesmsRelativeLayout1);
|
||||
//mrlContracts.setBackground(drawableFrame);
|
||||
// 初始化联系人姓名显示和搜索栏
|
||||
mtvTOName = (TextView) findViewById(R.id.activitycomposesmsTextView2);
|
||||
mrlContracts = (RelativeLayout) findViewById(R.id.activitycomposesmsRelativeLayout1);
|
||||
metTONameSearch = (EditText) findViewById(R.id.activitycomposesmsEditText2);
|
||||
|
||||
// 初始化联系人列表
|
||||
mlvContracts = findViewById(R.id.activitycomposesmsListView1);
|
||||
// 姓名搜索框文本变化监听
|
||||
metTONameSearch.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
metTO.setText(""); // 清空号码输入框,避免冲突
|
||||
String input = s == null ? "" : s.toString().trim();
|
||||
if (input.isEmpty()) {
|
||||
initAdapter(null); // 空搜索时显示所有联系人
|
||||
} else {
|
||||
setListViewPrePositionByName(); // 按姓名搜索
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化联系人输入框
|
||||
metTO = findViewById(R.id.activitycomposesmsEditText1);
|
||||
metTO.setText(mszPhoneTo);
|
||||
metTO.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
setListViewPrePosition();
|
||||
}
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
// 无操作
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化发送拉动控件
|
||||
mAOHPCTCSeekBar = findViewById(R.id.viewsmssendpart1AOHPCTCSeekBar1);
|
||||
mAOHPCTCSeekBar.setThumb(getDrawable(R.drawable.ic_message));
|
||||
mAOHPCTCSeekBar.setThumbOffset(20);
|
||||
mAOHPCTCSeekBar.setOnOHPCListener(new AOHPCTCSeekBar.OnOHPCListener() {
|
||||
@Override
|
||||
public void onOHPCommit() {
|
||||
// 空号码不发送
|
||||
mszPhoneTo = metTO.getText().toString();
|
||||
if (mszPhoneTo.trim().equals("")) {
|
||||
ToastUtils.show("没有设置接收号码。");
|
||||
return;
|
||||
}
|
||||
// 空消息不发送
|
||||
mszSMSBody = metSMSBody.getText().toString();
|
||||
if (mszSMSBody.equals("")) {
|
||||
ToastUtils.show("没有消息内容可发送。");
|
||||
return;
|
||||
}
|
||||
// 发送消息
|
||||
if (SMSUtil.sendMessageByInterface2(ComposeSMSActivity.this, mszPhoneTo, mszSMSBody)) {
|
||||
ComposeSMSActivity.this.finish();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
// 无操作
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化提示框
|
||||
TextView tvAOHPCTCSeekBarMSG = findViewById(R.id.viewsmssendpart1TextView1);
|
||||
// 初始化联系人列表
|
||||
mlvContracts = (ListView) findViewById(R.id.activitycomposesmsListView1);
|
||||
|
||||
// 初始化号码输入框(核心:优化文本变化监听逻辑)
|
||||
metTO = (EditText) findViewById(R.id.activitycomposesmsEditText1);
|
||||
if (mszPhoneTo != null) {
|
||||
metTO.setText(mszPhoneTo);
|
||||
}
|
||||
metTO.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
mtvTOName.setText(""); // 清空姓名显示
|
||||
String inputPhone = s == null ? "" : s.toString().trim();
|
||||
|
||||
if (inputPhone.isEmpty()) {
|
||||
// 输入为空时,显示所有联系人
|
||||
initAdapter(null);
|
||||
} else {
|
||||
// 输入非空时,按号码搜索并更新列表(无结果则清空)
|
||||
filterListByPhone(inputPhone);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
// 无操作
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
// 无操作
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化发送控件
|
||||
mAOHPCTCSeekBar = (AOHPCTCSeekBar) findViewById(R.id.viewsmssendpart1AOHPCTCSeekBar1);
|
||||
Drawable thumbDrawable = getResources().getDrawable(R.drawable.ic_message); // Java 7兼容写法
|
||||
mAOHPCTCSeekBar.setThumb(thumbDrawable);
|
||||
mAOHPCTCSeekBar.setThumbOffset(20);
|
||||
mAOHPCTCSeekBar.setOnOHPCListener(new AOHPCTCSeekBar.OnOHPCListener() {
|
||||
@Override
|
||||
public void onOHPCommit() {
|
||||
sendSMS();
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化短信内容输入框
|
||||
TextView tvAOHPCTCSeekBarMSG = (TextView) findViewById(R.id.viewsmssendpart1TextView1);
|
||||
tvAOHPCTCSeekBarMSG.setText(R.string.msg_100sendmsg);
|
||||
|
||||
// 初始化发送消息框
|
||||
metSMSBody = findViewById(R.id.viewsmssendpart1EditText1);
|
||||
//metSMSBody.setBackground(drawableFrame);
|
||||
metSMSBody.setText(mszSMSBody);
|
||||
metSMSBody = (EditText) findViewById(R.id.viewsmssendpart1EditText1);
|
||||
if (mszSMSBody != null) {
|
||||
metSMSBody.setText(mszSMSBody);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 设置搜索到的匹配位置
|
||||
//
|
||||
void setListViewPrePosition() {
|
||||
int nPrePosition = getContractsDataPrePosition(metTO.getText().toString());
|
||||
mlvContracts.setSelected(false);
|
||||
mlvContracts.setSelection(nPrePosition);
|
||||
// 核心优化:根据输入号码筛选列表(无结果则显示空列表)
|
||||
private void filterListByPhone(String inputPhone) {
|
||||
PhoneUtil phoneUtil = new PhoneUtil(this);
|
||||
List<PhoneBean> allContacts = phoneUtil.getPhoneList();
|
||||
List<PhoneBean> matchedContacts = new ArrayList<PhoneBean>();
|
||||
|
||||
// 遍历所有联系人,匹配包含输入号码的联系人
|
||||
for (PhoneBean contact : allContacts) {
|
||||
if (contact.getTelPhone().contains(inputPhone)
|
||||
|| phoneUtil.isTheSamePhoneNumber(contact.getTelPhone(), inputPhone)) {
|
||||
matchedContacts.add(contact);
|
||||
}
|
||||
}
|
||||
|
||||
LogUtils.d(TAG, "号码搜索:输入'" + inputPhone + "', 匹配" + matchedContacts.size() + "个结果");
|
||||
|
||||
// 用筛选结果更新列表(无结果则传入空列表)
|
||||
initAdapter(matchedContacts.isEmpty() ? new ArrayList<PhoneBean>() : matchedContacts);
|
||||
|
||||
// 定位到第一个匹配项(如果有)
|
||||
if (!matchedContacts.isEmpty()) {
|
||||
mlvContracts.setSelection(0);
|
||||
mtvTOName.setText(matchedContacts.get(0).getName());
|
||||
} else {
|
||||
mtvTOName.setText(""); // 无结果时清空姓名显示
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 返回搜索到的匹配位置
|
||||
//
|
||||
int getContractsDataPrePosition(String szPhone) {
|
||||
// 根据姓名搜索联系人
|
||||
private void setListViewPrePositionByName() {
|
||||
String searchName = metTONameSearch.getText().toString().trim();
|
||||
PhoneUtil phoneUtil = new PhoneUtil(this);
|
||||
List<PhoneBean> matchedContacts = phoneUtil.getPhonesByName(searchName);
|
||||
initAdapter(matchedContacts);
|
||||
if (!matchedContacts.isEmpty()) {
|
||||
mlvContracts.setSelection(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 初始定位号码对应的联系人
|
||||
private void setListViewPrePositionByPhone() {
|
||||
String inputPhone = metTO.getText().toString().trim();
|
||||
if (inputPhone.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
filterListByPhone(inputPhone); // 复用筛选逻辑
|
||||
}
|
||||
|
||||
// 获取号码匹配的位置(兼容旧逻辑)
|
||||
private int getContractsDataPrePositionByPhone(String szPhone) {
|
||||
if (mListPhoneBeanContracts == null || mListPhoneBeanContracts.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; i < mListPhoneBeanContracts.size(); i++) {
|
||||
if (mListPhoneBeanContracts.get(i).getTelPhone().compareTo(szPhone) > -1) {
|
||||
PhoneBean bean = mListPhoneBeanContracts.get(i);
|
||||
if (bean.getTelPhone().compareTo(szPhone) >= 0) {
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// 初始化适配器
|
||||
//
|
||||
void initAdapter() {
|
||||
// 初始化联系人数据适配器
|
||||
mAdapterData = new ArrayList<>();
|
||||
// 读取联系人数据
|
||||
PhoneUtil phoneUtils = new PhoneUtil(this);
|
||||
mListPhoneBeanContracts = phoneUtils.getPhoneList();
|
||||
// 映射联系人数据给适配器数据对象
|
||||
for (int i = 0;i < mListPhoneBeanContracts.size();i++) {
|
||||
Map<String,Object> map =new HashMap<>();
|
||||
map.put(MAP_NAME, mListPhoneBeanContracts.get(i).getName());
|
||||
map.put(MAP_PHONE, mListPhoneBeanContracts.get(i).getTelPhone());
|
||||
mAdapterData.add(map);
|
||||
// 获取姓名匹配的位置(兼容旧逻辑)
|
||||
private int getContractsDataPrePositionByName(String szName) {
|
||||
if (mListPhoneBeanContracts == null || mListPhoneBeanContracts.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
// 绑定适配器与数据
|
||||
mSimpleAdapter = new SimpleAdapter(ComposeSMSActivity.this, mAdapterData, R.layout.listview_contracts
|
||||
, new String[]{MAP_NAME, MAP_PHONE}
|
||||
, new int[]{R.id.listviewcontractsTextView1, R.id.listviewcontractsTextView2});
|
||||
mSimpleAdapter.setDropDownViewResource(R.layout.listview_contracts);
|
||||
mlvContracts.setAdapter(mSimpleAdapter);
|
||||
mlvContracts.setOnItemClickListener(new ListView.OnItemClickListener() {
|
||||
for (int i = 0; i < mListPhoneBeanContracts.size(); i++) {
|
||||
if (mListPhoneBeanContracts.get(i).getName().startsWith(szName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
metTO.setText(mAdapterData.get(position).get(MAP_PHONE).toString());
|
||||
// 初始化或更新列表适配器
|
||||
private void initAdapter(List<PhoneBean> initData) {
|
||||
mAdapterData.clear(); // 清空旧数据
|
||||
final PhoneUtil phoneUtil = new PhoneUtil(this);
|
||||
|
||||
}
|
||||
});
|
||||
// 确定数据源:传入的筛选数据或所有联系人
|
||||
if (initData != null) {
|
||||
mListPhoneBeanContracts = initData;
|
||||
} else {
|
||||
mListPhoneBeanContracts = phoneUtil.getPhoneList();
|
||||
}
|
||||
|
||||
// 转换数据为SimpleAdapter所需格式
|
||||
if (mListPhoneBeanContracts != null) {
|
||||
for (PhoneBean bean : mListPhoneBeanContracts) {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put(MAP_NAME, bean.getName());
|
||||
map.put(MAP_PHONE, bean.getTelPhone());
|
||||
mAdapterData.add(map);
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化或更新适配器
|
||||
if (mSimpleAdapter == null) {
|
||||
mSimpleAdapter = new SimpleAdapter(
|
||||
ComposeSMSActivity.this,
|
||||
mAdapterData,
|
||||
R.layout.listview_contracts,
|
||||
new String[]{MAP_NAME, MAP_PHONE},
|
||||
new int[]{R.id.listviewcontractsTextView1, R.id.listviewcontractsTextView2}
|
||||
);
|
||||
mSimpleAdapter.setDropDownViewResource(R.layout.listview_contracts);
|
||||
mlvContracts.setAdapter(mSimpleAdapter);
|
||||
|
||||
// 列表项点击事件
|
||||
mlvContracts.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (position < mAdapterData.size()) {
|
||||
String phone = mAdapterData.get(position).get(MAP_PHONE).toString();
|
||||
metTO.setText(phone);
|
||||
mtvTOName.setText(phoneUtil.getNameByPhone(phone));
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mSimpleAdapter.notifyDataSetChanged(); // 数据更新时通知适配器
|
||||
}
|
||||
}
|
||||
|
||||
// 发送短信逻辑
|
||||
private void sendSMS() {
|
||||
String phoneTo = metTO.getText().toString().trim();
|
||||
if (phoneTo.isEmpty()) {
|
||||
ToastUtils.show("没有设置接收号码。");
|
||||
return;
|
||||
}
|
||||
String smsBody = metSMSBody.getText().toString().trim();
|
||||
if (smsBody.isEmpty()) {
|
||||
ToastUtils.show("没有消息内容可发送。");
|
||||
return;
|
||||
}
|
||||
if (SMSUtil.sendMessageByInterface2(ComposeSMSActivity.this, phoneTo, smsBody)) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package cc.winboll.studio.mymessagemanager.utils;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen<zhangsken@188.com>
|
||||
* @Date 2024/07/19 14:30:57
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@188.com>
|
||||
* @Date 2025/08/30 14:32
|
||||
* @Describe 手机联系人工具类
|
||||
*/
|
||||
import android.content.ContentResolver;
|
||||
@@ -12,6 +12,12 @@ import android.net.Uri;
|
||||
import android.provider.ContactsContract;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.mymessagemanager.beans.PhoneBean;
|
||||
import net.sourceforge.pinyin4j.PinyinHelper;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
|
||||
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -38,28 +44,137 @@ public class PhoneUtil {
|
||||
}
|
||||
|
||||
// 读取所有联系人
|
||||
//
|
||||
public List<PhoneBean> getPhoneList() {
|
||||
List<PhoneBean> listPhoneBean = new ArrayList<>();
|
||||
ContentResolver cr = mContext.getContentResolver();
|
||||
Cursor cursor = cr.query(mUriPhoneContent, new String[]{NUMBER, DISPLAY_NAME}, null, null, null);
|
||||
while (cursor.moveToNext()) {
|
||||
PhoneBean phoneBean = new PhoneBean(cursor.getString(1), cursor.getString(0).replaceAll("\\s", ""));
|
||||
listPhoneBean.add(phoneBean);
|
||||
|
||||
if (cursor != null) {
|
||||
while (cursor.moveToNext()) {
|
||||
// 去除号码中的空格
|
||||
String phone = cursor.getString(0).replaceAll("\\s", "");
|
||||
String name = cursor.getString(1);
|
||||
PhoneBean phoneBean = new PhoneBean(name, phone);
|
||||
listPhoneBean.add(phoneBean);
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
cursor.close();
|
||||
|
||||
// 按电话号码排序
|
||||
Collections.sort(listPhoneBean, new Comparator<PhoneBean>() {
|
||||
@Override
|
||||
public int compare(PhoneBean o1, PhoneBean o2) {
|
||||
return o1.getTelPhone().compareTo(o2.getTelPhone());
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public int compare(PhoneBean o1, PhoneBean o2) {
|
||||
return o1.getTelPhone().compareTo(o2.getTelPhone());
|
||||
}
|
||||
});
|
||||
|
||||
return listPhoneBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据联系人名称查询号码(兼容拼音查询)
|
||||
* @param keyword 搜索关键词(支持汉字、拼音、拼音首字母)
|
||||
* @return 匹配的联系人列表(包含姓名和号码)
|
||||
*/
|
||||
public List<PhoneBean> getPhonesByName(String keyword) {
|
||||
List<PhoneBean> result = new ArrayList<>();
|
||||
if (keyword == null || keyword.trim().isEmpty()) {
|
||||
return result; // 关键词为空,返回空列表
|
||||
}
|
||||
|
||||
// 获取所有联系人
|
||||
List<PhoneBean> allContacts = getPhoneList();
|
||||
// 统一转为小写,忽略大小写
|
||||
String keywordLower = keyword.trim().toLowerCase();
|
||||
|
||||
for (PhoneBean contact : allContacts) {
|
||||
String name = contact.getName();
|
||||
if (name == null || name.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1. 直接匹配姓名(包含关键词)
|
||||
if (name.toLowerCase().contains(keywordLower)) {
|
||||
result.add(contact);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2. 匹配姓名的全拼(包含关键词)
|
||||
String namePinyin = getPinyin(name).toLowerCase();
|
||||
if (namePinyin.contains(keywordLower)) {
|
||||
result.add(contact);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3. 匹配姓名的拼音首字母(包含关键词)
|
||||
String namePinyinFirstLetter = getPinyinFirstLetter(name).toLowerCase();
|
||||
if (namePinyinFirstLetter.contains(keywordLower)) {
|
||||
result.add(contact);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将汉字转为全拼(不带声调,小写)
|
||||
* 例如:"张三" → "zhangsan"
|
||||
*/
|
||||
private String getPinyin(String chinese) {
|
||||
StringBuilder pinyin = new StringBuilder();
|
||||
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
|
||||
format.setCaseType(HanyuPinyinCaseType.LOWERCASE); // 小写
|
||||
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); // 不带声调
|
||||
|
||||
char[] chars = chinese.toCharArray();
|
||||
for (char c : chars) {
|
||||
// 如果是汉字,转换为拼音;否则直接拼接(如字母、数字、符号)
|
||||
if (Character.toString(c).matches("[\\u4e00-\\u9fa5]")) {
|
||||
try {
|
||||
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format);
|
||||
if (pinyinArray != null && pinyinArray.length > 0) {
|
||||
pinyin.append(pinyinArray[0]); // 取第一个拼音(多音字默认取第一个)
|
||||
}
|
||||
} catch (BadHanyuPinyinOutputFormatCombination e) {
|
||||
LogUtils.e(TAG, "拼音转换失败:" + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
pinyin.append(c);
|
||||
}
|
||||
}
|
||||
return pinyin.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将汉字转为拼音首字母(小写)
|
||||
* 例如:"张三" → "zs"
|
||||
*/
|
||||
private String getPinyinFirstLetter(String chinese) {
|
||||
StringBuilder firstLetters = new StringBuilder();
|
||||
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
|
||||
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
|
||||
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
||||
|
||||
char[] chars = chinese.toCharArray();
|
||||
for (char c : chars) {
|
||||
if (Character.toString(c).matches("[\\u4e00-\\u9fa5]")) {
|
||||
try {
|
||||
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format);
|
||||
if (pinyinArray != null && pinyinArray.length > 0) {
|
||||
// 取拼音首字母(如"zhang" → "z")
|
||||
firstLetters.append(pinyinArray[0].charAt(0));
|
||||
}
|
||||
} catch (BadHanyuPinyinOutputFormatCombination e) {
|
||||
LogUtils.e(TAG, "拼音首字母转换失败:" + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
// 非汉字直接拼接首字符(如"李3" → "l3")
|
||||
firstLetters.append(c);
|
||||
}
|
||||
}
|
||||
return firstLetters.toString();
|
||||
}
|
||||
|
||||
public boolean isPhoneInContacts(String szPhone) {
|
||||
List<PhoneBean> listPhoneDto = getPhoneList();
|
||||
LogUtils.d(TAG, String.format("isPhoneInContacts(...) listPhoneDto.size() %d", listPhoneDto.size()));
|
||||
@@ -70,49 +185,56 @@ public class PhoneUtil {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isTheSamePhoneNumber(String szNum1, String szNum2) {
|
||||
//LogUtils.d(TAG, String.format("szNum1 %s\nszNum2 %s", szNum1, szNum2));
|
||||
if(szNum1.equals(szNum2)) {
|
||||
|
||||
public String getNameByPhone(String szPhone) {
|
||||
if (szPhone == null || szPhone.equals("")) {
|
||||
return "";
|
||||
}
|
||||
|
||||
List<PhoneBean> listPhoneDto = getPhoneList();
|
||||
LogUtils.d(TAG, String.format("getNameByPhone(...) listPhoneDto.size() %d", listPhoneDto.size()));
|
||||
for (int i = 0; i < listPhoneDto.size(); i++) {
|
||||
if (isTheSamePhoneNumber(listPhoneDto.get(i).getTelPhone(), szPhone)) {
|
||||
return listPhoneDto.get(i).getName();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean isTheSamePhoneNumber(String szNum1, String szNum2) {
|
||||
if (szNum1.equals(szNum2)) {
|
||||
LogUtils.d(TAG, "szNum1.equals(szNum2)");
|
||||
return true;
|
||||
}
|
||||
|
||||
if(UnitAreaUtils.getInstance(mContext).isCurrentUnitAreaNumber(szNum1)) {
|
||||
if(szNum1.equals(UnitAreaUtils.getInstance(mContext).genCurrentUnitAreaNumber(szNum2))) {
|
||||
|
||||
if (UnitAreaUtils.getInstance(mContext).isCurrentUnitAreaNumber(szNum1)) {
|
||||
if (szNum1.equals(UnitAreaUtils.getInstance(mContext).genCurrentUnitAreaNumber(szNum2))) {
|
||||
LogUtils.d(TAG, "szNum1.equals(UnitAreaUtils.genCurrentUnitAreaNumber(szNum2))");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(UnitAreaUtils.getInstance(mContext).isCurrentUnitAreaNumber(szNum2)) {
|
||||
if(szNum2.equals(UnitAreaUtils.getInstance(mContext).genCurrentUnitAreaNumber(szNum1))) {
|
||||
|
||||
if (UnitAreaUtils.getInstance(mContext).isCurrentUnitAreaNumber(szNum2)) {
|
||||
if (szNum2.equals(UnitAreaUtils.getInstance(mContext).genCurrentUnitAreaNumber(szNum1))) {
|
||||
LogUtils.d(TAG, "szNum2.equals(UnitAreaUtils.genCurrentUnitAreaNumber(szNum1))");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LogUtils.d(TAG, "isTheSamePhoneNumber(...) return false;");
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// 检验电话号码是否是数字
|
||||
//
|
||||
public static boolean isPhoneByDigit(String szPhone) {
|
||||
if(!RegexPPiUtils.isPPiOK(szPhone)) {
|
||||
if (!RegexPPiUtils.isPPiOK(szPhone)) {
|
||||
return false;
|
||||
}
|
||||
//String text = "这里是一些任意的文本内容";
|
||||
String regex = "[+]?\\d+";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(szPhone);
|
||||
LogUtils.d(TAG, String.format("matcher.matches() : %s", matcher.matches()));
|
||||
/*if (matcher.matches()) {
|
||||
System.out.println("文本满足该正则表达式模式");
|
||||
} else {
|
||||
System.out.println("文本不满足该正则表达式模式");
|
||||
}*/
|
||||
return matcher.matches();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ import cc.winboll.studio.mymessagemanager.beans.AppConfigBean;
|
||||
import android.content.Context;
|
||||
|
||||
public class UnitAreaUtils {
|
||||
|
||||
|
||||
public static final String TAG = "UnitAreaUtils";
|
||||
|
||||
|
||||
static UnitAreaUtils _UnitAreaUtils;
|
||||
Context mContext;
|
||||
|
||||
@@ -26,19 +26,25 @@ public class UnitAreaUtils {
|
||||
}
|
||||
return _UnitAreaUtils;
|
||||
}
|
||||
|
||||
|
||||
public boolean isCurrentUnitAreaNumber(String szPhoneNumer) {
|
||||
String szUnitArea = getUnitArea();
|
||||
LogUtils.d(TAG, String.format("szPhoneNumer.substring(1,3) %s", szPhoneNumer.substring(1,3)));
|
||||
return szPhoneNumer.substring(1,3).equals(szUnitArea);
|
||||
try {
|
||||
String szPhoneNumerUnitArea = szPhoneNumer.substring(1, 3);
|
||||
LogUtils.d(TAG, String.format("szPhoneNumerUnitArea %s", szPhoneNumerUnitArea));
|
||||
return szPhoneNumerUnitArea.equals(szUnitArea);
|
||||
} catch (StringIndexOutOfBoundsException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public String genCurrentUnitAreaNumber(String szPhoneNumer) {
|
||||
String szUnitArea = getUnitArea();
|
||||
LogUtils.d(TAG, String.format("szUnitArea %s", szUnitArea));
|
||||
return "+" + szUnitArea + szPhoneNumer;
|
||||
}
|
||||
|
||||
|
||||
String getUnitArea() {
|
||||
String szUnitArea = AppConfigUtil.getInstance(mContext).mAppConfigBean.getCountryCode();
|
||||
LogUtils.d(TAG, String.format("szUnitArea %s", szUnitArea));
|
||||
|
||||
@@ -21,25 +21,63 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activitycomposesmsRelativeLayout1">
|
||||
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SMS TO : "
|
||||
android:id="@+id/activitycomposesmsTextView1"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_centerVertical="true"/>
|
||||
|
||||
<EditText
|
||||
android:layout_toRightOf="@id/activitycomposesmsTextView1"
|
||||
android:layout_width="wrap_content"
|
||||
android:inputType="phone"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:id="@+id/activitycomposesmsEditText1"
|
||||
android:id="@+id/activitycomposesmsLinearLayout1"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_centerVertical="true"/>
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_alignParentLeft="true">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="(拼音搜索):"/>
|
||||
|
||||
<EditText
|
||||
android:layout_width="80dp"
|
||||
android:ems="10"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activitycomposesmsEditText2"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toRightOf="@id/activitycomposesmsEditText2"
|
||||
android:id="@+id/activitycomposesmsTextView2"
|
||||
android:layout_weight="1.0"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_below="@id/activitycomposesmsLinearLayout1"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="(SMS TO) :"
|
||||
android:id="@+id/activitycomposesmsTextView1"/>
|
||||
|
||||
<EditText
|
||||
android:layout_width="wrap_content"
|
||||
android:inputType="phone"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:id="@+id/activitycomposesmsEditText1"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:padding="10dp"
|
||||
android:text="@string/text_onlyreceivecontacts"
|
||||
android:text="@string/text_norulesreceivecontacts"
|
||||
android:id="@+id/activitymainSwitchView2"/>
|
||||
|
||||
<cc.winboll.studio.mymessagemanager.views.ConfirmSwitchView
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<string name="text_item_rule_clean">清理设置</string>
|
||||
<string name="text_sendsms">发送短信</string>
|
||||
<string name="text_mainservice">短信服务管理总开关</string>
|
||||
<string name="text_onlyreceivecontacts">只接收联系人短信</string>
|
||||
<string name="text_norulesreceivecontacts">无限制接收联系人短信</string>
|
||||
<string name="text_usingtts">使用TTS语音播报</string>
|
||||
<string name="text_usingttsrule">使用TTS语音自定义规则</string>
|
||||
<string name="text_iamhere">短信管理服务已启动。</string>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<string name="text_item_rule_clean">Clean Setting</string>
|
||||
<string name="text_sendsms">Send SMS</string>
|
||||
<string name="text_mainservice">Main Service</string>
|
||||
<string name="text_onlyreceivecontacts">Only Receive Contacts</string>
|
||||
<string name="text_norulesreceivecontacts">No rules Receive Contacts</string>
|
||||
<string name="text_usingtts">Using TTS</string>
|
||||
<string name="text_usingttsrule">Using TTS Rule</string>
|
||||
<string name="text_iamhere">The main service is start.</string>
|
||||
|
||||
Reference in New Issue
Block a user