完成电话连接规则的编辑和保存
This commit is contained in:
		@@ -51,6 +51,8 @@ android {
 | 
				
			|||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    implementation fileTree(dir: 'libs', include: ['*.jar'])
 | 
					    implementation fileTree(dir: 'libs', include: ['*.jar'])
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    implementation 'com.squareup.okhttp3:okhttp:4.4.1'
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    // https://mvnrepository.com/artifact/com.github.open-android/pinyin4j
 | 
					    // https://mvnrepository.com/artifact/com.github.open-android/pinyin4j
 | 
				
			||||||
    implementation 'com.github.open-android:pinyin4j:2.5.0'
 | 
					    implementation 'com.github.open-android:pinyin4j:2.5.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
#Created by .winboll/winboll_app_build.gradle
 | 
					#Created by .winboll/winboll_app_build.gradle
 | 
				
			||||||
#Wed Feb 26 19:10:28 HKT 2025
 | 
					#Sun Mar 02 10:24:46 GMT 2025
 | 
				
			||||||
stageCount=5
 | 
					stageCount=5
 | 
				
			||||||
libraryProject=
 | 
					libraryProject=
 | 
				
			||||||
baseVersion=1.0
 | 
					baseVersion=1.0
 | 
				
			||||||
publishVersion=1.0.4
 | 
					publishVersion=1.0.4
 | 
				
			||||||
buildCount=0
 | 
					buildCount=40
 | 
				
			||||||
baseBetaVersion=1.0.5
 | 
					baseBetaVersion=1.0.5
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -183,6 +183,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        </provider>
 | 
					        </provider>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <activity android:name="cc.winboll.studio.contacts.activities.UnitTestActivity"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    </application>
 | 
					    </application>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</manifest>
 | 
					</manifest>
 | 
				
			||||||
@@ -8,6 +8,7 @@ package cc.winboll.studio.contacts;
 | 
				
			|||||||
import cc.winboll.studio.libappbase.GlobalApplication;
 | 
					import cc.winboll.studio.libappbase.GlobalApplication;
 | 
				
			||||||
import cc.winboll.studio.libappbase.LogUtils;
 | 
					import cc.winboll.studio.libappbase.LogUtils;
 | 
				
			||||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
 | 
					import cc.winboll.studio.libapputils.app.WinBollActivityManager;
 | 
				
			||||||
 | 
					import com.hjq.toast.ToastUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class App extends GlobalApplication {
 | 
					public class App extends GlobalApplication {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,6 +24,8 @@ public class App extends GlobalApplication {
 | 
				
			|||||||
        WinBollActivityManager.getInstance(this).setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Aplication);
 | 
					        WinBollActivityManager.getInstance(this).setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Aplication);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        LogUtils.d(TAG, "onCreate");
 | 
					        LogUtils.d(TAG, "onCreate");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        ToastUtils.init(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,6 @@ package cc.winboll.studio.contacts.activities;
 | 
				
			|||||||
 * @Author ZhanGSKen@AliYun.Com
 | 
					 * @Author ZhanGSKen@AliYun.Com
 | 
				
			||||||
 * @Date 2025/02/21 05:37:42
 | 
					 * @Date 2025/02/21 05:37:42
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
import android.app.NotificationManager;
 | 
					 | 
				
			||||||
import android.content.Context;
 | 
					import android.content.Context;
 | 
				
			||||||
import android.content.DialogInterface;
 | 
					import android.content.DialogInterface;
 | 
				
			||||||
import android.content.Intent;
 | 
					import android.content.Intent;
 | 
				
			||||||
@@ -15,21 +14,29 @@ import android.os.Bundle;
 | 
				
			|||||||
import android.provider.Settings;
 | 
					import android.provider.Settings;
 | 
				
			||||||
import android.view.View;
 | 
					import android.view.View;
 | 
				
			||||||
import android.view.WindowManager;
 | 
					import android.view.WindowManager;
 | 
				
			||||||
 | 
					import android.widget.EditText;
 | 
				
			||||||
 | 
					import android.widget.SeekBar;
 | 
				
			||||||
import android.widget.Switch;
 | 
					import android.widget.Switch;
 | 
				
			||||||
 | 
					import android.widget.TextView;
 | 
				
			||||||
import android.widget.Toast;
 | 
					import android.widget.Toast;
 | 
				
			||||||
import androidx.appcompat.app.AlertDialog;
 | 
					import androidx.appcompat.app.AlertDialog;
 | 
				
			||||||
import androidx.appcompat.app.AppCompatActivity;
 | 
					import androidx.appcompat.app.AppCompatActivity;
 | 
				
			||||||
import androidx.appcompat.widget.Toolbar;
 | 
					import androidx.appcompat.widget.Toolbar;
 | 
				
			||||||
 | 
					import androidx.recyclerview.widget.LinearLayoutManager;
 | 
				
			||||||
 | 
					import androidx.recyclerview.widget.RecyclerView;
 | 
				
			||||||
import cc.winboll.studio.contacts.R;
 | 
					import cc.winboll.studio.contacts.R;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.adapters.PhoneConnectRuleAdapter;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.beans.MainServiceBean;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel;
 | 
				
			||||||
import cc.winboll.studio.contacts.beans.RingTongBean;
 | 
					import cc.winboll.studio.contacts.beans.RingTongBean;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.bobulltoon.TomCat;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.dun.Rules;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.services.MainService;
 | 
				
			||||||
import cc.winboll.studio.libappbase.IWinBollActivity;
 | 
					import cc.winboll.studio.libappbase.IWinBollActivity;
 | 
				
			||||||
import cc.winboll.studio.libappbase.bean.APPInfo;
 | 
					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 android.widget.SeekBar;
 | 
					import java.util.List;
 | 
				
			||||||
import android.widget.TextView;
 | 
					 | 
				
			||||||
import cc.winboll.studio.contacts.beans.MainServiceBean; 
 | 
					 | 
				
			||||||
import cc.winboll.studio.contacts.services.MainService;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class SettingsActivity extends AppCompatActivity implements IWinBollActivity {
 | 
					public class SettingsActivity extends AppCompatActivity implements IWinBollActivity {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -43,6 +50,9 @@ public class SettingsActivity extends AppCompatActivity implements IWinBollActiv
 | 
				
			|||||||
    int mnStreamVolume;
 | 
					    int mnStreamVolume;
 | 
				
			||||||
    Switch mswMainService;
 | 
					    Switch mswMainService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private RecyclerView recyclerView;
 | 
				
			||||||
 | 
					    private PhoneConnectRuleAdapter adapter;
 | 
				
			||||||
 | 
					    private List<PhoneConnectRuleModel> ruleList;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public APPInfo getAppInfo() {
 | 
					    public APPInfo getAppInfo() {
 | 
				
			||||||
@@ -146,12 +156,26 @@ public class SettingsActivity extends AppCompatActivity implements IWinBollActiv
 | 
				
			|||||||
                    // 当停止拖动SeekBar时的操作
 | 
					                    // 当停止拖动SeekBar时的操作
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        recyclerView = findViewById(R.id.recycler_view);
 | 
				
			||||||
 | 
					        recyclerView.setLayoutManager(new LinearLayoutManager(this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ruleList = Rules.getInstance(this).getPhoneBlacRuleBeanList();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        adapter = new PhoneConnectRuleAdapter(this, ruleList);
 | 
				
			||||||
 | 
					        recyclerView.setAdapter(adapter);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void updateStreamVolumeTextView() {
 | 
					    void updateStreamVolumeTextView() {
 | 
				
			||||||
        mtvVolume.setText(String.format("%d/%d", mnStreamVolume, mnStreamMaxVolume));
 | 
					        mtvVolume.setText(String.format("%d/%d", mnStreamVolume, mnStreamMaxVolume));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void onUnitTest(View view) {
 | 
				
			||||||
 | 
					        Intent intent = new Intent(this, UnitTestActivity.class);
 | 
				
			||||||
 | 
					        startActivity(intent);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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);
 | 
				
			||||||
        startActivity(intent);
 | 
					        startActivity(intent);
 | 
				
			||||||
@@ -167,6 +191,34 @@ public class SettingsActivity extends AppCompatActivity implements IWinBollActiv
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void onDownloadBoBullToon(View view) {
 | 
				
			||||||
 | 
					        final TomCat tomCat = TomCat.getInstance(this);
 | 
				
			||||||
 | 
					        new Thread(new Runnable() {
 | 
				
			||||||
 | 
					                @Override
 | 
				
			||||||
 | 
					                public void run() {
 | 
				
			||||||
 | 
					                    if (tomCat.downloadBoBullToon()) {
 | 
				
			||||||
 | 
					                        ToastUtils.show("BoBullToon downlaod OK!");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }).start();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void onSearchBoBullToonPhone(View view) {
 | 
				
			||||||
 | 
					        TomCat tomCat = TomCat.getInstance(this);
 | 
				
			||||||
 | 
					        EditText etPhone = findViewById(R.id.activitysettingsEditText1);
 | 
				
			||||||
 | 
					        String phone = etPhone.getText().toString().trim();
 | 
				
			||||||
 | 
					        if (tomCat.loadPhoneBoBullToon()) {
 | 
				
			||||||
 | 
					            if (tomCat.isPhoneBoBullToon(phone)) {
 | 
				
			||||||
 | 
					                ToastUtils.show("It is a BoBullToon Phone!");
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                ToastUtils.show("Not in BoBullToon.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            ToastUtils.show("没有下载 BoBullToon。");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void askForDrawOverlay() {
 | 
					    private void askForDrawOverlay() {
 | 
				
			||||||
        AlertDialog alertDialog = new AlertDialog.Builder(this)
 | 
					        AlertDialog alertDialog = new AlertDialog.Builder(this)
 | 
				
			||||||
            .setTitle("允许显示悬浮框")
 | 
					            .setTitle("允许显示悬浮框")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					package cc.winboll.studio.contacts.activities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.app.Activity;
 | 
				
			||||||
 | 
					import android.os.Bundle;
 | 
				
			||||||
 | 
					import android.view.View;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.R;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.dun.Rules;
 | 
				
			||||||
 | 
					import cc.winboll.studio.libappbase.LogUtils;
 | 
				
			||||||
 | 
					import cc.winboll.studio.libappbase.LogView;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @Author ZhanGSKen@AliYun.Com
 | 
				
			||||||
 | 
					 * @Date 2025/03/02 16:07:04
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class UnitTestActivity extends Activity {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final String TAG = "UnitTestActivity";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LogView logView;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    protected void onCreate(Bundle savedInstanceState) {
 | 
				
			||||||
 | 
					        super.onCreate(savedInstanceState);
 | 
				
			||||||
 | 
					        setContentView(R.layout.activity_unittest);
 | 
				
			||||||
 | 
					        logView = findViewById(R.id.logview);
 | 
				
			||||||
 | 
					        logView.start();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void onTestMain(View view) {
 | 
				
			||||||
 | 
					        Rules rules = Rules.getInstance(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 如果没有规则就添加测试规则
 | 
				
			||||||
 | 
					        if (rules.getPhoneBlacRuleBeanList().size() == 0) {
 | 
				
			||||||
 | 
					            // 手机号码允许
 | 
				
			||||||
 | 
					            // 中国手机号码正则表达式,以1开头,第二位可以是3、4、5、6、7、8、9,后面跟9位数字
 | 
				
			||||||
 | 
					            String regex = "^1[3-9]\\d{9}$";
 | 
				
			||||||
 | 
					            rules.add(regex, true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 指定区号号码允许
 | 
				
			||||||
 | 
					            regex = "^0660\\d+$";
 | 
				
			||||||
 | 
					            rules.add(regex, true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 指定区号号码允许
 | 
				
			||||||
 | 
					            regex = "^020\\d+$";
 | 
				
			||||||
 | 
					            rules.add(regex, true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 添加默认拒接规则
 | 
				
			||||||
 | 
					            regex = ".*";
 | 
				
			||||||
 | 
					            rules.add(regex, false, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 保存规则到文件
 | 
				
			||||||
 | 
					            rules.saveRules();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 开始测试数据
 | 
				
			||||||
 | 
					        String phone = "16769764848";
 | 
				
			||||||
 | 
					        LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        phone = "16856582777";
 | 
				
			||||||
 | 
					        LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        phone = "17519703124";
 | 
				
			||||||
 | 
					        LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        phone = "0205658955";
 | 
				
			||||||
 | 
					        LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        phone = "0108965253";
 | 
				
			||||||
 | 
					        LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        phone = "+8616769764848";
 | 
				
			||||||
 | 
					        LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        phone = "4005816769764848";
 | 
				
			||||||
 | 
					        LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        phone = "95566";
 | 
				
			||||||
 | 
					        LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,42 +0,0 @@
 | 
				
			|||||||
package cc.winboll.studio.contacts.adapters;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @Author ZhanGSKen@AliYun.Com
 | 
					 | 
				
			||||||
 * @Date 2025/02/20 13:33:04
 | 
					 | 
				
			||||||
 * @Describe MyPagerAdapter
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
import androidx.annotation.NonNull;
 | 
					 | 
				
			||||||
import androidx.fragment.app.Fragment;
 | 
					 | 
				
			||||||
import androidx.fragment.app.FragmentManager;
 | 
					 | 
				
			||||||
import androidx.fragment.app.FragmentPagerAdapter;
 | 
					 | 
				
			||||||
import cc.winboll.studio.contacts.fragments.CallLogFragment;
 | 
					 | 
				
			||||||
import cc.winboll.studio.contacts.fragments.ContactsFragment;
 | 
					 | 
				
			||||||
import cc.winboll.studio.contacts.fragments.LogFragment;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class MyPagerAdapter2 extends FragmentPagerAdapter {
 | 
					 | 
				
			||||||
    public static final String TAG = "MyPagerAdapter";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static final int PAGE_COUNT = 3;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public MyPagerAdapter2(@NonNull FragmentManager fm) {
 | 
					 | 
				
			||||||
        super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @NonNull
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public Fragment getItem(int position) {
 | 
					 | 
				
			||||||
        if(position == 1) {
 | 
					 | 
				
			||||||
            return ContactsFragment.newInstance(position);
 | 
					 | 
				
			||||||
        } else if(position == 2) {
 | 
					 | 
				
			||||||
            return LogFragment.newInstance(position);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return CallLogFragment.newInstance(position);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public int getCount() {
 | 
					 | 
				
			||||||
        return PAGE_COUNT;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					package cc.winboll.studio.contacts.adapters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @Author ZhanGSKen@AliYun.Com
 | 
				
			||||||
 | 
					 * @Date 2025/03/02 17:27:41
 | 
				
			||||||
 | 
					 * @Describe PhoneConnectRuleAdapter
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import android.content.Context;
 | 
				
			||||||
 | 
					import android.view.LayoutInflater;
 | 
				
			||||||
 | 
					import android.view.View;
 | 
				
			||||||
 | 
					import android.view.ViewGroup;
 | 
				
			||||||
 | 
					import android.widget.Button;
 | 
				
			||||||
 | 
					import android.widget.CheckBox;
 | 
				
			||||||
 | 
					import android.widget.EditText;
 | 
				
			||||||
 | 
					import android.widget.TextView;
 | 
				
			||||||
 | 
					import android.widget.Toast;
 | 
				
			||||||
 | 
					import androidx.annotation.NonNull;
 | 
				
			||||||
 | 
					import androidx.recyclerview.widget.RecyclerView;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.R;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.dun.Rules;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final String TAG = "PhoneConnectRuleAdapter";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final int VIEW_TYPE_SIMPLE = 0;
 | 
				
			||||||
 | 
					    private static final int VIEW_TYPE_EDIT = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Context context;
 | 
				
			||||||
 | 
					    private List<PhoneConnectRuleModel> ruleList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public PhoneConnectRuleAdapter(Context context, List<PhoneConnectRuleModel> ruleList) {
 | 
				
			||||||
 | 
					        this.context = context;
 | 
				
			||||||
 | 
					        this.ruleList = ruleList;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @NonNull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
 | 
				
			||||||
 | 
					        LayoutInflater inflater = LayoutInflater.from(context);
 | 
				
			||||||
 | 
					        if (viewType == VIEW_TYPE_SIMPLE) {
 | 
				
			||||||
 | 
					            View view = inflater.inflate(R.layout.view_phone_connect_rule_simple, parent, false);
 | 
				
			||||||
 | 
					            return new SimpleViewHolder(view);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            View view = inflater.inflate(R.layout.view_phone_connect_rule, parent, false);
 | 
				
			||||||
 | 
					            return new EditViewHolder(view);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
 | 
				
			||||||
 | 
					        final PhoneConnectRuleModel model = ruleList.get(position);
 | 
				
			||||||
 | 
					        if (holder instanceof SimpleViewHolder) {
 | 
				
			||||||
 | 
					            SimpleViewHolder simpleViewHolder = (SimpleViewHolder) holder;
 | 
				
			||||||
 | 
					            simpleViewHolder.textView.setText(model.getRuleText());
 | 
				
			||||||
 | 
					            simpleViewHolder.button.setOnClickListener(new View.OnClickListener() {
 | 
				
			||||||
 | 
					                    @Override
 | 
				
			||||||
 | 
					                    public void onClick(View v) {
 | 
				
			||||||
 | 
					                        model.setIsSimpleView(false);
 | 
				
			||||||
 | 
					                        notifyItemChanged(position);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        } else if (holder instanceof EditViewHolder) {
 | 
				
			||||||
 | 
					            final EditViewHolder editViewHolder = (EditViewHolder) holder;
 | 
				
			||||||
 | 
					            editViewHolder.editText.setText(model.getRuleText());
 | 
				
			||||||
 | 
					            editViewHolder.checkBoxAllow.setChecked(model.isAllowConnection());
 | 
				
			||||||
 | 
					            editViewHolder.checkBoxEnable.setChecked(model.isEnable());
 | 
				
			||||||
 | 
					            editViewHolder.buttonConfirm.setOnClickListener(new View.OnClickListener() {
 | 
				
			||||||
 | 
					                    @Override
 | 
				
			||||||
 | 
					                    public void onClick(View v) {
 | 
				
			||||||
 | 
					                        model.setRuleText(editViewHolder.editText.getText().toString());
 | 
				
			||||||
 | 
					                        model.setIsAllowConnection(editViewHolder.checkBoxAllow.isChecked());
 | 
				
			||||||
 | 
					                        model.setIsEnable(editViewHolder.checkBoxEnable.isChecked());
 | 
				
			||||||
 | 
					                        model.setIsSimpleView(true);
 | 
				
			||||||
 | 
					                        Rules.getInstance(context).saveRules();
 | 
				
			||||||
 | 
					                        notifyItemChanged(position);
 | 
				
			||||||
 | 
					                        Toast.makeText(context, "保存成功", Toast.LENGTH_SHORT).show();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int getItemCount() {
 | 
				
			||||||
 | 
					        return ruleList.size();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int getItemViewType(int position) {
 | 
				
			||||||
 | 
					        PhoneConnectRuleModel model = ruleList.get(position);
 | 
				
			||||||
 | 
					        // 这里可以根据模型的状态来决定视图类型,简单起见,假设点击按钮后进入编辑视图
 | 
				
			||||||
 | 
					        return model.isSimpleView() ? VIEW_TYPE_SIMPLE : VIEW_TYPE_EDIT;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static class SimpleViewHolder extends RecyclerView.ViewHolder {
 | 
				
			||||||
 | 
					        TextView textView;
 | 
				
			||||||
 | 
					        Button button;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public SimpleViewHolder(@NonNull View itemView) {
 | 
				
			||||||
 | 
					            super(itemView);
 | 
				
			||||||
 | 
					            textView = itemView.findViewById(R.id.text_view);
 | 
				
			||||||
 | 
					            button = itemView.findViewById(R.id.button);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static class EditViewHolder extends RecyclerView.ViewHolder {
 | 
				
			||||||
 | 
					        EditText editText;
 | 
				
			||||||
 | 
					        CheckBox checkBoxAllow;
 | 
				
			||||||
 | 
					        CheckBox checkBoxEnable;
 | 
				
			||||||
 | 
					        Button buttonConfirm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public EditViewHolder(@NonNull View itemView) {
 | 
				
			||||||
 | 
					            super(itemView);
 | 
				
			||||||
 | 
					            editText = itemView.findViewById(R.id.edit_text);
 | 
				
			||||||
 | 
					            checkBoxAllow = itemView.findViewById(R.id.checkbox_allow);
 | 
				
			||||||
 | 
					            checkBoxEnable = itemView.findViewById(R.id.checkbox_enable);
 | 
				
			||||||
 | 
					            buttonConfirm = itemView.findViewById(R.id.button_confirm);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -10,21 +10,35 @@ import android.util.JsonWriter;
 | 
				
			|||||||
import cc.winboll.studio.libappbase.BaseBean;
 | 
					import cc.winboll.studio.libappbase.BaseBean;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class PhoneBlackRuleBean extends BaseBean {
 | 
					public class PhoneConnectRuleModel extends BaseBean {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static final String TAG = "PhoneBlackRuleBean";
 | 
					    public static final String TAG = "PhoneConnectRuleModel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    String ruleText;
 | 
					    String ruleText;
 | 
				
			||||||
 | 
					    boolean isAllowConnection;
 | 
				
			||||||
    boolean isEnable;
 | 
					    boolean isEnable;
 | 
				
			||||||
 | 
					    boolean isSimpleView;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public PhoneBlackRuleBean() {
 | 
					    public PhoneConnectRuleModel() {
 | 
				
			||||||
        this.ruleText = "";
 | 
					        this.ruleText = "";
 | 
				
			||||||
 | 
					        this.isAllowConnection = false;
 | 
				
			||||||
        this.isEnable = false;
 | 
					        this.isEnable = false;
 | 
				
			||||||
 | 
					        this.isSimpleView = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public PhoneBlackRuleBean(String ruleText, boolean isEnable) {
 | 
					    public PhoneConnectRuleModel(String ruleText, boolean isAllowConnection, boolean isEnable) {
 | 
				
			||||||
        this.ruleText = ruleText;
 | 
					        this.ruleText = ruleText;
 | 
				
			||||||
 | 
					        this.isAllowConnection = isAllowConnection;
 | 
				
			||||||
        this.isEnable = isEnable;
 | 
					        this.isEnable = isEnable;
 | 
				
			||||||
 | 
					        this.isSimpleView = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setIsSimpleView(boolean isSimpleView) {
 | 
				
			||||||
 | 
					        this.isSimpleView = isSimpleView;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isSimpleView() {
 | 
				
			||||||
 | 
					        return isSimpleView;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void setRuleText(String ruleText) {
 | 
					    public void setRuleText(String ruleText) {
 | 
				
			||||||
@@ -35,6 +49,14 @@ public class PhoneBlackRuleBean extends BaseBean {
 | 
				
			|||||||
        return ruleText;
 | 
					        return ruleText;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setIsAllowConnection(boolean isAllowConnection) {
 | 
				
			||||||
 | 
					        this.isAllowConnection = isAllowConnection;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isAllowConnection() {
 | 
				
			||||||
 | 
					        return isAllowConnection;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void setIsEnable(boolean isEnable) {
 | 
					    public void setIsEnable(boolean isEnable) {
 | 
				
			||||||
        this.isEnable = isEnable;
 | 
					        this.isEnable = isEnable;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -43,17 +65,19 @@ public class PhoneBlackRuleBean extends BaseBean {
 | 
				
			|||||||
        return isEnable;
 | 
					        return isEnable;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public String getName() {
 | 
					    public String getName() {
 | 
				
			||||||
        return PhoneBlackRuleBean.class.getName();
 | 
					        return PhoneConnectRuleModel.class.getName();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
 | 
					    public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
 | 
				
			||||||
        super.writeThisToJsonWriter(jsonWriter);
 | 
					        super.writeThisToJsonWriter(jsonWriter);
 | 
				
			||||||
        jsonWriter.name("ruleText").value(getRuleText());
 | 
					        jsonWriter.name("ruleText").value(getRuleText());
 | 
				
			||||||
 | 
					        jsonWriter.name("isAllowConnection").value(isAllowConnection());
 | 
				
			||||||
        jsonWriter.name("isEnable").value(isEnable());
 | 
					        jsonWriter.name("isEnable").value(isEnable());
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
@@ -61,6 +85,8 @@ public class PhoneBlackRuleBean extends BaseBean {
 | 
				
			|||||||
        if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
 | 
					        if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
 | 
				
			||||||
            if (name.equals("ruleText")) {
 | 
					            if (name.equals("ruleText")) {
 | 
				
			||||||
                setRuleText(jsonReader.nextString());
 | 
					                setRuleText(jsonReader.nextString());
 | 
				
			||||||
 | 
					            } else if (name.equals("isAllowConnection")) {
 | 
				
			||||||
 | 
					                setIsAllowConnection(jsonReader.nextBoolean());
 | 
				
			||||||
            } else if (name.equals("isEnable")) {
 | 
					            } else if (name.equals("isEnable")) {
 | 
				
			||||||
                setIsEnable(jsonReader.nextBoolean());
 | 
					                setIsEnable(jsonReader.nextBoolean());
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
@@ -0,0 +1,142 @@
 | 
				
			|||||||
 | 
					package cc.winboll.studio.contacts.bobulltoon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @Author ZhanGSKen@AliYun.Com
 | 
				
			||||||
 | 
					 * @Date 2025/03/02 13:47:48
 | 
				
			||||||
 | 
					 * @Describe 汤姆猫管家 :使用 BoBullToon 项目,对通讯地址进行筛选判断的好朋友。
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import android.content.Context;
 | 
				
			||||||
 | 
					import cc.winboll.studio.libappbase.LogUtils;
 | 
				
			||||||
 | 
					import com.hjq.toast.ToastUtils;
 | 
				
			||||||
 | 
					import java.io.File;
 | 
				
			||||||
 | 
					import java.io.FileOutputStream;
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.io.InputStream;
 | 
				
			||||||
 | 
					import java.nio.file.Files;
 | 
				
			||||||
 | 
					import java.nio.file.Path;
 | 
				
			||||||
 | 
					import java.nio.file.Paths;
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.zip.ZipEntry;
 | 
				
			||||||
 | 
					import java.util.zip.ZipInputStream;
 | 
				
			||||||
 | 
					import okhttp3.OkHttpClient;
 | 
				
			||||||
 | 
					import okhttp3.Request;
 | 
				
			||||||
 | 
					import okhttp3.Response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TomCat {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final String TAG = "TomCat";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    List<String> listPhoneBoBullToon = new ArrayList<String>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static volatile TomCat _TomCat;
 | 
				
			||||||
 | 
					    Context mContext;
 | 
				
			||||||
 | 
					    TomCat(Context context) {
 | 
				
			||||||
 | 
					        mContext = context;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static synchronized TomCat getInstance(Context context) {
 | 
				
			||||||
 | 
					        if (_TomCat == null) {
 | 
				
			||||||
 | 
					            _TomCat = new TomCat(context);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return _TomCat;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void downloadAndExtractZip(String zipUrl, String destinationFolder) throws IOException {
 | 
				
			||||||
 | 
					        OkHttpClient client = new OkHttpClient();
 | 
				
			||||||
 | 
					        Request request = new Request.Builder()
 | 
				
			||||||
 | 
					            .url(zipUrl)
 | 
				
			||||||
 | 
					            .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try (Response response = client.newCall(request).execute()) {
 | 
				
			||||||
 | 
					            if (!response.isSuccessful()) {
 | 
				
			||||||
 | 
					                throw new IOException("Unexpected code " + response);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 下载 ZIP 文件到临时位置
 | 
				
			||||||
 | 
					            File tempZipFile = File.createTempFile("temp", ".zip");
 | 
				
			||||||
 | 
					            try (InputStream inputStream = response.body().byteStream();
 | 
				
			||||||
 | 
					            FileOutputStream outputStream = new FileOutputStream(tempZipFile)) {
 | 
				
			||||||
 | 
					                byte[] buffer = new byte[1024];
 | 
				
			||||||
 | 
					                int length;
 | 
				
			||||||
 | 
					                while ((length = inputStream.read(buffer)) > 0) {
 | 
				
			||||||
 | 
					                    outputStream.write(buffer, 0, length);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 解压 ZIP 文件到指定文件夹
 | 
				
			||||||
 | 
					            try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(tempZipFile.toPath()))) {
 | 
				
			||||||
 | 
					                ZipEntry zipEntry;
 | 
				
			||||||
 | 
					                while ((zipEntry = zipInputStream.getNextEntry()) != null) {
 | 
				
			||||||
 | 
					                    Path targetFilePath = Paths.get(destinationFolder, zipEntry.getName());
 | 
				
			||||||
 | 
					                    if (zipEntry.isDirectory()) {
 | 
				
			||||||
 | 
					                        Files.createDirectories(targetFilePath);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        Files.createDirectories(targetFilePath.getParent());
 | 
				
			||||||
 | 
					                        try (FileOutputStream fos = new FileOutputStream(targetFilePath.toFile())) {
 | 
				
			||||||
 | 
					                            byte[] buffer = new byte[1024];
 | 
				
			||||||
 | 
					                            int len;
 | 
				
			||||||
 | 
					                            while ((len = zipInputStream.read(buffer)) > 0) {
 | 
				
			||||||
 | 
					                                fos.write(buffer, 0, len);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    zipInputStream.closeEntry();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 删除临时 ZIP 文件
 | 
				
			||||||
 | 
					            tempZipFile.delete();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean downloadBoBullToon() {
 | 
				
			||||||
 | 
					        String zipUrl = "https://gitea.winboll.cc//Studio/BoBullToon/archive/main.zip"; // 替换为实际的 ZIP 文件 URL
 | 
				
			||||||
 | 
					        String destinationFolder = getWorkingFolder().getPath(); // 替换为实际的目标文件夹路径
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            downloadAndExtractZip(zipUrl, destinationFolder);
 | 
				
			||||||
 | 
					            LogUtils.d(TAG, "ZIP 文件下载并解压成功。");
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    File getWorkingFolder() {
 | 
				
			||||||
 | 
					        return mContext.getExternalFilesDir(TAG);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean loadPhoneBoBullToon() {
 | 
				
			||||||
 | 
					        listPhoneBoBullToon.clear();
 | 
				
			||||||
 | 
					        File fBoBullToon = new File(getWorkingFolder(), "bobulltoon");
 | 
				
			||||||
 | 
					        if (fBoBullToon.exists()) {
 | 
				
			||||||
 | 
					            LogUtils.d(TAG, String.format("getWorkingFolder() %s", getWorkingFolder()));
 | 
				
			||||||
 | 
					            for (File userFolder : fBoBullToon.listFiles()) {
 | 
				
			||||||
 | 
					                if (userFolder.isDirectory()) {
 | 
				
			||||||
 | 
					                    for (File recordFile : userFolder.listFiles()) {
 | 
				
			||||||
 | 
					                        listPhoneBoBullToon.add(recordFile.getName());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < listPhoneBoBullToon.size(); i++) {
 | 
				
			||||||
 | 
					                LogUtils.d(TAG, String.format("listPhoneBoBullToon add : %s", listPhoneBoBullToon.get(i)));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            LogUtils.d(TAG, "fBoBullToon not exists。");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isPhoneBoBullToon(String phone) {
 | 
				
			||||||
 | 
					        for (int i = 0; i < listPhoneBoBullToon.size(); i++) {
 | 
				
			||||||
 | 
					            LogUtils.d(TAG, String.format("isPhoneBoBullToon(...) get(i) phone : %s", listPhoneBoBullToon.get(i)));
 | 
				
			||||||
 | 
					            if (listPhoneBoBullToon.get(i).equals(phone)) {
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,25 +5,28 @@ package cc.winboll.studio.contacts.dun;
 | 
				
			|||||||
 * @Date 2025/02/21 06:15:10
 | 
					 * @Date 2025/02/21 06:15:10
 | 
				
			||||||
 * @Describe 云盾防御规则
 | 
					 * @Describe 云盾防御规则
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
import cc.winboll.studio.contacts.beans.PhoneBlackRuleBean;
 | 
					import android.content.Context;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.services.MainService;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.utils.RegexPPiUtils;
 | 
				
			||||||
 | 
					import cc.winboll.studio.libappbase.LogUtils;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.regex.Pattern;
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
import android.content.Context;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class Rules {
 | 
					public class Rules {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static final String TAG = "Rules";
 | 
					    public static final String TAG = "Rules";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ArrayList<PhoneBlackRuleBean> _PhoneBlacRuleBeanList;
 | 
					    ArrayList<PhoneConnectRuleModel> _PhoneConnectRuleModelList;
 | 
				
			||||||
    static volatile Rules _Rules;
 | 
					    static volatile Rules _Rules;
 | 
				
			||||||
    Context mContext;
 | 
					    Context mContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Rules(Context context) {
 | 
					    Rules(Context context) {
 | 
				
			||||||
        mContext = context;
 | 
					        mContext = context;
 | 
				
			||||||
        _PhoneBlacRuleBeanList = new ArrayList<PhoneBlackRuleBean>();
 | 
					        _PhoneConnectRuleModelList = new ArrayList<PhoneConnectRuleModel>();
 | 
				
			||||||
        PhoneBlackRuleBean.loadBeanList(mContext, _PhoneBlacRuleBeanList, PhoneBlackRuleBean.class);
 | 
					        loadRules();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static synchronized Rules getInstance(Context context) {
 | 
					    public static synchronized Rules getInstance(Context context) {
 | 
				
			||||||
        if (_Rules == null) {
 | 
					        if (_Rules == null) {
 | 
				
			||||||
            _Rules = new Rules(context);
 | 
					            _Rules = new Rules(context);
 | 
				
			||||||
@@ -31,46 +34,47 @@ public class Rules {
 | 
				
			|||||||
        return _Rules;
 | 
					        return _Rules;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void loadRules() {
 | 
				
			||||||
 | 
					        _PhoneConnectRuleModelList.clear();
 | 
				
			||||||
 | 
					        PhoneConnectRuleModel.loadBeanList(mContext, _PhoneConnectRuleModelList, PhoneConnectRuleModel.class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void saveRules() {
 | 
				
			||||||
 | 
					        PhoneConnectRuleModel.saveBeanList(mContext, _PhoneConnectRuleModelList, PhoneConnectRuleModel.class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean isAllowed(String phoneNumber) {
 | 
					    public boolean isAllowed(String phoneNumber) {
 | 
				
			||||||
        // 黑名单拒接
 | 
					        // 正则运算预防针
 | 
				
			||||||
        for (int i = 0; i < _PhoneBlacRuleBeanList.size(); i++) {
 | 
					        if (!RegexPPiUtils.isPPiOK(phoneNumber)) {
 | 
				
			||||||
            if (_PhoneBlacRuleBeanList.get(i).isEnable()) {
 | 
					            LogUtils.d(TAG, "RegexPPiUtils.isPPiOK return false.");
 | 
				
			||||||
                String regex = _PhoneBlacRuleBeanList.get(i).getRuleText();
 | 
					 | 
				
			||||||
                if (Pattern.matches(regex, phoneNumber)) {
 | 
					 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            }
 | 
					        // 检验拨不通号码群
 | 
				
			||||||
        }
 | 
					        if (MainService.isPhoneInBoBullToon(phoneNumber)) {
 | 
				
			||||||
 | 
					            LogUtils.d(TAG, String.format("PhoneNumber %s\n Is In BoBullToon", phoneNumber));
 | 
				
			||||||
        // 手机号码允许
 | 
					 | 
				
			||||||
        // 中国手机号码正则表达式,以1开头,第二位可以是3、4、5、6、7、8、9,后面跟9位数字
 | 
					 | 
				
			||||||
        String regex = "^1[3-9]\\d{9}$";
 | 
					 | 
				
			||||||
        if (Pattern.matches(regex, phoneNumber)) {
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // 指定区号号码允许
 | 
					 | 
				
			||||||
        regex = "^0660\\d+$";
 | 
					 | 
				
			||||||
        if (Pattern.matches(regex, phoneNumber)) {
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // 指定区号号码允许
 | 
					 | 
				
			||||||
        regex = "^020\\d+$";
 | 
					 | 
				
			||||||
        if (Pattern.matches(regex, phoneNumber)) {
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // 其他拒接
 | 
					 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void add(String phoneRuleBlack, boolean isEnable) {
 | 
					        // 正则匹配规则名单校验
 | 
				
			||||||
        _PhoneBlacRuleBeanList.add(new PhoneBlackRuleBean(phoneRuleBlack, isEnable));
 | 
					        for (int i = 0; i < _PhoneConnectRuleModelList.size(); i++) {
 | 
				
			||||||
        PhoneBlackRuleBean.saveBeanList(mContext, _PhoneBlacRuleBeanList, PhoneBlackRuleBean.class);
 | 
					            if (_PhoneConnectRuleModelList.get(i).isEnable()) {
 | 
				
			||||||
 | 
					                String regex = _PhoneConnectRuleModelList.get(i).getRuleText();
 | 
				
			||||||
 | 
					                if (Pattern.matches(regex, phoneNumber)) {
 | 
				
			||||||
 | 
					                    LogUtils.d(TAG, String.format("phoneNumber :%s \nisAllowConnection %s By Rule : %s", phoneNumber, _PhoneConnectRuleModelList.get(i).isAllowConnection(), _PhoneConnectRuleModelList.get(i)));
 | 
				
			||||||
 | 
					                    return _PhoneConnectRuleModelList.get(i).isAllowConnection();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ArrayList<PhoneBlackRuleBean> getPhoneBlacRuleBeanList() {
 | 
					        // 其他默认接收
 | 
				
			||||||
        return _PhoneBlacRuleBeanList;
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void add(String szPhoneConnectRule, boolean isAllowConnection, boolean isEnable) {
 | 
				
			||||||
 | 
					        _PhoneConnectRuleModelList.add(new PhoneConnectRuleModel(szPhoneConnectRule, isAllowConnection, isEnable));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ArrayList<PhoneConnectRuleModel> getPhoneBlacRuleBeanList() {
 | 
				
			||||||
 | 
					        return _PhoneConnectRuleModelList;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -104,6 +104,7 @@ public class ContactsFragment extends Fragment {
 | 
				
			|||||||
                public void onClick(View p1) {
 | 
					                public void onClick(View p1) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    String phoneNumber = searchEditText.getText().toString().replaceAll("\\s", "");
 | 
					                    String phoneNumber = searchEditText.getText().toString().replaceAll("\\s", "");
 | 
				
			||||||
 | 
					                    //phoneNumber = "+8616769764848";
 | 
				
			||||||
                    ToastUtils.show(phoneNumber);
 | 
					                    ToastUtils.show(phoneNumber);
 | 
				
			||||||
                    Intent intent = new Intent(Intent.ACTION_CALL);
 | 
					                    Intent intent = new Intent(Intent.ACTION_CALL);
 | 
				
			||||||
                    intent.setData(android.net.Uri.parse("tel:" + phoneNumber));
 | 
					                    intent.setData(android.net.Uri.parse("tel:" + phoneNumber));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,7 @@ import cc.winboll.studio.libappbase.SOS;
 | 
				
			|||||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
 | 
					import cc.winboll.studio.libappbase.bean.APPSOSBean;
 | 
				
			||||||
import java.util.Timer;
 | 
					import java.util.Timer;
 | 
				
			||||||
import java.util.TimerTask;
 | 
					import java.util.TimerTask;
 | 
				
			||||||
 | 
					import cc.winboll.studio.contacts.bobulltoon.TomCat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class MainService extends Service {
 | 
					public class MainService extends Service {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,6 +51,7 @@ public class MainService extends Service {
 | 
				
			|||||||
    boolean isBound = false;
 | 
					    boolean isBound = false;
 | 
				
			||||||
    MainReceiver mMainReceiver;
 | 
					    MainReceiver mMainReceiver;
 | 
				
			||||||
    Timer mStreamVolumeCheckTimer;
 | 
					    Timer mStreamVolumeCheckTimer;
 | 
				
			||||||
 | 
					    static volatile TomCat _TomCat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public IBinder onBind(Intent intent) {
 | 
					    public IBinder onBind(Intent intent) {
 | 
				
			||||||
@@ -128,6 +130,12 @@ public class MainService extends Service {
 | 
				
			|||||||
            // 召唤 WinBoll APP 绑定本服务
 | 
					            // 召唤 WinBoll APP 绑定本服务
 | 
				
			||||||
            SOS.bindToAPPService(this, new APPSOSBean(getPackageName(), MainService.class.getName()));
 | 
					            SOS.bindToAPPService(this, new APPSOSBean(getPackageName(), MainService.class.getName()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 初始化服务运行参数
 | 
				
			||||||
 | 
					            _TomCat = TomCat.getInstance(this);
 | 
				
			||||||
 | 
					            if (!_TomCat.loadPhoneBoBullToon()) {
 | 
				
			||||||
 | 
					                LogUtils.d(TAG, "没有下载 BoBullToon 数据。BoBullToon 参数无法加载。");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (mMainReceiver == null) {
 | 
					            if (mMainReceiver == null) {
 | 
				
			||||||
                // 注册广播接收器
 | 
					                // 注册广播接收器
 | 
				
			||||||
                mMainReceiver = new MainReceiver(this);
 | 
					                mMainReceiver = new MainReceiver(this);
 | 
				
			||||||
@@ -135,8 +143,6 @@ public class MainService extends Service {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Rules.getInstance(this);
 | 
					            Rules.getInstance(this);
 | 
				
			||||||
            //Rules.getInstance(this).add("18888888888", true);
 | 
					 | 
				
			||||||
            //Rules.getInstance(this).add("16769764848", true);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            startPhoneCallListener();
 | 
					            startPhoneCallListener();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -146,6 +152,14 @@ public class MainService extends Service {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static boolean isPhoneInBoBullToon(String phone) {
 | 
				
			||||||
 | 
					        if (_TomCat != null) {
 | 
				
			||||||
 | 
					            return _TomCat.isPhoneBoBullToon(phone);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 唤醒和绑定守护进程
 | 
					    // 唤醒和绑定守护进程
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    void wakeupAndBindAssistant() {
 | 
					    void wakeupAndBindAssistant() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					package cc.winboll.studio.contacts.utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @Author ZhanGSKen@QQ.COM
 | 
				
			||||||
 | 
					 * @Date 2024/12/09 19:00:21
 | 
				
			||||||
 | 
					 * @Describe .* 前置预防针
 | 
				
			||||||
 | 
					 regex pointer preventive injection
 | 
				
			||||||
 | 
					 简称 RegexPPi
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import java.util.regex.Matcher;
 | 
				
			||||||
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class RegexPPiUtils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final String TAG = "RegexPPiUtils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // 检验文本是否满足适合正则表达式模式计算
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    public static boolean isPPiOK(String text) {
 | 
				
			||||||
 | 
					        //String text = "这里是一些任意的文本内容";
 | 
				
			||||||
 | 
					        String regex = ".*";
 | 
				
			||||||
 | 
					        Pattern pattern = Pattern.compile(regex);
 | 
				
			||||||
 | 
					        Matcher matcher = pattern.matcher(text);
 | 
				
			||||||
 | 
					        /*if (matcher.matches()) {
 | 
				
			||||||
 | 
					         System.out.println("文本满足该正则表达式模式");
 | 
				
			||||||
 | 
					         } else {
 | 
				
			||||||
 | 
					         System.out.println("文本不满足该正则表达式模式");
 | 
				
			||||||
 | 
					         }*/
 | 
				
			||||||
 | 
					        return matcher.matches();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								contacts/src/main/res/drawable/recycler_view_border.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								contacts/src/main/res/drawable/recycler_view_border.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<shape xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    android:shape="rectangle">
 | 
				
			||||||
 | 
					    <stroke
 | 
				
			||||||
 | 
					        android:width="1dp"
 | 
				
			||||||
 | 
					        android:color="#000000" /> <!-- 设置边框宽度和颜色,这里是黑色 1dp 边框 -->
 | 
				
			||||||
 | 
					    <solid android:color="#ffffff" /> <!-- 设置背景颜色,这里是白色 -->
 | 
				
			||||||
 | 
					</shape>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -90,6 +90,86 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		</LinearLayout>
 | 
							</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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<TextView
 | 
				
			||||||
 | 
								android:layout_width="wrap_content"
 | 
				
			||||||
 | 
								android:layout_height="wrap_content"
 | 
				
			||||||
 | 
								android:text="Phone Connect Rule :"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<androidx.recyclerview.widget.RecyclerView
 | 
				
			||||||
 | 
								android:id="@+id/recycler_view"
 | 
				
			||||||
 | 
								android:layout_width="match_parent"
 | 
				
			||||||
 | 
								android:layout_height="0dp"
 | 
				
			||||||
 | 
								android:layout_weight="1.0"
 | 
				
			||||||
 | 
								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>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								contacts/src/main/res/layout/activity_unittest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								contacts/src/main/res/layout/activity_unittest.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					<?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:orientation="vertical"
 | 
				
			||||||
 | 
						android:layout_width="match_parent"
 | 
				
			||||||
 | 
						android:layout_height="match_parent">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<HorizontalScrollView
 | 
				
			||||||
 | 
							android:layout_width="match_parent"
 | 
				
			||||||
 | 
							android:layout_height="wrap_content">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<Button
 | 
				
			||||||
 | 
								android:layout_width="wrap_content"
 | 
				
			||||||
 | 
								android:layout_height="wrap_content"
 | 
				
			||||||
 | 
								android:text="Test Main"
 | 
				
			||||||
 | 
								android:onClick="onTestMain"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</HorizontalScrollView>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<cc.winboll.studio.libappbase.LogView
 | 
				
			||||||
 | 
							android:layout_width="match_parent"
 | 
				
			||||||
 | 
							android:layout_height="0dp"
 | 
				
			||||||
 | 
							android:layout_weight="1.0"
 | 
				
			||||||
 | 
							android:id="@+id/logview"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										44
									
								
								contacts/src/main/res/layout/view_phone_connect_rule.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								contacts/src/main/res/layout/view_phone_connect_rule.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					<?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:orientation="vertical"
 | 
				
			||||||
 | 
						android:layout_width="match_parent"
 | 
				
			||||||
 | 
						android:layout_height="wrap_content"
 | 
				
			||||||
 | 
						android:padding="16dp">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<EditText
 | 
				
			||||||
 | 
							android:id="@+id/edit_text"
 | 
				
			||||||
 | 
							android:layout_width="match_parent"
 | 
				
			||||||
 | 
							android:layout_height="wrap_content"
 | 
				
			||||||
 | 
							android:hint="请输入规则文本"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<LinearLayout
 | 
				
			||||||
 | 
							android:orientation="horizontal"
 | 
				
			||||||
 | 
							android:layout_width="match_parent"
 | 
				
			||||||
 | 
							android:layout_height="wrap_content"
 | 
				
			||||||
 | 
							android:gravity="right|center_vertical">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<CheckBox
 | 
				
			||||||
 | 
								android:id="@+id/checkbox_allow"
 | 
				
			||||||
 | 
								android:layout_width="wrap_content"
 | 
				
			||||||
 | 
								android:layout_height="wrap_content"
 | 
				
			||||||
 | 
								android:text="允许连接"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <CheckBox
 | 
				
			||||||
 | 
					            android:id="@+id/checkbox_enable"
 | 
				
			||||||
 | 
					            android:layout_width="wrap_content"
 | 
				
			||||||
 | 
					            android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					            android:text="启用"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <Button
 | 
				
			||||||
 | 
					            android:id="@+id/button_confirm"
 | 
				
			||||||
 | 
					            android:layout_width="wrap_content"
 | 
				
			||||||
 | 
					            android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					            android:text="确定"/>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
						</LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					<?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:orientation="horizontal"
 | 
				
			||||||
 | 
						android:layout_width="match_parent"
 | 
				
			||||||
 | 
						android:layout_height="wrap_content"
 | 
				
			||||||
 | 
						android:padding="16dp"
 | 
				
			||||||
 | 
						android:gravity="center_vertical">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<TextView
 | 
				
			||||||
 | 
							android:id="@+id/text_view"
 | 
				
			||||||
 | 
							android:layout_width="0dp"
 | 
				
			||||||
 | 
							android:layout_height="wrap_content"
 | 
				
			||||||
 | 
							android:layout_weight="1"
 | 
				
			||||||
 | 
							android:textSize="16sp"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<Button
 | 
				
			||||||
 | 
							android:id="@+id/button"
 | 
				
			||||||
 | 
							android:layout_width="wrap_content"
 | 
				
			||||||
 | 
							android:layout_height="wrap_content"
 | 
				
			||||||
 | 
							android:text="编辑"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user