diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cc63663..42b6eb2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ @@ -67,16 +66,14 @@ android:supportsRtl="true" android:theme="@style/AppTheme"> @@ -88,6 +85,17 @@ + + + @@ -119,7 +127,7 @@ + android:screenOrientation="userPortrait" /> + android:screenOrientation="userLandscape" + android:theme="@style/activity_styles" /> @@ -171,11 +179,12 @@ android:screenOrientation="userLandscape" /> - + android:launchMode="singleTask" + android:screenOrientation="userPortrait" /> + mFragments; + private ControlFragment mControlFragment; + private HomeFragment mHomeFragment; + // private CustomFragment mCustomFragment; + private SecondFragment mSecondFragment; + + private boolean is_twoscreen = false; + private int appListIndex = 3; + private int defaultCurrent = 2; + + @Override + public void initView() { + ButterKnife.bind(this); + toggleNotificationListenerService(this); + mMainPresenter = new MainPresenter(this); + mMainPresenter.attachView(this); + mMainPresenter.setLifecycle(lifecycleSubject); + + if (BuildConfig.DEBUG) { +// SystemClock.setCurrentTimeMillis(1662123600000L);//09-02 +// SystemClock.setCurrentTimeMillis(1662210000000L);//09-03 + } + + mFragmentManager = getSupportFragmentManager(); + mFragmentTransaction = mFragmentManager.beginTransaction(); + mFragments = new ArrayList<>(); + 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", 1) == 1; +// if (is_twoscreen) { +// appListIndex = 2; +// defaultCurrent = 1; + mSecondFragment = new SecondFragment(); + mFragments.add(mSecondFragment); +// } +// mCustomFragment = new CustomFragment(); +// mFragments.add(mCustomFragment); + + mHomeFragment = new HomeFragment(); + mFragments.add(mHomeFragment); + + mMainPresenter.getSystemSettings(); +// mMainPresenter.getAdminSnSetting(); + ArrayList desktopIcons = ApkUtils.queryFilterAppInfo(this); + int x = 0; + for (int i = 0; i <= desktopIcons.size(); i++) { + if (i != 0 && i % APP_LIST_SIZE == 0) { + AppListFragment appListFragment = new AppListFragment(); + appListFragment.setAppList(new ArrayList<>(desktopIcons.subList(x, i))); + mFragments.add(appListFragment); + x = i; + } else if (i == desktopIcons.size()) { + AppListFragment appListFragment = new AppListFragment(); + mFragments.add(appListFragment); + appListFragment.setAppList(new ArrayList<>(desktopIcons.subList(x, i))); + } + } + + scaleCircleNavigator = new ScaleCircleNavigator(this); + scaleCircleNavigator.setCircleCount(mFragments.size()); + scaleCircleNavigator.setNormalCircleColor(Color.DKGRAY); + scaleCircleNavigator.setSelectedCircleColor(Color.LTGRAY); + scaleCircleNavigator.setCircleClickListener(new ScaleCircleNavigator.OnCircleClickListener() { + @Override + public void onClick(int index) { + + } + }); + + mViewPager.setAdapter(mBaseFragmentPagerAdapter); + mViewPager.setOffscreenPageLimit(3); + mMagicIndicator.setNavigator(scaleCircleNavigator); + ViewPagerHelper.bind(mMagicIndicator, mViewPager); + if (mFragments.size() > 1) { + mViewPager.setCurrentItem(defaultCurrent); + } + + View decorView = getWindow().getDecorView(); + decorView.setOnSystemUiVisibilityChangeListener(mOnSystemUiVisibilityChangeListener); + + // 隐藏导航栏 + hideNavigationBar(); + } + + private View.OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener = + new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { + // 导航栏显示中,重新隐藏导航栏 + hideNavigationBar(); + } + } + }; + + // 隐藏导航栏 + private void hideNavigationBar() { + View decorView = getWindow().getDecorView(); + int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + decorView.setSystemUiVisibility(uiOptions); + } + + + @Override + public void initData() { + registmNewAppReceiver(); + registerSOSNumberReceiver(); + registerUpdateDesktopReceiver(); + mAlarmServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + Log.e(TAG, "onServiceConnected: "); + mIAlarmAidlInterface = IAlarmAidlInterface.Stub.asInterface(service); + getAlarmData(); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + Log.e(TAG, "onServiceDisconnected: "); + mIAlarmAidlInterface = null; + } + }; + bindAlarmService(); + RemoteManager.getInstance().setListener(new RemoteManager.ConnectedListener() { + @Override + public void onConnected() { + setDefaultDesktop(); + } + }); + } + + private ServiceConnection mAlarmServiceConnection; + private IAlarmAidlInterface mIAlarmAidlInterface; + + private void bindAlarmService() { + if (mIAlarmAidlInterface == null) { + //这是连接aidl服务的代码 + Intent intent = new Intent(); + intent.setAction("com.alarmclock.uiui.IAlarmAidlInterface"); + intent.setPackage("com.alarmclock.uiui"); + intent.setComponent(new ComponentName("com.alarmclock.uiui", "com.alarmclock.uiui.AIDLAlarmService")); + bindService(intent, mAlarmServiceConnection, Context.BIND_AUTO_CREATE); + } else { + + } + } + + public static void toggleNotificationListenerService(Context context) { + Log.e(TAG, "toggleNotificationListenerService"); + PackageManager pm = context.getPackageManager(); + pm.setComponentEnabledSetting(new ComponentName(context, NotificationService.class), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + + pm.setComponentEnabledSetting(new ComponentName(context, NotificationService.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + } + + private void getAlarmData() { + if (mIAlarmAidlInterface == null) { + bindAlarmService(); + return; + } + try { + String json = mIAlarmAidlInterface.getAlarm(); + Log.e(TAG, "onServiceConnected: " + json); + if ("暂无闹钟".equalsIgnoreCase(json) || TextUtils.isEmpty(json)) { +// mCustomFragment.setAlarmItem(null); + return; + } + Type type = new TypeToken>() { + }.getType(); + List alarmItem = new Gson().fromJson(json, type); +// mCustomFragment.setAlarmItem(alarmItem); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + private final static int APP_LIST_SIZE = 3 * 4; + + private void addData() { + Log.e(TAG, "addData: "); + List fragmentList = new ArrayList<>(); + ArrayList applicationInfoList = ApkUtils.queryFilterAppInfo(this); + int x = 0; + for (int i = 0; i <= applicationInfoList.size(); i++) { + if (i != 0 && i % APP_LIST_SIZE == 0) { + AppListFragment appListFragment = new AppListFragment(); + appListFragment.setAppList(new ArrayList<>(applicationInfoList.subList(x, i))); + fragmentList.add(appListFragment); + x = i; + } else if (i == applicationInfoList.size()) { + AppListFragment appListFragment = new AppListFragment(); + fragmentList.add(appListFragment); + appListFragment.setAppList(new ArrayList<>(applicationInfoList.subList(x, i))); + } + } + //从第三个开始改 + for (int i = 0; i < fragmentList.size(); i++) { + if (i + appListIndex < mFragments.size()) { + mBaseFragmentPagerAdapter.replaceFragment(i + appListIndex, fragmentList.get(i)); +// mFragments.remove(i + 2); +// mFragments.add(i + 2, fragmentList.get(i)); + } else { +// mFragments.add(fragmentList.get(i)); +// mBaseFragmentPagerAdapter.getFragments(); + mBaseFragmentPagerAdapter.addFragment(fragmentList.get(i)); + } + } + for (int i = mFragments.size(); i > fragmentList.size() + appListIndex; i--) { + mFragments.remove(i - 1); + } + scaleCircleNavigator.setCircleCount(mFragments.size()); + scaleCircleNavigator.notifyDataSetChanged(); + mBaseFragmentPagerAdapter.notifyItemChanged(); + } + + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { + return false; + } + return super.onKeyDown(keyCode, event); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + Log.e(TAG, "onNewIntent: " + intent.getAction()); + String action = intent.getAction(); + if (TextUtils.isEmpty(action)) { + return; + } + switch (action) { + default: + break; + case Intent.ACTION_MAIN: + mViewPager.setCurrentItem(defaultCurrent); + break; + } + } + + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + super.onConfigurationChanged(newConfig); + } + + @Override + protected void onStart() { + super.onStart(); + AppUsedTimeUtils.getInstance().setAppPackageName(BuildConfig.APPLICATION_ID); + AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis()); + getAlarmData(); + } + + @Override + protected void onResume() { + super.onResume(); + Log.e(TAG, "onResume: "); + if (!isNotificationListenersEnabled()) { + ToastUtil.show("请授予\"" + getString(R.string.app_name) + "\"使用通知权"); + gotoNotificationAccessSetting(this); + } else { + getPermission(); + } + } + + public static final String Launcher3 = "com.android.launcher3"; + public static final String Launcher3Class = "com.android.launcher3.Launcher"; + public static final String Launcher3QuickstepClass = "com.android.launcher3.uioverrides.QuickstepLauncher"; + + private void setDefaultDesktop() { + int is_activation = Settings.Global.getInt(getContentResolver(), CommonConfig.UIUI_ACTIVATION_KEY, 0); + Log.e(TAG, "onResume: is_activation = " + is_activation); + if (is_activation == 1) { + RemoteManager.getInstance().setDefaultDesktop(BuildConfig.APPLICATION_ID, this.getClass().getName()); + } else { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { + RemoteManager.getInstance().setDefaultDesktop(Launcher3, Launcher3QuickstepClass); + } else { + RemoteManager.getInstance().setDefaultDesktop(Launcher3, Launcher3Class); + } + } + } + + + private String[] permission = new String[]{ + Permission.CALL_PHONE, +// Permission.REQUEST_INSTALL_PACKAGES, + Permission.WRITE_EXTERNAL_STORAGE, + Permission.READ_PHONE_STATE, + Permission.WRITE_SETTINGS, + Permission.READ_CALL_LOG, + Permission.WRITE_CALL_LOG, + }; + + private void getPermission() { + XXPermissions.with(this) + // 申请单个权限 +// .permission(Permission.RECORD_AUDIO) + // 申请多个权限 + .permission(permission) + // 设置权限请求拦截器(局部设置) + //.interceptor(new PermissionInterceptor()) + // 设置不触发错误检测机制(局部设置) + //.unchecked() + .request(new OnPermissionCallback() { + + @Override + public void onGranted(@NonNull List permissions, boolean allGranted) { + if (!allGranted) { + ToastUtil.show("获取部分权限成功,但部分权限未正常授予"); + return; + } +// ToastUtil.show("获取录音和日历权限成功"); + Log.e(TAG, "onGranted: 获取存储权限成功"); + addData(); + } + + @Override + public void onDenied(@NonNull List permissions, boolean doNotAskAgain) { + if (doNotAskAgain) { + ToastUtil.show("被永久拒绝授权,请手动授予存储权限"); + // 如果是被永久拒绝就跳转到应用权限系统设置页面 + XXPermissions.startPermissionActivity(BaseMainActivity.this, permissions); + } else { +// ToastUtil.show("获取录音和日历权限失败"); + Log.e(TAG, "onGranted: 获取存储权限权限失败"); + } + } + }); + } + + + private static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners"; + + private boolean isNotificationListenersEnabled() { + String pkgName = getPackageName(); + final String flat = Settings.Secure.getString(getContentResolver(), ENABLED_NOTIFICATION_LISTENERS); + if (!TextUtils.isEmpty(flat)) { + final String[] names = flat.split(":"); + for (int i = 0; i < names.length; i++) { + final ComponentName cn = ComponentName.unflattenFromString(names[i]); + if (cn != null) { + if (TextUtils.equals(pkgName, cn.getPackageName())) { + return true; + } + } + } + } + return false; + } + + public static boolean gotoNotificationAccessSetting(Context context) { + try { + Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + return true; + + } catch (ActivityNotFoundException e) {//普通情况下找不到的时候需要再特殊处理找一次 + try { + Intent intent = new Intent(); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.Settings$NotificationAccessSettingsActivity"); + intent.setComponent(cn); + intent.putExtra(":settings:show_fragment", "NotificationAccessSettings"); + context.startActivity(intent); + return true; + } catch (Exception e1) { + e1.printStackTrace(); + } + ToastUtil.show("对不起,您的手机暂不支持"); + e.printStackTrace(); + return false; + } + } + + + @Override + protected void onRestart() { + super.onRestart(); + mMainPresenter.sendAPPUsage(); + mMainPresenter.sendRunningInfo(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onStop() { + super.onStop(); + AppUsedTimeUtils.getInstance().setEndTime(System.currentTimeMillis()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mMainPresenter.detachView(); + if (mNewAppReceiver != null) { + unregisterReceiver(mNewAppReceiver); + } + if (updateDesktopReceiver != null) { + unregisterReceiver(updateDesktopReceiver); + } + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { +// super.onSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { +// super.onRestoreInstanceState(savedInstanceState); + } + + private void registmNewAppReceiver() { + mNewAppReceiver = new NewAppReceiver(); + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addAction(Intent.ACTION_PACKAGE_REPLACED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addDataScheme("package"); + registerReceiver(mNewAppReceiver, filter); + } + + private NewAppReceiver mNewAppReceiver; + + class NewAppReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + Log.e(TAG, "onReceive: " + action); + if (Intent.ACTION_PACKAGE_ADDED.equals(action) + || Intent.ACTION_PACKAGE_REMOVED.equals(action) + || Intent.ACTION_PACKAGE_CHANGED.equals(action)) { + addData(); + } + } + } + + private SOSNumberReceiver sosNumberReceiver; + + private void registerSOSNumberReceiver() { + if (sosNumberReceiver == null) { + sosNumberReceiver = new SOSNumberReceiver(); + } + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction("setting_sos"); + registerReceiver(sosNumberReceiver, filter); + } + + class SOSNumberReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + Log.e(TAG, "onReceive: " + intent.getAction()); + String setting_sos = intent.getStringExtra("setting_sos"); + if (TextUtils.isEmpty(setting_sos)) return; +// mCustomFragment.setSosNumber(); + } + } + + public static final String ACTION_PACKAGE_HIDE = "com.uiui.aios.ACTION_PACKAGE_HIDE"; + + private UpdateDesktopReceiver updateDesktopReceiver; + + private void registerUpdateDesktopReceiver() { + if (updateDesktopReceiver == null) { + updateDesktopReceiver = new UpdateDesktopReceiver(); + } + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction("UPDATE_DESKTOP_ICON"); + filter.addAction(ACTION_PACKAGE_HIDE); + registerReceiver(updateDesktopReceiver, filter); + } + + class UpdateDesktopReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + Log.e(TAG, "onReceive: " + intent.getAction()); + addData(); + } + } + + @Override + public void setSystemSettings() { +// mMainPresenter.getDesktopLayout(); + } + + @Override + public void getDesktopLayoutFinish() { + + } + + @Override + public void updateDesktopLayoutFinish() { + + } + + @Override + public void sendAPPUsageFinish() { + + } + + @Override + public void sendRunningInfoFinish() { + + } + + @Override + public void setAdminSnSetting() { + + } +} + diff --git a/app/src/main/java/com/uiuios/aios/activity/main/MainActivity.java b/app/src/main/java/com/uiuios/aios/activity/main/MainActivity.java index 00fc6ae..561379d 100644 --- a/app/src/main/java/com/uiuios/aios/activity/main/MainActivity.java +++ b/app/src/main/java/com/uiuios/aios/activity/main/MainActivity.java @@ -1,612 +1,12 @@ package com.uiuios.aios.activity.main; -import android.content.ActivityNotFoundException; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.ServiceConnection; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.graphics.Color; -import android.os.Build; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; -import androidx.viewpager.widget.ViewPager; - -import com.alarmclock.uiui.IAlarmAidlInterface; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.hjq.permissions.OnPermissionCallback; -import com.hjq.permissions.Permission; -import com.hjq.permissions.XXPermissions; -import com.uiuios.aios.BuildConfig; import com.uiuios.aios.R; -import com.uiuios.aios.base.BaseActivity; -import com.uiuios.aios.bean.AlarmItem; -import com.uiuios.aios.bean.DesktopIcon; -import com.uiuios.aios.config.CommonConfig; -import com.uiuios.aios.fragment.AppListFragment; -import com.uiuios.aios.base.BaseFragmentPagerAdapter; -import com.uiuios.aios.fragment.ControlFragment; -import com.uiuios.aios.fragment.custom.CustomFragment; -import com.uiuios.aios.fragment.home.HomeFragment; -import com.uiuios.aios.fragment.second.SecondFragment; -import com.uiuios.aios.manager.RemoteManager; -import com.uiuios.aios.service.NotificationService; -import com.uiuios.aios.utils.ApkUtils; -import com.uiuios.aios.utils.AppUsedTimeUtils; -import com.uiuios.aios.utils.HomeWatcher; -import com.uiuios.aios.utils.ToastUtil; -import com.uiuios.aios.view.ScaleCircleNavigator; -import net.lucode.hackware.magicindicator.MagicIndicator; -import net.lucode.hackware.magicindicator.ViewPagerHelper; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; - -import butterknife.BindView; -import butterknife.ButterKnife; - -public class MainActivity extends BaseActivity implements MainContact.MainView { +public class MainActivity extends BaseMainActivity { private static final String TAG = MainActivity.class.getSimpleName(); - private MainPresenter mMainPresenter; - - @BindView(R.id.viewPager) - ViewPager mViewPager; - @BindView(R.id.magicIndicator) - MagicIndicator mMagicIndicator; - - private FragmentManager mFragmentManager; - private FragmentTransaction mFragmentTransaction; - - private ScaleCircleNavigator scaleCircleNavigator; - private BaseFragmentPagerAdapter mBaseFragmentPagerAdapter; - - private List mFragments; - private ControlFragment mControlFragment; - private HomeFragment mHomeFragment; -// private CustomFragment mCustomFragment; - private SecondFragment mSecondFragment; - - private boolean is_twoscreen = false; - private int appListIndex = 3; - private int defaultCurrent = 2; @Override public int getLayoutId() { return R.layout.activity_main; } - - @Override - public void initView() { - ButterKnife.bind(this); - toggleNotificationListenerService(this); - mMainPresenter = new MainPresenter(this); - mMainPresenter.attachView(this); - mMainPresenter.setLifecycle(lifecycleSubject); - - if (BuildConfig.DEBUG) { -// SystemClock.setCurrentTimeMillis(1662123600000L);//09-02 -// SystemClock.setCurrentTimeMillis(1662210000000L);//09-03 - } - - mFragmentManager = getSupportFragmentManager(); - mFragmentTransaction = mFragmentManager.beginTransaction(); - mFragments = new ArrayList<>(); - 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", 1) == 1; -// if (is_twoscreen) { -// appListIndex = 2; -// defaultCurrent = 1; - mSecondFragment = new SecondFragment(); - mFragments.add(mSecondFragment); -// } -// mCustomFragment = new CustomFragment(); -// mFragments.add(mCustomFragment); - - mHomeFragment =new HomeFragment(); - mFragments.add(mHomeFragment); - - mMainPresenter.getSystemSettings(); -// mMainPresenter.getAdminSnSetting(); - ArrayList desktopIcons = ApkUtils.queryFilterAppInfo(this); - int x = 0; - for (int i = 0; i <= desktopIcons.size(); i++) { - if (i != 0 && i % APP_LIST_SIZE == 0) { - AppListFragment appListFragment = new AppListFragment(); - appListFragment.setAppList(new ArrayList<>(desktopIcons.subList(x, i))); - mFragments.add(appListFragment); - x = i; - } else if (i == desktopIcons.size()) { - AppListFragment appListFragment = new AppListFragment(); - mFragments.add(appListFragment); - appListFragment.setAppList(new ArrayList<>(desktopIcons.subList(x, i))); - } - } - - scaleCircleNavigator = new ScaleCircleNavigator(this); - scaleCircleNavigator.setCircleCount(mFragments.size()); - scaleCircleNavigator.setNormalCircleColor(Color.DKGRAY); - scaleCircleNavigator.setSelectedCircleColor(Color.LTGRAY); - scaleCircleNavigator.setCircleClickListener(new ScaleCircleNavigator.OnCircleClickListener() { - @Override - public void onClick(int index) { - - } - }); - - mViewPager.setAdapter(mBaseFragmentPagerAdapter); - mViewPager.setOffscreenPageLimit(3); - mMagicIndicator.setNavigator(scaleCircleNavigator); - ViewPagerHelper.bind(mMagicIndicator, mViewPager); - if (mFragments.size() > 1) { - mViewPager.setCurrentItem(defaultCurrent); - } - - View decorView = getWindow().getDecorView(); - decorView.setOnSystemUiVisibilityChangeListener(mOnSystemUiVisibilityChangeListener); - - // 隐藏导航栏 - hideNavigationBar(); - } - - private View.OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener = - new View.OnSystemUiVisibilityChangeListener() { - @Override - public void onSystemUiVisibilityChange(int visibility) { - if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { - // 导航栏显示中,重新隐藏导航栏 - hideNavigationBar(); - } - } - }; - - // 隐藏导航栏 - private void hideNavigationBar() { - View decorView = getWindow().getDecorView(); - int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; - decorView.setSystemUiVisibility(uiOptions); - } - - - @Override - public void initData() { - registmNewAppReceiver(); - registerSOSNumberReceiver(); - registerUpdateDesktopReceiver(); - mAlarmServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - Log.e(TAG, "onServiceConnected: "); - mIAlarmAidlInterface = IAlarmAidlInterface.Stub.asInterface(service); - getAlarmData(); - } - - @Override - public void onServiceDisconnected(ComponentName name) { - Log.e(TAG, "onServiceDisconnected: "); - mIAlarmAidlInterface = null; - } - }; - bindAlarmService(); - RemoteManager.getInstance().setListener(new RemoteManager.ConnectedListener() { - @Override - public void onConnected() { - setDefaultDesktop(); - } - }); - } - - private ServiceConnection mAlarmServiceConnection; - private IAlarmAidlInterface mIAlarmAidlInterface; - - private void bindAlarmService() { - if (mIAlarmAidlInterface == null) { - //这是连接aidl服务的代码 - Intent intent = new Intent(); - intent.setAction("com.alarmclock.uiui.IAlarmAidlInterface"); - intent.setPackage("com.alarmclock.uiui"); - intent.setComponent(new ComponentName("com.alarmclock.uiui", "com.alarmclock.uiui.AIDLAlarmService")); - bindService(intent, mAlarmServiceConnection, Context.BIND_AUTO_CREATE); - } else { - - } - } - - public static void toggleNotificationListenerService(Context context) { - Log.e(TAG, "toggleNotificationListenerService"); - PackageManager pm = context.getPackageManager(); - pm.setComponentEnabledSetting(new ComponentName(context, NotificationService.class), - PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); - - pm.setComponentEnabledSetting(new ComponentName(context, NotificationService.class), - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); - } - - private void getAlarmData() { - if (mIAlarmAidlInterface == null) { - bindAlarmService(); - return; - } - try { - String json = mIAlarmAidlInterface.getAlarm(); - Log.e(TAG, "onServiceConnected: " + json); - if ("暂无闹钟".equalsIgnoreCase(json) || TextUtils.isEmpty(json)) { -// mCustomFragment.setAlarmItem(null); - return; - } - Type type = new TypeToken>() { - }.getType(); - List alarmItem = new Gson().fromJson(json, type); -// mCustomFragment.setAlarmItem(alarmItem); - } catch (RemoteException e) { - e.printStackTrace(); - } - } - - private final static int APP_LIST_SIZE = 3 * 4; - - private void addData() { - Log.e(TAG, "addData: "); - List fragmentList = new ArrayList<>(); - ArrayList applicationInfoList = ApkUtils.queryFilterAppInfo(this); - int x = 0; - for (int i = 0; i <= applicationInfoList.size(); i++) { - if (i != 0 && i % APP_LIST_SIZE == 0) { - AppListFragment appListFragment = new AppListFragment(); - appListFragment.setAppList(new ArrayList<>(applicationInfoList.subList(x, i))); - fragmentList.add(appListFragment); - x = i; - } else if (i == applicationInfoList.size()) { - AppListFragment appListFragment = new AppListFragment(); - fragmentList.add(appListFragment); - appListFragment.setAppList(new ArrayList<>(applicationInfoList.subList(x, i))); - } - } - //从第三个开始改 - for (int i = 0; i < fragmentList.size(); i++) { - if (i + appListIndex < mFragments.size()) { - mBaseFragmentPagerAdapter.replaceFragment(i + appListIndex, fragmentList.get(i)); -// mFragments.remove(i + 2); -// mFragments.add(i + 2, fragmentList.get(i)); - } else { -// mFragments.add(fragmentList.get(i)); -// mBaseFragmentPagerAdapter.getFragments(); - mBaseFragmentPagerAdapter.addFragment(fragmentList.get(i)); - } - } - for (int i = mFragments.size(); i > fragmentList.size() + appListIndex; i--) { - mFragments.remove(i - 1); - } - scaleCircleNavigator.setCircleCount(mFragments.size()); - scaleCircleNavigator.notifyDataSetChanged(); - mBaseFragmentPagerAdapter.notifyItemChanged(); - } - - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { - return false; - } - return super.onKeyDown(keyCode, event); - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - Log.e(TAG, "onNewIntent: " + intent.getAction()); - String action = intent.getAction(); - if (TextUtils.isEmpty(action)) { - return; - } - switch (action) { - default: - break; - case Intent.ACTION_MAIN: - mViewPager.setCurrentItem(defaultCurrent); - break; - } - } - - @Override - public void onConfigurationChanged(@NonNull Configuration newConfig) { - super.onConfigurationChanged(newConfig); - } - - @Override - protected void onStart() { - super.onStart(); - AppUsedTimeUtils.getInstance().setAppPackageName(BuildConfig.APPLICATION_ID); - AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis()); - getAlarmData(); - } - - @Override - protected void onResume() { - super.onResume(); - Log.e(TAG, "onResume: "); - if (!isNotificationListenersEnabled()) { - ToastUtil.show("请授予\"" + getString(R.string.app_name) + "\"使用通知权"); - gotoNotificationAccessSetting(this); - } else { - getPermission(); - } - } - - public static final String Launcher3 = "com.android.launcher3"; - public static final String Launcher3Class = "com.android.launcher3.Launcher"; - public static final String Launcher3QuickstepClass = "com.android.launcher3.uioverrides.QuickstepLauncher"; - - private void setDefaultDesktop() { - int is_activation = Settings.Global.getInt(getContentResolver(), CommonConfig.UIUI_ACTIVATION_KEY, 0); - Log.e(TAG, "onResume: is_activation = " + is_activation); - if (is_activation == 1) { - RemoteManager.getInstance().setDefaultDesktop(BuildConfig.APPLICATION_ID, this.getClass().getName()); - } else { - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { - RemoteManager.getInstance().setDefaultDesktop(Launcher3, Launcher3QuickstepClass); - } else { - RemoteManager.getInstance().setDefaultDesktop(Launcher3, Launcher3Class); - } - } - } - - - private String[] permission = new String[]{ - Permission.CALL_PHONE, -// Permission.REQUEST_INSTALL_PACKAGES, - Permission.WRITE_EXTERNAL_STORAGE, - Permission.READ_PHONE_STATE, - Permission.WRITE_SETTINGS, - Permission.READ_CALL_LOG, - Permission.WRITE_CALL_LOG, - }; - - private void getPermission() { - XXPermissions.with(this) - // 申请单个权限 -// .permission(Permission.RECORD_AUDIO) - // 申请多个权限 - .permission(permission) - // 设置权限请求拦截器(局部设置) - //.interceptor(new PermissionInterceptor()) - // 设置不触发错误检测机制(局部设置) - //.unchecked() - .request(new OnPermissionCallback() { - - @Override - public void onGranted(@NonNull List permissions, boolean allGranted) { - if (!allGranted) { - ToastUtil.show("获取部分权限成功,但部分权限未正常授予"); - return; - } -// ToastUtil.show("获取录音和日历权限成功"); - Log.e(TAG, "onGranted: 获取存储权限成功"); - addData(); - } - - @Override - public void onDenied(@NonNull List permissions, boolean doNotAskAgain) { - if (doNotAskAgain) { - ToastUtil.show("被永久拒绝授权,请手动授予存储权限"); - // 如果是被永久拒绝就跳转到应用权限系统设置页面 - XXPermissions.startPermissionActivity(MainActivity.this, permissions); - } else { -// ToastUtil.show("获取录音和日历权限失败"); - Log.e(TAG, "onGranted: 获取存储权限权限失败"); - } - } - }); - } - - - private static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners"; - - private boolean isNotificationListenersEnabled() { - String pkgName = getPackageName(); - final String flat = Settings.Secure.getString(getContentResolver(), ENABLED_NOTIFICATION_LISTENERS); - if (!TextUtils.isEmpty(flat)) { - final String[] names = flat.split(":"); - for (int i = 0; i < names.length; i++) { - final ComponentName cn = ComponentName.unflattenFromString(names[i]); - if (cn != null) { - if (TextUtils.equals(pkgName, cn.getPackageName())) { - return true; - } - } - } - } - return false; - } - - public static boolean gotoNotificationAccessSetting(Context context) { - try { - Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - return true; - - } catch (ActivityNotFoundException e) {//普通情况下找不到的时候需要再特殊处理找一次 - try { - Intent intent = new Intent(); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.Settings$NotificationAccessSettingsActivity"); - intent.setComponent(cn); - intent.putExtra(":settings:show_fragment", "NotificationAccessSettings"); - context.startActivity(intent); - return true; - } catch (Exception e1) { - e1.printStackTrace(); - } - ToastUtil.show("对不起,您的手机暂不支持"); - e.printStackTrace(); - return false; - } - } - - - @Override - protected void onRestart() { - super.onRestart(); - mMainPresenter.sendAPPUsage(); - mMainPresenter.sendRunningInfo(); - } - - @Override - protected void onPause() { - super.onPause(); - } - - @Override - protected void onStop() { - super.onStop(); - AppUsedTimeUtils.getInstance().setEndTime(System.currentTimeMillis()); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mMainPresenter.detachView(); - if (mNewAppReceiver != null) { - unregisterReceiver(mNewAppReceiver); - } - if (updateDesktopReceiver != null) { - unregisterReceiver(updateDesktopReceiver); - } - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { -// super.onSaveInstanceState(outState); - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { -// super.onRestoreInstanceState(savedInstanceState); - } - - private void registmNewAppReceiver() { - mNewAppReceiver = new NewAppReceiver(); - IntentFilter filter = new IntentFilter(); - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - filter.addAction(Intent.ACTION_PACKAGE_ADDED); - filter.addAction(Intent.ACTION_PACKAGE_CHANGED); - filter.addAction(Intent.ACTION_PACKAGE_REPLACED); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addDataScheme("package"); - registerReceiver(mNewAppReceiver, filter); - } - - private NewAppReceiver mNewAppReceiver; - - class NewAppReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - Log.e(TAG, "onReceive: " + action); - if (Intent.ACTION_PACKAGE_ADDED.equals(action) - || Intent.ACTION_PACKAGE_REMOVED.equals(action) - || Intent.ACTION_PACKAGE_CHANGED.equals(action)) { - addData(); - } - } - } - - private SOSNumberReceiver sosNumberReceiver; - - private void registerSOSNumberReceiver() { - if (sosNumberReceiver == null) { - sosNumberReceiver = new SOSNumberReceiver(); - } - IntentFilter filter = new IntentFilter(); - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - filter.addAction("setting_sos"); - registerReceiver(sosNumberReceiver, filter); - } - - class SOSNumberReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Log.e(TAG, "onReceive: " + intent.getAction()); - String setting_sos = intent.getStringExtra("setting_sos"); - if (TextUtils.isEmpty(setting_sos)) return; -// mCustomFragment.setSosNumber(); - } - } - - public static final String ACTION_PACKAGE_HIDE = "com.uiui.aios.ACTION_PACKAGE_HIDE"; - - private UpdateDesktopReceiver updateDesktopReceiver; - - private void registerUpdateDesktopReceiver() { - if (updateDesktopReceiver == null) { - updateDesktopReceiver = new UpdateDesktopReceiver(); - } - IntentFilter filter = new IntentFilter(); - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - filter.addAction("UPDATE_DESKTOP_ICON"); - filter.addAction(ACTION_PACKAGE_HIDE); - registerReceiver(updateDesktopReceiver, filter); - } - - class UpdateDesktopReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - Log.e(TAG, "onReceive: " + intent.getAction()); - addData(); - } - } - - @Override - public void setSystemSettings() { -// mMainPresenter.getDesktopLayout(); - } - - @Override - public void getDesktopLayoutFinish() { - - } - - @Override - public void updateDesktopLayoutFinish() { - - } - - @Override - public void sendAPPUsageFinish() { - - } - - @Override - public void sendRunningInfoFinish() { - - } - - @Override - public void setAdminSnSetting() { - - } } diff --git a/app/src/main/java/com/uiuios/aios/activity/main/PhoneMainActivity.java b/app/src/main/java/com/uiuios/aios/activity/main/PhoneMainActivity.java new file mode 100644 index 0000000..46ff825 --- /dev/null +++ b/app/src/main/java/com/uiuios/aios/activity/main/PhoneMainActivity.java @@ -0,0 +1,12 @@ +package com.uiuios.aios.activity.main; + +import com.uiuios.aios.R; + +public class PhoneMainActivity extends BaseMainActivity { + private static final String TAG = PhoneMainActivity.class.getSimpleName(); + + @Override + public int getLayoutId() { + return R.layout.phone_activity_main; + } +} diff --git a/app/src/main/java/com/uiuios/aios/fragment/ControlFragment.java b/app/src/main/java/com/uiuios/aios/fragment/ControlFragment.java index beaa68f..b28e0ff 100644 --- a/app/src/main/java/com/uiuios/aios/fragment/ControlFragment.java +++ b/app/src/main/java/com/uiuios/aios/fragment/ControlFragment.java @@ -37,12 +37,16 @@ import androidx.fragment.app.Fragment; import com.tencent.mmkv.MMKV; import com.uiuios.aios.R; import com.uiuios.aios.activity.ControlActivity; +import com.uiuios.aios.activity.SplashActivity; +import com.uiuios.aios.activity.main.MainActivity; +import com.uiuios.aios.activity.main.PhoneMainActivity; import com.uiuios.aios.base.BaseFragment; import com.uiuios.aios.config.CommonConfig; import com.uiuios.aios.disklrucache.CacheHelper; import com.uiuios.aios.manager.RemoteManager; import com.uiuios.aios.utils.BrightnessUtils; import com.uiuios.aios.utils.ToastUtil; +import com.uiuios.aios.utils.Utils; import com.uiuios.aios.view.RulerSeekBar; import java.lang.reflect.InvocationTargetException; @@ -163,7 +167,11 @@ public class ControlFragment extends BaseFragment { parent.removeView(rootView); } } else { // 如ongoing果rootView为空 ,就实例化该视图 - rootView = inflater.inflate(R.layout.fragment_control, container, false); + if (Utils.isTablet(container.getContext())) { + rootView = inflater.inflate(R.layout.fragment_control, container, false); + } else { + rootView = inflater.inflate(R.layout.phone_fragment_control, container, false); + } mContext = rootView.getContext(); mCRv = mContext.getContentResolver(); mCacheHelper = new CacheHelper(mContext); diff --git a/app/src/main/java/com/uiuios/aios/utils/ApkUtils.java b/app/src/main/java/com/uiuios/aios/utils/ApkUtils.java index a2b536f..4fb067a 100644 --- a/app/src/main/java/com/uiuios/aios/utils/ApkUtils.java +++ b/app/src/main/java/com/uiuios/aios/utils/ApkUtils.java @@ -224,21 +224,21 @@ public class ApkUtils { // return o1.loadLabel(pm).toString().compareTo(o2.loadLabel(pm).toString()); } }); - resolveInfos.sort(new Comparator() { - @Override - public int compare(ResolveInfo o1, ResolveInfo o2) { - try { - if ((pm.getApplicationInfo(o1.activityInfo.packageName, 0).flags & ApplicationInfo.FLAG_SYSTEM) <= (pm.getApplicationInfo(o2.activityInfo.packageName, 0).flags & ApplicationInfo.FLAG_SYSTEM)) { - return 1; - } else { - return -1; - } - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - } - return -1; - } - }); +// resolveInfos.sort(new Comparator() { +// @Override +// public int compare(ResolveInfo o1, ResolveInfo o2) { +// try { +// if ((pm.getApplicationInfo(o1.activityInfo.packageName, 0).flags & ApplicationInfo.FLAG_SYSTEM) <= (pm.getApplicationInfo(o2.activityInfo.packageName, 0).flags & ApplicationInfo.FLAG_SYSTEM)) { +// return 1; +// } else { +// return -1; +// } +// } catch (PackageManager.NameNotFoundException e) { +// e.printStackTrace(); +// } +// return 0; +// } +// }); ArrayList desktopIcons = new ArrayList<>(); for (ResolveInfo applicationInfo : resolveInfos) { if (!excludeClassName.contains(applicationInfo.activityInfo.name)) { diff --git a/app/src/main/java/com/uiuios/aios/utils/Utils.java b/app/src/main/java/com/uiuios/aios/utils/Utils.java index 2d9a39f..1ea8927 100644 --- a/app/src/main/java/com/uiuios/aios/utils/Utils.java +++ b/app/src/main/java/com/uiuios/aios/utils/Utils.java @@ -9,6 +9,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -258,4 +259,43 @@ public class Utils { // return bgBitmap; } + /** + * 获取系统配置信息 + * + * @param key + * @param defaultValue + * @return + */ + public static String getProperty(String key, String defaultValue) { + String value = defaultValue; + try { + Class c = Class.forName("android.os.SystemProperties"); + Method get = c.getMethod("get", String.class, String.class); + value = (String) (get.invoke(c, key, "unknown")); + } catch (Exception e) { + e.printStackTrace(); + } finally { + return value; + } + } + + public static boolean isTablet(Context context) { +// return isPad(); + boolean isTablet = (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; + Log.e(TAG, "isTablet: " + isTablet); + return isTablet; + } + + + public static boolean isPad() { + boolean result = false; + String mDeviceType = getProperty("ro.build.characteristics", "default"); + Log.e(TAG, "isPad: " + mDeviceType); + if (mDeviceType != null && mDeviceType.equalsIgnoreCase("tablet")) { + result = true; + } + Log.d(TAG, "isPad:" + result); + return result; + } + } diff --git a/app/src/main/res/layout-port/fragment_second.xml b/app/src/main/res/layout-port/fragment_second.xml index e3416c5..5ecd8a1 100644 --- a/app/src/main/res/layout-port/fragment_second.xml +++ b/app/src/main/res/layout-port/fragment_second.xml @@ -6,518 +6,710 @@ android:layout_height="match_parent" tools:context="fragment.second.SecondFragment"> - + android:layout_height="match_parent"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:orientation="vertical"> - + - + - + - + - + - + - + - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_articl.xml b/app/src/main/res/layout/activity_articl.xml index 845f780..1298e0e 100644 --- a/app/src/main/res/layout/activity_articl.xml +++ b/app/src/main/res/layout/activity_articl.xml @@ -3,6 +3,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools" + tools:context=".activity.ArticleActivity" android:background="@color/white"> + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/phone_activity_main.xml b/app/src/main/res/layout/phone_activity_main.xml new file mode 100644 index 0000000..c1cae04 --- /dev/null +++ b/app/src/main/res/layout/phone_activity_main.xml @@ -0,0 +1,28 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/phone_fragment_control.xml b/app/src/main/res/layout/phone_fragment_control.xml new file mode 100644 index 0000000..de03f8e --- /dev/null +++ b/app/src/main/res/layout/phone_fragment_control.xml @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file