diff --git a/app/build.gradle b/app/build.gradle index a1464c4..602363c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { applicationId "com.uiui.aios" minSdkVersion 24 targetSdkVersion 29 - versionCode 51 - versionName "6.0" + versionCode 52 + versionName "6.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/com/uiui/aios/activity/main/MainActivity.java b/app/src/main/java/com/uiui/aios/activity/main/MainActivity.java index a696cb3..b30bed2 100644 --- a/app/src/main/java/com/uiui/aios/activity/main/MainActivity.java +++ b/app/src/main/java/com/uiui/aios/activity/main/MainActivity.java @@ -36,6 +36,7 @@ import com.uiui.aios.bean.AlarmItem; import com.uiui.aios.bean.DesktopIcon; import com.uiui.aios.dialog.PasswordDialog; import com.uiui.aios.fragment.AppListFragment; +import com.uiui.aios.fragment.ControlFragment; import com.uiui.aios.fragment.SecondFragment; import com.uiui.aios.fragment.custom.CustomFragment; import com.uiui.aios.service.NotificationService; @@ -70,11 +71,12 @@ public class MainActivity extends BaseActivity implements MainContact.MainView { private ScaleCircleNavigator scaleCircleNavigator; private BaseFragmentPagerAdapter mBaseFragmentPagerAdapter; private List mFragments; + private ControlFragment mControlFragment; private CustomFragment mCustomFragment; private SecondFragment mSecondFragment; private boolean is_twoscreen = false; - private int appListIndex = 1; - private int defaultCurrent = 0; + private int appListIndex = 2; + private int defaultCurrent = 1; private HomeWatcher mHomeWatcher; @@ -104,19 +106,18 @@ public class MainActivity extends BaseActivity implements MainContact.MainView { mBaseFragmentPagerAdapter = new BaseFragmentPagerAdapter(mFragmentManager, mFragments); // fragmentTransaction.add(R.id.viewPager, appListFragment); // fragmentTransaction.commit(); - + mControlFragment = new ControlFragment(); + mFragments.add(mControlFragment); is_twoscreen = Settings.Global.getInt(getContentResolver(), "is_twoscreen", 0) == 1; if (is_twoscreen) { - appListIndex = 2; - defaultCurrent = 1; + appListIndex = 3; + defaultCurrent = 2; mSecondFragment = new SecondFragment(); mFragments.add(mSecondFragment); } mCustomFragment = new CustomFragment(); mFragments.add(mCustomFragment); - mMainPresenter.getSystemSettings(); - ArrayList desktopIcons = ApkUtils.queryFilterAppInfo(this); int x = 0; for (int i = 0; i <= desktopIcons.size(); i++) { diff --git a/app/src/main/java/com/uiui/aios/fragment/ControlFragment.java b/app/src/main/java/com/uiui/aios/fragment/ControlFragment.java new file mode 100644 index 0000000..781dc31 --- /dev/null +++ b/app/src/main/java/com/uiui/aios/fragment/ControlFragment.java @@ -0,0 +1,815 @@ +package com.uiui.aios.fragment; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraManager; +import android.media.AudioManager; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.BatteryManager; +import android.os.Build; +import android.os.Bundle; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.SeekBar; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.fragment.app.Fragment; + +import com.amap.api.location.AMapLocation; +import com.amap.api.location.AMapLocationClient; +import com.amap.api.location.AMapLocationListener; +import com.uiui.aios.R; +import com.uiui.aios.manager.AmapManager; +import com.uiui.aios.utils.BrightnessUtils; +import com.uiui.aios.view.RulerSeekBar; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * A simple {@link Fragment} subclass. + * Use the {@link ControlFragment#newInstance} factory method to + * create an instance of this fragment. + */ +public class ControlFragment extends Fragment { + private static final String TAG = ControlFragment.class.getSimpleName(); + + @BindView(R.id.iv_back) + ImageView iv_back; + + @BindView(R.id.tv_wifi) + TextView tv_wifi; + @BindView(R.id.tv_wifi_ssid) + TextView tv_wifi_ssid; + @BindView(R.id.tv_bt) + TextView tv_bt; + @BindView(R.id.tv_bt_ssid) + TextView tv_bt_ssid; + + // @BindView(R.id.tv_font_size) +// TextView tv_font_size; + @BindView(R.id.seekBar) + RulerSeekBar seekBar; + @BindView(R.id.seekbar_brightness) + SeekBar seekbar_brightness; + @BindView(R.id.seekbar_sound) + SeekBar seekbar_sound; + + @BindView(R.id.tv_sound) + TextView tv_sound; + + @BindView(R.id.tv_battery) + TextView tv_battery; + @BindView(R.id.tv_electricity) + TextView tv_electricity; + @BindView(R.id.tv_flashlight) + TextView tv_flashlight; + @BindView(R.id.tv_flashlight_switch) + TextView tv_flashlight_switch; + + @BindView(R.id.tv_brightness) + TextView tv_brightness; + @BindView(R.id.tv_location) + TextView tv_location; + + @BindView(R.id.cl_wifi) + ConstraintLayout cl_wifi; + @BindView(R.id.cl_bt) + ConstraintLayout cl_bt; + @BindView(R.id.cl_battery) + ConstraintLayout cl_battery; + @BindView(R.id.cl_flashlight) + ConstraintLayout cl_flashlight; + @BindView(R.id.cl_location) + ConstraintLayout cl_location; + + private View rootView; + private Context mContext; + private ContentResolver mCRv; + + + // TODO: Rename parameter arguments, choose names that match + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER + private static final String ARG_PARAM1 = "param1"; + private static final String ARG_PARAM2 = "param2"; + + // TODO: Rename and change types of parameters + private String mParam1; + private String mParam2; + + public ControlFragment() { + // Required empty public constructor + } + + /** + * Use this factory method to create a new instance of + * this fragment using the provided parameters. + * + * @param param1 Parameter 1. + * @param param2 Parameter 2. + * @return A new instance of fragment ControlFragment. + */ + // TODO: Rename and change types and number of parameters + public static ControlFragment newInstance(String param1, String param2) { + ControlFragment fragment = new ControlFragment(); + Bundle args = new Bundle(); + args.putString(ARG_PARAM1, param1); + args.putString(ARG_PARAM2, param2); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mParam1 = getArguments().getString(ARG_PARAM1); + mParam2 = getArguments().getString(ARG_PARAM2); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + rootView = inflater.inflate(R.layout.fragment_control, container, false); + mContext = rootView.getContext(); + mCRv = mContext.getContentResolver(); + ButterKnife.bind(this, rootView); + initView(); + initData(); + return rootView; + } + + private void initView() { + getWifi(); + registerReceivers(); + getBluetooth(); + registerBluetoothReceiver(); + getBattery(); + registerBatteryReceiver(); + getFlashlight(); + getFontSize(); + getLocation(); + getBrightness(); + getSound(); + } + + private void initData() { + + } + + private void getWifi() { + cl_wifi.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startActivity(new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS)); + } + }); + if (isWifiEnabled()) { + tv_wifi_ssid.setText(getConnectWifiSsid()); + cl_wifi.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + } else { + tv_wifi_ssid.setText("未连接"); + cl_wifi.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + } + } + + public boolean isWifiEnabled() { + WifiManager wifiMgr = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + if (wifiMgr.getWifiState() == WifiManager.WIFI_STATE_ENABLED) { + ConnectivityManager connManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo wifiInfo = connManager + .getNetworkInfo(ConnectivityManager.TYPE_WIFI); + return wifiInfo.isConnected(); + } else { + return false; + } + } + + private WifiReceiver mWifiReceiver; + + private void registerReceivers() { + registerWiFiReceiver(); + } + + private void registerWiFiReceiver() { + if (mWifiReceiver == null) { + mWifiReceiver = new WifiReceiver(); + } + IntentFilter filter = new IntentFilter(); + filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.RSSI_CHANGED_ACTION); + filter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); + filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + filter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); + filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); + filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + mContext.registerReceiver(mWifiReceiver, filter); + } + + public class WifiReceiver extends BroadcastReceiver { + private static final String TAG = "wifiReceiver"; + + @Override + public void onReceive(Context context, Intent intent) { + switch (intent.getAction()) { + case WifiManager.RSSI_CHANGED_ACTION: + Log.e(TAG, "wifi信号强度变化"); + break; + //wifi连接上与否 + case WifiManager.NETWORK_STATE_CHANGED_ACTION: + NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); + if (info.getState().equals(NetworkInfo.State.DISCONNECTED)) { + Log.e(TAG, "wifi断开"); + tv_wifi_ssid.setText("未连接"); + cl_wifi.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + } else if (info.getState().equals(NetworkInfo.State.CONNECTED)) { + WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + WifiInfo wifiInfo = wifiManager.getConnectionInfo(); + //获取当前wifi名称 + String newSSID = wifiInfo.getSSID(); + tv_wifi_ssid.setText(newSSID.replaceAll("\"", "")); + cl_wifi.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + } + break; + //wifi打开与否 + case WifiManager.WIFI_STATE_CHANGED_ACTION: + int wifistate = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED); + if (wifistate == WifiManager.WIFI_STATE_DISABLED) { + Log.e(TAG, "系统关闭wifi"); + tv_wifi_ssid.setText("关"); + cl_wifi.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + } else if (wifistate == WifiManager.WIFI_STATE_ENABLED) { + Log.e(TAG, "系统开启wifi"); + } + break; + default: + } + } + } + + /** + * 获取当前连接WIFI的SSID + */ + public String getSSID() { + WifiManager wm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + if (wm != null) { + WifiInfo winfo = wm.getConnectionInfo(); + if (winfo != null) { + String s = winfo.getSSID(); + if (s.length() > 2 && s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"') { + return s.substring(1, s.length() - 1); + } + } + } + return ""; + } + + private String getConnectWifiSsid() { + WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + WifiInfo wifiInfo = wifiManager.getConnectionInfo(); +// //去掉带引号的字符串方法一 +// String wifiInfo1 = wifiInfo.getSSID(); +// if (wifiInfo1.contains("\"")) { +// wifiInfo1 = wifiInfo1.substring(1, wifiInfo1.length() - 1); +// } +//去掉带引号的字符串方法二 + String wifiSSID = wifiInfo.getSSID(); + String wifiInfo1 = wifiSSID.replaceAll("\"", ""); + return wifiInfo1; + } + + private BluetoothAdapter bluetoothAdapter; + + private void getBluetooth() { + bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (bluetoothAdapter.isEnabled()) { + if (isConnected()) { + cl_bt.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + tv_bt_ssid.setText(getBluetoothDeviceName()); + } else { + cl_bt.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + tv_bt_ssid.setText("未连接"); + } + } else { + cl_bt.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + tv_bt_ssid.setText("已关闭"); + } + getConnectedDevicesV1(); + cl_bt.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS)); + } + }); + } + + public boolean isConnected() { + Set bondedDevices = bluetoothAdapter.getBondedDevices(); + List deviceList = bondedDevices.stream().filter(new Predicate() { + @Override + public boolean test(BluetoothDevice bluetoothDevice) { + return bluetoothDevice.isConnected(); + } + }).collect(Collectors.toList()); + return deviceList.size() > 0; + } + + public String getBluetoothDeviceName() { + Set bondedDevices = bluetoothAdapter.getBondedDevices(); + List deviceList = bondedDevices.stream().filter(new Predicate() { + @Override + public boolean test(BluetoothDevice bluetoothDevice) { + return bluetoothDevice.isConnected(); + } + }).collect(Collectors.toList()); + if (deviceList.size() == 0) { + return "未连接"; + } else { + return deviceList.get(0).getName(); + } + } + + //TODO 根据mac地址判断是否已连接(这里参数可以直接用BluetoothDevice对象) +//但这么写其实更通用。 + public boolean isConnected(String macAddress) { + if (!BluetoothAdapter.checkBluetoothAddress(macAddress)) { + return false; + } + final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + BluetoothDevice device = bluetoothAdapter.getRemoteDevice(macAddress); + + Method isConnectedMethod = null; + boolean isConnected; + try { + isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null); + isConnectedMethod.setAccessible(true); + isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null); + } catch (NoSuchMethodException e) { + isConnected = false; + } catch (IllegalAccessException e) { + isConnected = false; + } catch (InvocationTargetException e) { + isConnected = false; + } + return isConnected; + } + + /** + * 获取系统中已连接的蓝牙设备 + * + * @return + */ + public Set getConnectedDevicesV1() { + Class bluetoothAdapterClass = BluetoothAdapter.class;//得到BluetoothAdapter的Class对象 + Set deviceSet = new HashSet<>(); + //是否存在连接的蓝牙设备 + try { + Method method = bluetoothAdapterClass.getDeclaredMethod("getMostRecentlyConnectedDevices", (Class[]) null); + //打开权限 + method.setAccessible(true); + List list = (List) method.invoke(BluetoothAdapter.getDefaultAdapter(), (Object[]) null); + Log.e("zbh", "最近连接过的设备:"); + for (BluetoothDevice dev : list + ) { + String Type = ""; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + switch (dev.getType()) { + case BluetoothDevice.DEVICE_TYPE_CLASSIC: + Type = "经典"; + break; + case BluetoothDevice.DEVICE_TYPE_LE: + Type = "BLE"; + break; + case BluetoothDevice.DEVICE_TYPE_DUAL: + Type = "双模"; + break; + default: + Type = "未知"; + break; + } + } + String connect = "设备未连接"; + if (isConnected(dev.getAddress())) { + deviceSet.add(dev); + connect = "设备已连接"; + } + Log.e("zbh", connect + ", address = " + dev.getAddress() + "(" + Type + "), name --> " + dev.getName()); + + } + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + return deviceSet; + } + + private BluetoothMonitorReceiver bleListenerReceiver; + + private void registerBluetoothReceiver() { + bleListenerReceiver = new BluetoothMonitorReceiver(); + IntentFilter intentFilter = new IntentFilter(); + // 监视蓝牙关闭和打开的状态 + intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + // 监视蓝牙设备与APP连接的状态 + intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); + intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); + // 注册广播 + mContext.registerReceiver(this.bleListenerReceiver, intentFilter); + } + + public class BluetoothMonitorReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + Log.e("BluetoothMonitorReceiver", "onReceive: " + action); + if (!TextUtils.isEmpty(action)) { + switch (action) { + case BluetoothAdapter.ACTION_STATE_CHANGED: + int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0); + switch (blueState) { + case BluetoothAdapter.STATE_TURNING_ON: + tv_bt_ssid.setText("正在打开"); + cl_bt.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + break; + case BluetoothAdapter.STATE_ON: + tv_bt_ssid.setText("已打开"); + cl_bt.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + break; + case BluetoothAdapter.STATE_TURNING_OFF: + tv_bt_ssid.setText("正在关闭"); + cl_bt.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + break; + case BluetoothAdapter.STATE_OFF: + tv_bt_ssid.setText("已关闭"); + cl_bt.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + break; + default: + } + break; + case BluetoothDevice.ACTION_ACL_CONNECTED: + tv_bt_ssid.setText(getBluetoothDeviceName()); + cl_bt.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + break; + case BluetoothDevice.ACTION_ACL_DISCONNECTED: + tv_bt_ssid.setText("未连接"); + cl_bt.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + break; + default: + } + + } + } + } + + private void getBattery() { + tv_electricity.setText(getBatteryCapacity() + "%"); + if (isBatteryCharging()) { + cl_battery.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + } else { + cl_battery.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + } + } + + /** + * 主动获取当前电池是否在充电 , 即数据线是否插在手机上 + * + * @return + */ + public boolean isBatteryCharging() { + boolean isBatteryCharging = false; + // 主动发送包含是否正在充电状态的广播 , 该广播会持续发送 + IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + // 注册广播接受者 + Intent intent = mContext.registerReceiver(null, intentFilter); + // 获取充电状态 + int batteryChargeState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); + // 判定是否是 AC 交流电充电 + boolean isAc = batteryChargeState == BatteryManager.BATTERY_PLUGGED_AC; + // 判断是否是 USB 充电 + boolean isUsb = batteryChargeState == BatteryManager.BATTERY_PLUGGED_USB; + // 判断是否是 无线充电 + boolean isWireless = batteryChargeState == BatteryManager.BATTERY_PLUGGED_WIRELESS; + // 如何上述任意一种为 true , 说明当前正在充电 + isBatteryCharging = isAc || isUsb || isWireless; + return isBatteryCharging; + } + + + public int getBatteryCapacity() { + try { + BatteryManager batteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE); + return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + } catch (Exception e) { + Log.e("getBattery", "getBattery" + e.getMessage()); + } + return 0; + } + + private BatteryReceiver mBatteryReceiver; + + private void registerBatteryReceiver() { + if (mBatteryReceiver == null) { + mBatteryReceiver = new BatteryReceiver(); + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_POWER_CONNECTED); + filter.addAction(Intent.ACTION_POWER_DISCONNECTED); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED); + filter.addAction(Intent.ACTION_BATTERY_LOW); + filter.addAction(Intent.ACTION_BATTERY_OKAY); + mContext.registerReceiver(mBatteryReceiver, filter); + } + } + + public class BatteryReceiver extends BroadcastReceiver { + public static final String TAG = "BatteryReceiver"; + + @Override + public void onReceive(Context context, Intent intent) { + // 获取广播事件 + String action = intent.getAction(); + if (TextUtils.isEmpty(action)) return; + Log.e(TAG, "onReceive: " + action); + switch (action) { + case Intent.ACTION_POWER_CONNECTED: + cl_battery.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + break; + case Intent.ACTION_POWER_DISCONNECTED: + cl_battery.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + break; + case Intent.ACTION_BATTERY_LEVEL_CHANGED: + tv_electricity.setText(getBatteryCapacity() + "%"); + break; + default: + } + } + } + + private boolean flashing = false; + private CameraManager cameraManager; + + private void getFlashlight() { + if (isFlashlightAvailable()) { + tv_flashlight_switch.setText("关"); + cl_flashlight.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + } else { + tv_flashlight_switch.setText("不可用"); + cl_flashlight.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + return; + } +// if (isFlashlightEnabled()) { +// tv_flashlight_switch.setText("开"); +// cl_flashlight.setBackground(getDrawable(R.drawable.control_background_item)); +// } else { +// tv_flashlight_switch.setText("关"); +// cl_flashlight.setBackground(getDrawable(R.drawable.control_background_item_dis)); +// } + + cameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE); + + cl_flashlight.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (flashing) { + try { + String CameraId = cameraManager.getCameraIdList()[0]; + cameraManager.setTorchMode(CameraId, false); + } catch (CameraAccessException e) { + e.printStackTrace(); + } + flashing = false; + tv_flashlight_switch.setText("关"); + cl_flashlight.setBackground(mContext.getDrawable(R.drawable.control_background_item_dis)); + } else { + try { + String CameraId = cameraManager.getCameraIdList()[0]; + cameraManager.setTorchMode(CameraId, true); + } catch (CameraAccessException e) { + e.printStackTrace(); + } + tv_flashlight_switch.setText("开"); + cl_flashlight.setBackground(mContext.getDrawable(R.drawable.control_background_item)); + flashing = true; + } + } + }); + } + + + private boolean isFlashlightAvailable() { + return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH); + } + + private static String getCameraId(Context context) throws CameraAccessException { + final CameraManager cameraManager = context.getSystemService(CameraManager.class); + final String[] ids = cameraManager.getCameraIdList(); + for (String id : ids) { + CameraCharacteristics c = cameraManager.getCameraCharacteristics(id); + Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE); + Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING); + if (flashAvailable != null && flashAvailable + && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) { + return id; + } + } + return null; + } + + private boolean isFlashlightEnabled() { + return Settings.Secure.getInt(mCRv, Settings.Secure.FLASHLIGHT_ENABLED, 0) == 1; + } + + private void getFontSize() { + float fontScale = Settings.System.getFloat(mCRv, Settings.System.FONT_SCALE, 0.0f); + Log.e(TAG, "getFontSize: fontScale = " + fontScale); + List mEntries = Arrays.asList(getResources().getStringArray(R.array.entries_font_size)); + String[] strEntryValues = getResources().getStringArray(R.array.entryvalues_font_size); + float[] mValues = new float[strEntryValues.length]; + for (int i = 0; i < strEntryValues.length; ++i) { + mValues[i] = Float.parseFloat(strEntryValues[i]); + } + seekBar.setMax(mEntries.size() - 1); + String font_size; + int index = Arrays.binarySearch(mValues, fontScale); + Log.e(TAG, "getFontSize: index: " + index); + if (index == -1) { + font_size = "默认"; + } else { + font_size = mEntries.get(index); + } +// tv_font_size.setText(font_size); + seekBar.setProgress(index); + seekBar.postDelayed(new Runnable() { + @Override + public void run() { + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int i, boolean b) { + Log.e(TAG, "getFontSize: onProgressChanged: " + i); + Log.e(TAG, "getFontSize: FONT_SCALE = " + Float.parseFloat(strEntryValues[i])); + Settings.System.putFloat(mCRv, Settings.System.FONT_SCALE, Float.parseFloat(strEntryValues[i])); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + }); + } + },1999); + } + + private AMapLocationClient locationClient; + + private void getLocation() { + AMapLocation aMapLocation = AmapManager.getInstance().getNowAMapLocation(); + if (aMapLocation != null) { + if (aMapLocation.getErrorCode() == 0) {// 离线定位结果 + tv_location.setText(aMapLocation.getAddress()); + } else { + tv_location.setText("未知"); + } + } else { + tv_location.setText("定位失败"); + } + startLocation(); + cl_location.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startLocation(); + } + }); + } + + private void startLocation() { + if (locationClient == null) { + locationClient = AmapManager.getInstance().getLocationClient(); + } + locationClient.stopLocation(); + locationClient.startLocation(); + locationClient.setLocationListener(new AMapLocationListener() { + @Override + public void onLocationChanged(AMapLocation aMapLocation) { + if (aMapLocation.getErrorCode() == 0) { + tv_location.setText(aMapLocation.getAddress()); + } else { + tv_location.setText("定位失败"); + } + } + }); + } + + private void getBrightness() { + seekbar_brightness.setMax(255); + //亮度 + int brightness = Settings.System.getInt(mCRv, Settings.System.SCREEN_BRIGHTNESS, 1); + seekbar_brightness.setProgress(brightness); + Log.e(TAG, "getBrightness: brightness = " + brightness); + int gamma = BrightnessUtils.convertLinearToGamma(brightness, 1, 255); + Log.e(TAG, "getBrightness: gamma = " + gamma); + long percentage = Math.round((((double) gamma / 65535) * 100f)); + tv_brightness.setText(percentage + "%"); + Log.e(TAG, "getBrightness: percentage = " + percentage); + seekbar_brightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int i, boolean b) { + Log.e(TAG, "onProgressChanged: i = " + i); + Settings.System.putInt(mCRv, Settings.System.SCREEN_BRIGHTNESS, i); + int gamma = BrightnessUtils.convertLinearToGamma(i, 1, 255); + Log.e(TAG, "onProgressChanged: gamma = " + gamma); + long percentage = Math.round((((double) gamma / 65535) * 100f)); + Log.e(TAG, "onProgressChanged: percentage = " + percentage); + tv_brightness.setText(percentage + "%"); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + }); + } + + private AudioManager mAudioManager; + + private void getSound() { + mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + //最大音量 + int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + seekbar_sound.setMax(maxVolume); + Log.e(TAG, "getSound: maxVolume = " + maxVolume); + //音量 + int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + seekbar_sound.setProgress(streamVolume); + Log.e(TAG, "getSound: streamVolume = " + streamVolume); + int currentVolume = (int) (((double) streamVolume / (double) maxVolume) * 100f); + Log.e(TAG, "getSound: currentVolume = " + currentVolume); + tv_sound.setText(currentVolume + "%"); + seekbar_sound.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int i, boolean b) { + int volume = (int) (((double) i / (double) maxVolume) * 100f); + tv_sound.setText(volume + "%"); + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, i, 0); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + }); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mWifiReceiver != null) mContext.unregisterReceiver(mWifiReceiver); + } +} diff --git a/app/src/main/java/com/uiui/aios/utils/BrightnessUtils.java b/app/src/main/java/com/uiui/aios/utils/BrightnessUtils.java new file mode 100644 index 0000000..06a2533 --- /dev/null +++ b/app/src/main/java/com/uiui/aios/utils/BrightnessUtils.java @@ -0,0 +1,142 @@ + +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.uiui.aios.utils; + +import android.util.MathUtils; + +public class BrightnessUtils { + + public static final int GAMMA_SPACE_MIN = 0; + public static final int GAMMA_SPACE_MAX = 65535; + + // Hybrid Log Gamma constant values + private static final float R = 0.5f; + private static final float A = 0.17883277f; + private static final float B = 0.28466892f; + private static final float C = 0.55991073f; + + /** + * A function for converting from the gamma space that the slider works in to the + * linear space that the setting works in. + *

