Skip to content

Commit 2233e2d

Browse files
committed
feat: Implement comprehensive call recording with UI for management and playback.
1 parent 11900df commit 2233e2d

23 files changed

+1820
-318
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@
8282
android:name=".activities.TextEditorActivity"
8383
android:theme="@style/AppTheme" />
8484

85+
<activity
86+
android:name=".activities.CallRecordingSettingsActivity"
87+
android:theme="@style/Theme.Material3.DynamicColors.DayNight.NoActionBar"
88+
android:parentActivityName=".activities.MainActivity" />
89+
8590
<activity
8691
android:name=".activities.ForceStartActivity"
8792
android:excludeFromRecents="true"
@@ -115,6 +120,16 @@
115120
android:exported="true"
116121
tools:ignore="ExportedService" />
117122

123+
<provider
124+
android:name="androidx.core.content.FileProvider"
125+
android:authorities="${applicationId}.fileprovider"
126+
android:exported="false"
127+
android:grantUriPermissions="true">
128+
<meta-data
129+
android:name="android.support.FILE_PROVIDER_PATHS"
130+
android:resource="@xml/file_paths" />
131+
</provider>
132+
118133
<provider
119134
android:name=".xposed.bridge.providers.HookProvider"
120135
android:authorities="${applicationId}.hookprovider"
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package com.wmods.wppenhacer.activities;
2+
3+
import android.content.SharedPreferences;
4+
import android.os.Bundle;
5+
import android.util.Log;
6+
import android.view.MenuItem;
7+
import android.widget.RadioButton;
8+
import android.widget.RadioGroup;
9+
import android.widget.Toast;
10+
11+
import androidx.appcompat.app.AppCompatActivity;
12+
import androidx.preference.PreferenceManager;
13+
14+
import com.google.android.material.appbar.MaterialToolbar;
15+
import com.wmods.wppenhacer.R;
16+
17+
import java.io.BufferedReader;
18+
import java.io.DataOutputStream;
19+
import java.io.InputStreamReader;
20+
21+
public class CallRecordingSettingsActivity extends AppCompatActivity {
22+
23+
private static final String TAG = "WaEnhancer";
24+
private SharedPreferences prefs;
25+
private RadioGroup radioGroupMode;
26+
private RadioButton radioRoot;
27+
private RadioButton radioNonRoot;
28+
29+
@Override
30+
protected void onCreate(Bundle savedInstanceState) {
31+
super.onCreate(savedInstanceState);
32+
setContentView(R.layout.activity_call_recording_settings);
33+
34+
MaterialToolbar toolbar = findViewById(R.id.toolbar);
35+
setSupportActionBar(toolbar);
36+
if (getSupportActionBar() != null) {
37+
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
38+
getSupportActionBar().setTitle(R.string.call_recording_settings);
39+
}
40+
41+
prefs = PreferenceManager.getDefaultSharedPreferences(this);
42+
43+
radioGroupMode = findViewById(R.id.radio_group_mode);
44+
radioRoot = findViewById(R.id.radio_root);
45+
radioNonRoot = findViewById(R.id.radio_non_root);
46+
47+
// Load saved preference
48+
boolean useRoot = prefs.getBoolean("call_recording_use_root", false);
49+
Log.d(TAG, "Loaded call_recording_use_root: " + useRoot);
50+
51+
if (useRoot) {
52+
radioRoot.setChecked(true);
53+
} else {
54+
radioNonRoot.setChecked(true);
55+
}
56+
57+
// Direct click listeners on radio buttons
58+
radioRoot.setOnClickListener(v -> {
59+
Log.d(TAG, "Root mode clicked");
60+
radioRoot.setChecked(true);
61+
radioNonRoot.setChecked(false);
62+
Toast.makeText(this, "Checking root access...", Toast.LENGTH_SHORT).show();
63+
checkRootAccess();
64+
});
65+
66+
radioNonRoot.setOnClickListener(v -> {
67+
Log.d(TAG, "Non-root mode clicked");
68+
radioNonRoot.setChecked(true);
69+
radioRoot.setChecked(false);
70+
boolean saved = prefs.edit().putBoolean("call_recording_use_root", false).commit();
71+
Log.d(TAG, "Saved non-root preference: " + saved);
72+
Toast.makeText(this, R.string.non_root_mode_enabled, Toast.LENGTH_SHORT).show();
73+
});
74+
}
75+
76+
private void checkRootAccess() {
77+
new Thread(() -> {
78+
boolean hasRoot = false;
79+
String rootOutput = "";
80+
81+
try {
82+
Log.d(TAG, "Executing su command...");
83+
Process process = Runtime.getRuntime().exec("su");
84+
DataOutputStream os = new DataOutputStream(process.getOutputStream());
85+
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
86+
87+
os.writeBytes("id\n");
88+
os.writeBytes("exit\n");
89+
os.flush();
90+
91+
// Read output
92+
StringBuilder sb = new StringBuilder();
93+
String line;
94+
while ((line = reader.readLine()) != null) {
95+
sb.append(line);
96+
}
97+
rootOutput = sb.toString();
98+
99+
int exitCode = process.waitFor();
100+
Log.d(TAG, "Root check exit code: " + exitCode + ", output: " + rootOutput);
101+
102+
hasRoot = (exitCode == 0 && rootOutput.contains("uid=0"));
103+
} catch (Exception e) {
104+
Log.e(TAG, "Root check exception: " + e.getMessage());
105+
hasRoot = false;
106+
}
107+
108+
final boolean rootGranted = hasRoot;
109+
final String output = rootOutput;
110+
111+
runOnUiThread(() -> {
112+
if (rootGranted) {
113+
boolean saved = prefs.edit().putBoolean("call_recording_use_root", true).commit();
114+
Log.d(TAG, "Root granted, saved preference: " + saved);
115+
Toast.makeText(this, R.string.root_access_granted, Toast.LENGTH_SHORT).show();
116+
} else {
117+
boolean saved = prefs.edit().putBoolean("call_recording_use_root", false).commit();
118+
Log.d(TAG, "Root denied, saved preference: " + saved + ", output: " + output);
119+
radioNonRoot.setChecked(true);
120+
Toast.makeText(this, R.string.root_access_denied, Toast.LENGTH_LONG).show();
121+
}
122+
});
123+
}).start();
124+
}
125+
126+
@Override
127+
public boolean onOptionsItemSelected(MenuItem item) {
128+
if (item.getItemId() == android.R.id.home) {
129+
finish();
130+
return true;
131+
}
132+
return super.onOptionsItemSelected(item);
133+
}
134+
}
135+

0 commit comments

Comments
 (0)