-
Notifications
You must be signed in to change notification settings - Fork 157
Resolve merge conflicts and add Call Recording feature #518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
440e701
7690b65
aa0dd09
4f32623
baa2d0d
ac4151e
f2976be
1d397ed
11900df
2233e2d
0a28640
780b2f0
b095467
6d9387b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,3 +9,4 @@ | |
| .cxx | ||
| local.properties | ||
| key.jks | ||
| key_base64.txt | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,135 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package com.wmods.wppenhacer.activities; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.content.SharedPreferences; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.os.Bundle; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.util.Log; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.MenuItem; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.widget.RadioButton; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.widget.RadioGroup; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.widget.Toast; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import androidx.appcompat.app.AppCompatActivity; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import androidx.preference.PreferenceManager; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.google.android.material.appbar.MaterialToolbar; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.wmods.wppenhacer.R; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.io.BufferedReader; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.io.DataOutputStream; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.io.InputStreamReader; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class CallRecordingSettingsActivity extends AppCompatActivity { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static final String TAG = "WaEnhancer"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private SharedPreferences prefs; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private RadioGroup radioGroupMode; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private RadioButton radioRoot; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private RadioButton radioNonRoot; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| protected void onCreate(Bundle savedInstanceState) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| super.onCreate(savedInstanceState); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setContentView(R.layout.activity_call_recording_settings); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MaterialToolbar toolbar = findViewById(R.id.toolbar); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setSupportActionBar(toolbar); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (getSupportActionBar() != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getSupportActionBar().setDisplayHomeAsUpEnabled(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getSupportActionBar().setTitle(R.string.call_recording_settings); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| prefs = PreferenceManager.getDefaultSharedPreferences(this); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioGroupMode = findViewById(R.id.radio_group_mode); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioRoot = findViewById(R.id.radio_root); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioNonRoot = findViewById(R.id.radio_non_root); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Load saved preference | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| boolean useRoot = prefs.getBoolean("call_recording_use_root", false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log.d(TAG, "Loaded call_recording_use_root: " + useRoot); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (useRoot) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioRoot.setChecked(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioNonRoot.setChecked(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Direct click listeners on radio buttons | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioRoot.setOnClickListener(v -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log.d(TAG, "Root mode clicked"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioRoot.setChecked(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioNonRoot.setChecked(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Toast.makeText(this, "Checking root access...", Toast.LENGTH_SHORT).show(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkRootAccess(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioNonRoot.setOnClickListener(v -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log.d(TAG, "Non-root mode clicked"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioNonRoot.setChecked(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| radioRoot.setChecked(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| boolean saved = prefs.edit().putBoolean("call_recording_use_root", false).commit(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log.d(TAG, "Saved non-root preference: " + saved); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+70
to
+71
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| boolean saved = prefs.edit().putBoolean("call_recording_use_root", false).commit(); | |
| Log.d(TAG, "Saved non-root preference: " + saved); | |
| prefs.edit().putBoolean("call_recording_use_root", false).apply(); | |
| Log.d(TAG, "Requested save of non-root preference using apply()"); |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The BufferedReader is created but never explicitly closed. While the try-with-resources pattern is used for the cursor below, it's not used here. This could lead to resource leaks. The DataOutputStream is also not closed. Consider wrapping these streams in try-with-resources or ensuring they're closed in a finally block.
| try { | |
| Log.d(TAG, "Executing su command..."); | |
| Process process = Runtime.getRuntime().exec("su"); | |
| DataOutputStream os = new DataOutputStream(process.getOutputStream()); | |
| BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); | |
| os.writeBytes("id\n"); | |
| os.writeBytes("exit\n"); | |
| os.flush(); | |
| // Read output | |
| StringBuilder sb = new StringBuilder(); | |
| String line; | |
| while ((line = reader.readLine()) != null) { | |
| sb.append(line); | |
| } | |
| rootOutput = sb.toString(); | |
| int exitCode = process.waitFor(); | |
| Log.d(TAG, "Root check exit code: " + exitCode + ", output: " + rootOutput); | |
| hasRoot = (exitCode == 0 && rootOutput.contains("uid=0")); | |
| } catch (Exception e) { | |
| Log.e(TAG, "Root check exception: " + e.getMessage()); | |
| hasRoot = false; | |
| } | |
| final boolean rootGranted = hasRoot; | |
| final String output = rootOutput; | |
| Process process = null; | |
| try { | |
| Log.d(TAG, "Executing su command..."); | |
| process = Runtime.getRuntime().exec("su"); | |
| try (DataOutputStream os = new DataOutputStream(process.getOutputStream()); | |
| BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { | |
| os.writeBytes("id\n"); | |
| os.writeBytes("exit\n"); | |
| os.flush(); | |
| // Read output | |
| StringBuilder sb = new StringBuilder(); | |
| String line; | |
| while ((line = reader.readLine()) != null) { | |
| sb.append(line); | |
| } | |
| rootOutput = sb.toString(); | |
| int exitCode = process.waitFor(); | |
| Log.d(TAG, "Root check exit code: " + exitCode + ", output: " + rootOutput); | |
| hasRoot = (exitCode == 0 && rootOutput.contains("uid=0")); | |
| } | |
| } catch (Exception e) { | |
| Log.e(TAG, "Root check exception: " + e.getMessage()); | |
| hasRoot = false; | |
| } finally { | |
| if (process != null) { | |
| process.destroy(); | |
| } | |
| } | |
| final boolean rootGranted = hasRoot; | |
| final String output = rootOutput; |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using commit() instead of apply() blocks the UI thread while writing to disk. These SharedPreferences updates are happening on the UI thread (via runOnUiThread) and could cause frame drops or UI lag. Since immediate confirmation of the write isn't necessary for correctness here, use apply() for better performance.
| boolean saved = prefs.edit().putBoolean("call_recording_use_root", true).commit(); | |
| Log.d(TAG, "Root granted, saved preference: " + saved); | |
| Toast.makeText(this, R.string.root_access_granted, Toast.LENGTH_SHORT).show(); | |
| } else { | |
| boolean saved = prefs.edit().putBoolean("call_recording_use_root", false).commit(); | |
| Log.d(TAG, "Root denied, saved preference: " + saved + ", output: " + output); | |
| prefs.edit().putBoolean("call_recording_use_root", true).apply(); | |
| Log.d(TAG, "Root granted, preference update requested."); | |
| Toast.makeText(this, R.string.root_access_granted, Toast.LENGTH_SHORT).show(); | |
| } else { | |
| prefs.edit().putBoolean("call_recording_use_root", false).apply(); | |
| Log.d(TAG, "Root denied, preference update requested, output: " + output); |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The root check spawns a new thread but doesn't maintain a reference to it or provide any way to cancel it. If the user navigates away from this activity before the check completes, the callback will still attempt to update the UI, which could cause issues. Consider canceling the thread in onDestroy() or checking if the activity is still valid before running UI updates.
| runOnUiThread(() -> { | |
| if (rootGranted) { | |
| boolean saved = prefs.edit().putBoolean("call_recording_use_root", true).commit(); | |
| Log.d(TAG, "Root granted, saved preference: " + saved); | |
| Toast.makeText(this, R.string.root_access_granted, Toast.LENGTH_SHORT).show(); | |
| } else { | |
| boolean saved = prefs.edit().putBoolean("call_recording_use_root", false).commit(); | |
| Log.d(TAG, "Root denied, saved preference: " + saved + ", output: " + output); | |
| radioNonRoot.setChecked(true); | |
| Toast.makeText(this, R.string.root_access_denied, Toast.LENGTH_LONG).show(); | |
| } | |
| }); | |
| if (!isFinishing() && !isDestroyed()) { | |
| runOnUiThread(() -> { | |
| if (isFinishing() || isDestroyed()) { | |
| return; | |
| } | |
| if (rootGranted) { | |
| boolean saved = prefs.edit().putBoolean("call_recording_use_root", true).commit(); | |
| Log.d(TAG, "Root granted, saved preference: " + saved); | |
| Toast.makeText(this, R.string.root_access_granted, Toast.LENGTH_SHORT).show(); | |
| } else { | |
| boolean saved = prefs.edit().putBoolean("call_recording_use_root", false).commit(); | |
| Log.d(TAG, "Root denied, saved preference: " + saved + ", output: " + output); | |
| radioNonRoot.setChecked(true); | |
| Toast.makeText(this, R.string.root_access_denied, Toast.LENGTH_LONG).show(); | |
| } | |
| }); | |
| } |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -43,6 +43,10 @@ protected void onCreate(Bundle savedInstanceState) { | |||||||||
| MainPagerAdapter pagerAdapter = new MainPagerAdapter(this); | ||||||||||
| binding.viewPager.setAdapter(pagerAdapter); | ||||||||||
|
|
||||||||||
| var prefs = androidx.preference.PreferenceManager.getDefaultSharedPreferences(this); | ||||||||||
| if (!prefs.getBoolean("call_recording_enable", false)) { | ||||||||||
| binding.navView.getMenu().findItem(R.id.navigation_recordings).setVisible(false); | ||||||||||
| } | ||||||||||
|
Comment on lines
+46
to
+49
|
||||||||||
| binding.viewPager.setPageTransformer(new DepthPageTransformer()); | ||||||||||
|
|
||||||||||
| binding.navView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() { | ||||||||||
|
|
@@ -70,6 +74,10 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) { | |||||||||
| binding.viewPager.setCurrentItem(4, true); | ||||||||||
| yield true; | ||||||||||
| } | ||||||||||
| case R.id.navigation_recordings -> { | ||||||||||
| binding.viewPager.setCurrentItem(5); | ||||||||||
| yield true; | ||||||||||
| } | ||||||||||
| default -> false; | ||||||||||
|
||||||||||
| default -> false; | |
| default -> { | |
| yield false; | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The environment variable KEY_STORE is now wrapped in quotes when echoed to base64 decode. However, the original code had
${{ secrets.KEY_STORE }}directly without quotes. If the KEY_STORE secret contains spaces or special characters, the quoted version is correct. But verify that this change doesn't break the base64 decoding if the secret value itself contains quotes or if the shell interprets them incorrectly.