+ * The gamma space effectively provides us a way to make linear changes to the slider that + * result in linear changes in perception. If we made changes to the slider in the linear space + * then we'd see an approximately logarithmic change in perception (c.f. Fechner's Law). + *

+ * Internally, this implements the Hybrid Log Gamma electro-optical transfer function, which is + * a slight improvement to the typical gamma transfer function for displays whose max + * brightness exceeds the 120 nit reference point, but doesn't set a specific reference + * brightness like the PQ function does. + *

+ * Note that this transfer function is only valid if the display's backlight value is a linear + * control. If it's calibrated to be something non-linear, then a different transfer function + * should be used. + * + * @param val The slider value. + * @param min The minimum acceptable value for the setting. + * @param max The maximum acceptable value for the setting. + * @return The corresponding setting value. + */ + public static final int convertGammaToLinear(int val, int min, int max) { + final float normalizedVal = MathUtils.norm(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, val); + final float ret; + if (normalizedVal <= R) { + ret = MathUtils.sq(normalizedVal / R); + } else { + ret = MathUtils.exp((normalizedVal - C) / A) + B; + } + + // HLG is normalized to the range [0, 12], so we need to re-normalize to the range [0, 1] + // in order to derive the correct setting value. + return Math.round(MathUtils.lerp(min, max, ret / 12)); + } + + /** + * Version of {@link #convertGammaToLinear} that takes and returns float values. + * TODO(flc): refactor Android Auto to use float version + * + * @param val The slider value. + * @param min The minimum acceptable value for the setting. + * @param max The maximum acceptable value for the setting. + * @return The corresponding setting value. + */ + public static final float convertGammaToLinearFloat(int val, float min, float max) { + final float normalizedVal = MathUtils.norm(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, val); + final float ret; + if (normalizedVal <= R) { + ret = MathUtils.sq(normalizedVal / R); + } else { + ret = MathUtils.exp((normalizedVal - C) / A) + B; + } + + // HLG is normalized to the range [0, 12], ensure that value is within that range, + // it shouldn't be out of bounds. + final float normalizedRet = MathUtils.constrain(ret, 0, 12); + + // Re-normalize to the range [0, 1] + // in order to derive the correct setting value. + return MathUtils.lerp(min, max, normalizedRet / 12); + } + + /** + * A function for converting from the linear space that the setting works in to the + * gamma space that the slider works in. + *

+ * The gamma space effectively provides us a way to make linear changes to the slider that + * result in linear changes in perception. If we made changes to the slider in the linear space + * then we'd see an approximately logarithmic change in perception (c.f. Fechner's Law). + *

