henrichg / PhoneProfilesPlus

Profile manager for Android - event triggered
Apache License 2.0
423 stars 32 forks source link

Airplane Mode #122

Closed ghost closed 9 months ago

ghost commented 9 months ago

Hello sir ! can you help me to separate the logic of airplane mode by using default assistant. I tried but i failed. my scene is this that i want that there will be a button on which i clicked and the airplane mode will toggle.

ghost commented 9 months ago

Hello sir ! I need your help. Actually i was creating my own app to toggle airplane mode which will be connect to my Python script which will be running in Termux apk. I will toggle airplane mode from my script. i will handle it. the main problem is that i was unable to implement the logic of airplane mode toggle using assistant as your app is doing, Can you please help me about this? this is very important for me

henrichg commented 9 months ago

How to use it is in ActivateProfileHelper.setAirplaneMode() Application must be set as default assistant:

if (isPPPSetAsDefaultAssistant(context)) {
        Intent intent = new Intent(PPVoiceService.ACTION_ASSISTANT);
        intent.putExtra("ACTION", Settings.ACTION_VOICE_CONTROL_AIRPLANE_MODE);
        intent.putExtra(Settings.EXTRA_AIRPLANE_MODE_ENABLED, mode);
        context.sendBroadcast(intent);
}

ActivateProfileHelper.isPPPSetAsDefaultAssistant()

static boolean isPPPSetAsDefaultAssistant(Context context) {
    boolean assistIsSet = false;

    ComponentName compName = null;
    try {
        Method declaredMethod = UserHandle.class.getDeclaredMethod("myUserId", new Class[0]);
        declaredMethod.setAccessible(true);
        Integer num = (Integer) declaredMethod.invoke(null, new Object[0]);
        if (num != null) {
            @SuppressLint("PrivateApi")
            Object newInstance = Class.forName("com.android.internal.app.AssistUtils").getConstructor(new Class[]{Context.class}).newInstance(new Object[]{context});
            Method declaredMethod2 = newInstance.getClass().getDeclaredMethod("getAssistComponentForUser", new Class[]{Integer.TYPE});
            declaredMethod2.setAccessible(true);
            compName = (ComponentName) declaredMethod2.invoke(newInstance, new Object[]{num});
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    if (compName != null && compName.getPackageName().equals(context.getPackageName())) {
        assistIsSet = true;
    }
    if (!assistIsSet) {
        String string = Settings.Secure.getString(context.getContentResolver(), "assistant");
        if ((string != null) && (string.startsWith(context.getPackageName()))) {
            assistIsSet = true;
        }
    }

    return assistIsSet;
}

Manifest file:

  <service android:name="sk.henrichg.phoneprofilesplus.PPVoiceService"
      android:exported="true"
      android:permission="android.permission.BIND_VOICE_INTERACTION"
      tools:ignore="IntentFilterExportedReceiver">
      <meta-data android:name="android.voice_interaction"
          android:resource="@xml/assist_metadata"/>
      <intent-filter>
          <action android:name="android.service.voice.VoiceInteractionService"/>
      </intent-filter>
  </service>

  <service android:name="sk.henrichg.phoneprofilesplus.PPVoiceSessionService"
      android:exported="true"
      android:permission="android.permission.BIND_VOICE_INTERACTION"/>

  <!-- This service is required, when user needs to configure PPP as default assistant, for -->
  <!-- airplane mode switching without root. -->
  <!-- This service is required by Googe (e-mail from Google):
       "We recently uncovered a highly visible user-facing issue where your app (sk.henrichg.phoneprofilesplus)
       causes the Android RecognitionService to break, which is potentially affecting all of your users on
       Android 11 or earlier.
       Specifically, when a user on Android 11 or earlier sets your assistant application as the default
       assistant for the phone, it is expected to provide RecognitionService (speech to text) functionality
       to other applications on the same device as well. However, if another app requests the RecognitionService
       functionality and does not receive it from your assistant app, the requesting app will immediately crash.
       The Android RecognitionService functionality is a widely used service. To fix the issue as soon as
       possible, please review the below recommendation." -->
  <service android:name="sk.henrichg.phoneprofilesplus.PPRecognitionServiceTrampoline"
      android:label="RecognitionServiceTrampoline"
      android:exported="true"
      tools:ignore="ExportedService">
      <intent-filter>
          <action android:name="android.speech.RecognitionService" />
          <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
  </service>
henrichg commented 9 months ago

By me is better using Shizuku (replaces root calls = root is not required):

private static final String COMMAND_SETTINGS_PUT_GLOBAL = "settings put global ";
private static final String COMMAND_AM_AIRPLANE_MODE = "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state ";
private static final String COMMAND_AIRPLANE_MODE = "cmd connectivity airplane-mode";

if (ShizukuUtils.hasShizukuPermission()) {
    synchronized (PPApplication.rootMutex) {
        if (Build.VERSION.SDK_INT <= 27) {
            String command1;
            String command2;
            final String AIRPLANE_MODE_ON = "airplane_mode_on ";
            if (mode) {
                command1 = COMMAND_SETTINGS_PUT_GLOBAL + AIRPLANE_MODE_ON + "1";
                command2 = COMMAND_AM_AIRPLANE_MODE + StringConstants.TRUE_STRING;
            } else {
                command1 = COMMAND_SETTINGS_PUT_GLOBAL + AIRPLANE_MODE_ON + "0";
                command2 = COMMAND_AM_AIRPLANE_MODE + StringConstants.FALSE_STRING;
            }
            try {
                ShizukuUtils.executeCommand(command1);
                ShizukuUtils.executeCommand(command2);
            } catch (Exception e) {
                //Log.e("ActivateProfileHelper.setAirplaneMode", Log.getStackTraceString(e));
            }
        } else {
            String command1;
            if (mode) {
                command1 = COMMAND_AIRPLANE_MODE + " enable";
            } else {
                command1 = COMMAND_AIRPLANE_MODE + " disable";
            }
            try {
                ShizukuUtils.executeCommand(command1);
            } catch (Exception e) {
                //Log.e("ActivateProfileHelper.setAirplaneMode", Log.getStackTraceString(e));
            }
        }
    }
}
ghost commented 9 months ago

@henrichg thank you soo much sir. Let me try this approach . Actually i did this approach but my app was not working. Its screen keeps blinking all the time when i set it to default assistant. Let me try your approach again today . I will let you know about the progress. Thanks for your kind reply !

ghost commented 9 months ago

@henrichg Hello sir ! i created the app as you provide me the settings. but my app have no effect. Can i send you my app to debug ??? Please this is very important to me .

henrichg commented 9 months ago

Debug it yourself in Android emulator or in physical device. I debug my applications in physical device.

Dňa ne 18. 2. 2024, 17:57 androiddev16 @.***> napísal(a):

@henrichg https://github.com/henrichg Hello sir ! i created the app as you provide me the settings. but my app have no effect. Can i send you my app to debug ??? Please this is very important to me .

— Reply to this email directly, view it on GitHub https://github.com/henrichg/PhoneProfilesPlus/issues/122#issuecomment-1951384906, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA63YWQ4D4ZJXWNQGFZEO73YUIXJLAVCNFSM6AAAAABDNEIUASVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNJRGM4DIOJQGY . You are receiving this because you were mentioned.Message ID: @.***>

ghost commented 9 months ago

@henrichg Thanks sir i have successfully created the app. Thanks for your kind reply and help....