+ * Internally, this implements the Hybrid Log Gamma opto-electronic transfer function, which is + * a slight improvement to the typical gamma transfer function for displays whose max + * brightness exceeds the 120 nit reference point, but doesn't set a specific reference + * brightness like the PQ function does. + *

+ * Note that this transfer function is only valid if the display's backlight value is a linear + * control. If it's calibrated to be something non-linear, then a different transfer function + * should be used. + * + * @param val The brightness setting value. + * @param min The minimum acceptable value for the setting. + * @param max The maximum acceptable value for the setting. + * @return The corresponding slider value + */ + public static final int convertLinearToGamma(int val, int min, int max) { + return convertLinearToGammaFloat((float) val, (float) min, (float) max); + } + + /** + * Version of {@link #convertLinearToGamma} that takes float values. + * TODO: brightnessfloat merge with above method(?) + * + * @param val The brightness setting value. + * @param min The minimum acceptable value for the setting. + * @param max The maximum acceptable value for the setting. + * @return The corresponding slider value + */ + public static final int convertLinearToGammaFloat(float val, float min, float max) { + // For some reason, HLG normalizes to the range [0, 12] rather than [0, 1] + final float normalizedVal = MathUtils.norm(min, max, val) * 12; + final float ret; + if (normalizedVal <= 1f) { + ret = MathUtils.sqrt(normalizedVal) * R; + } else { + ret = A * MathUtils.log(normalizedVal - B) + C; + } + + return Math.round(MathUtils.lerp(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, ret)); + } +} diff --git a/app/src/main/java/com/uiui/aios/view/RulerSeekBar.java b/app/src/main/java/com/uiui/aios/view/RulerSeekBar.java new file mode 100644 index 0000000..2de3097 --- /dev/null +++ b/app/src/main/java/com/uiui/aios/view/RulerSeekBar.java @@ -0,0 +1,185 @@ +package com.uiui.aios.view; + + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; + +public class RulerSeekBar extends androidx.appcompat.widget.AppCompatSeekBar { + + /** + * 刻度线画笔 + */ + private Paint mRulerPaint; + + /** + * 刻度线的个数,等分数等于刻度线的个数加1 + */ + private int mRulerCount = 1; + + /** + * 每条刻度线的宽度 + */ + private int mRulerWidth = 2; + + /** + * 刻度线的颜色 + */ + private int mRulerColor = Color.GRAY; + + /** + * 滑块上面是否要显示刻度线 + */ + private boolean isShowTopOfThumb = true; + + private int radius = 12; + + public RulerSeekBar(Context context) { + super(context); + init(); + } + + public RulerSeekBar(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public RulerSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + /** + * 初始化 + */ + private void init() { + //创建绘制刻度线的画笔 + mRulerPaint = new Paint(); + mRulerPaint.setColor(Color.parseColor("#d0cccc")); + mRulerPaint.setAntiAlias(true); + + //Api21及以上调用,去掉滑块后面的背景 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setSplitTrack(false); + } + } + + /** + * 重写onDraw方法绘制刻度线 + * + * @param canvas + */ + @Override + protected synchronized void onDraw(Canvas canvas) { + super.onDraw(canvas); + + //极限条件校验 + if (getWidth() <= 0 || mRulerCount <= 0) { + return; + } + + + int thumbRadius = 0; + if (getThumb() != null) { + Rect rect = getThumb().getBounds(); + thumbRadius = (rect.right - rect.left) / 2; + } + Log.e("RulerSeekBar", "onDraw: thumbRadius = " + thumbRadius); + + + //获取每一份的长度 + int length = (getWidth() - getPaddingLeft() - getPaddingRight() - (mRulerCount + 1) * (radius) - thumbRadius * 2) / (mRulerCount + 1); + Log.e("RulerSeekBar", "onDraw: mRulerCount = " + mRulerCount); + + Log.e("RulerSeekBar", "onDraw: getWidth = " + getWidth()); + Log.e("RulerSeekBar", "onDraw: getPaddingLeft = " + getPaddingLeft()); + Log.e("RulerSeekBar", "onDraw: getPaddingRight = " + getPaddingRight()); + Log.e("RulerSeekBar", "onDraw: length = " + length); + + //计算刻度线的顶部坐标和底部坐标 + Log.e("RulerSeekBar", "onDraw: getHeight = " + getHeight()); + Log.e("RulerSeekBar", "onDraw: getMinimumHeight = " + getMinimumHeight()); + + int rulerTop = getHeight() / 2 - getMinimumHeight() / 2; + int rulerBottom = rulerTop + getMinimumHeight(); + Log.e("RulerSeekBar", "onDraw: rulerTop = " + rulerTop); + Log.e("RulerSeekBar", "onDraw: rulerBottom = " + rulerBottom); + int center = getHeight() / 2; + + //获取滑块的位置信息 + Rect thumbRect = null; + if (getThumb() != null) { + thumbRect = getThumb().getBounds(); + } + Log.e("RulerSeekBar", "onDraw: thumbRect = " + thumbRect); + + //绘制刻度线 + for (int i = 0; i <= mRulerCount + 1; i++) { + //计算刻度线的左边坐标和右边坐标 + int rulerLeft = i * length + getPaddingLeft(); + Log.e("RulerSeekBar", "onDraw: rulerLeft = " + rulerLeft); + int rulerRight = rulerLeft + mRulerWidth; + + //判断是否需要绘制刻度线 + if (!isShowTopOfThumb && thumbRect != null && rulerLeft - getPaddingLeft() > thumbRect.left && rulerRight - getPaddingLeft() < thumbRect.right) { + continue; + } + + if (rulerLeft > thumbRect.left && rulerLeft < thumbRect.right) { + continue; + } + + //进行绘制 +// canvas.drawRect(rulerLeft, rulerTop, rulerRight, rulerBottom, mRulerPaint); + canvas.drawCircle(rulerLeft + radius + thumbRadius, center, radius, mRulerPaint); + } + } + + /** + * 设置刻度线的个数 + * + * @param mRulerCount + */ + public void setRulerCount(int mRulerCount) { + this.mRulerCount = mRulerCount; + requestLayout(); + } + + /** + * 设置刻度线的宽度,单位(px) + * + * @param mRulerWidth + */ + public void setRulerWidth(int mRulerWidth) { + this.mRulerWidth = mRulerWidth; + requestLayout(); + } + + /** + * 设置刻度线的颜色 + * + * @param mRulerColor + */ + public void setRulerColor(int mRulerColor) { + this.mRulerColor = mRulerColor; + if (mRulerPaint != null) { + mRulerPaint.setColor(mRulerColor); + requestLayout(); + } + } + + /** + * 滑块上面是否需要显示刻度线 + * + * @param isShowTopOfThumb + */ + public void setShowTopOfThumb(boolean isShowTopOfThumb) { + this.isShowTopOfThumb = isShowTopOfThumb; + requestLayout(); + } +} diff --git a/app/src/main/res/drawable-hdpi/back.png b/app/src/main/res/drawable-hdpi/back.png new file mode 100644 index 0000000..e57a14b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/back.png differ diff --git a/app/src/main/res/drawable-hdpi/battery1.png b/app/src/main/res/drawable-hdpi/battery1.png new file mode 100644 index 0000000..8959a34 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/battery1.png differ diff --git a/app/src/main/res/drawable-hdpi/bluetooth1.png b/app/src/main/res/drawable-hdpi/bluetooth1.png new file mode 100644 index 0000000..8212fdd Binary files /dev/null and b/app/src/main/res/drawable-hdpi/bluetooth1.png differ diff --git a/app/src/main/res/drawable-hdpi/brightness1.png b/app/src/main/res/drawable-hdpi/brightness1.png new file mode 100644 index 0000000..6997b5f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/brightness1.png differ diff --git a/app/src/main/res/drawable-hdpi/control_background.png b/app/src/main/res/drawable-hdpi/control_background.png new file mode 100644 index 0000000..0fce687 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/control_background.png differ diff --git a/app/src/main/res/drawable-hdpi/flashlight1.png b/app/src/main/res/drawable-hdpi/flashlight1.png new file mode 100644 index 0000000..c419b65 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/flashlight1.png differ diff --git a/app/src/main/res/drawable-hdpi/position.png b/app/src/main/res/drawable-hdpi/position.png new file mode 100644 index 0000000..7a9e54e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/position.png differ diff --git a/app/src/main/res/drawable-hdpi/sound1.png b/app/src/main/res/drawable-hdpi/sound1.png new file mode 100644 index 0000000..0d95b28 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/sound1.png differ diff --git a/app/src/main/res/drawable-hdpi/wifi1.png b/app/src/main/res/drawable-hdpi/wifi1.png new file mode 100644 index 0000000..8fefacb Binary files /dev/null and b/app/src/main/res/drawable-hdpi/wifi1.png differ diff --git a/app/src/main/res/drawable/control_background_item.xml b/app/src/main/res/drawable/control_background_item.xml new file mode 100644 index 0000000..03dd6b2 --- /dev/null +++ b/app/src/main/res/drawable/control_background_item.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/control_background_item_dis.xml b/app/src/main/res/drawable/control_background_item_dis.xml new file mode 100644 index 0000000..1582ff2 --- /dev/null +++ b/app/src/main/res/drawable/control_background_item_dis.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/seekbar_progress_default.xml b/app/src/main/res/drawable/seekbar_progress_default.xml new file mode 100644 index 0000000..a7f0e64 --- /dev/null +++ b/app/src/main/res/drawable/seekbar_progress_default.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_progress_drawable.xml b/app/src/main/res/drawable/shape_progress_drawable.xml new file mode 100644 index 0000000..12f6c7e --- /dev/null +++ b/app/src/main/res/drawable/shape_progress_drawable.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_thumb_icon.xml b/app/src/main/res/drawable/shape_thumb_icon.xml new file mode 100644 index 0000000..3d62cd5 --- /dev/null +++ b/app/src/main/res/drawable/shape_thumb_icon.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/fragment_control.xml b/app/src/main/res/layout-land/fragment_control.xml new file mode 100644 index 0000000..f360f31 --- /dev/null +++ b/app/src/main/res/layout-land/fragment_control.xml @@ -0,0 +1,496 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-port/fragment_control.xml b/app/src/main/res/layout-port/fragment_control.xml new file mode 100644 index 0000000..ffc52c4 --- /dev/null +++ b/app/src/main/res/layout-port/fragment_control.xml @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 1a49501..7db21ff 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -16,4 +16,16 @@ + + + 1.0 + 1.15 + 1.30 + + + + "默认" + "大" + "最大" + \ No newline at end of file