Android 14+ FIX

This commit is contained in:
Epic Studios 2024-04-18 23:01:02 +02:00
parent 0bbbeb5445
commit 4ec46836e8
79 changed files with 638 additions and 119 deletions

View file

@ -29,8 +29,8 @@ public class ConnectionBean {
public ConnectionBean() {
setAddress(Config.defaultVNCHost);
setUserName(Config.defaultVNCUsername);
setPassword(Config.defaultVNCPasswd);
setPort(Config.defaultVNCPort + 5900);
setPassword("555555");
setPort(Config.defaultVNCPort + 5901);
setColorModel(Config.defaultVNCColorMode);
if (Config.enable_qemu_fullScreen)
setScaleMode(Config.defaultFullscreenScaleMode);

View file

@ -314,7 +314,7 @@ public class RfbProto {
//
LocalSocket localSocket = null;
public static boolean allow_external = false;
public static boolean allow_external = true;
//-RfbProto(String h, int p, VncViewer v) throws IOException {
RfbProto(String h, int p) throws IOException{

View file

@ -127,7 +127,7 @@ public class Config {
public static int MAX_DISPLAY_REFRESH_RATE = 100; //Hz
// VNC Defaults
public static String defaultVNCHost = "127.0.0.1";
public static String defaultVNCHost = "localhost";
public static final String defaultVNCUsername = "vectras";
public static final String defaultVNCPasswd = "";

View file

@ -753,6 +753,16 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
return prefs.getString("vmUi", "VNC");
}
public static void setResolution(Activity activity, String RESOLUTION) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("RESOLUTION", RESOLUTION);
edit.apply();
}
public static String getResolution(Activity activity) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
return prefs.getString("RESOLUTION", "800x600x32");
}
public static void setSoundCard(Activity activity, String soundCard) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor edit = prefs.edit();

View file

@ -19,7 +19,7 @@ import java.util.Objects;
public class AppConfig {
// App Config
public static final String vectrasVersion = "v2.8";
public static final String vectrasVersion = "2.9.1";
public static final String vectrasWebsite = "https://vectras.netlify.com/";
public static final String vectrasHelp = "https://vectras.netlify.app/how";
public static final String vectrasRaw = "https://raw.githubusercontent.com/epicstudios856/Vectras-windows-emulator/main/";
@ -33,11 +33,11 @@ public class AppConfig {
public static final String storeJson = vectrasRaw + "store_list.json";
public static final String vectrasPkg = vectrasWebsite + "download";
public static final String serverIP = "https://github.com/epicstudios856/Vectras-VM-Android";
public static final String releaseUrl = "https://vectrasvm.blackstorm.cc/vectras-vm/Releases/";
public static String getSetupFiles() {
String abi = Build.SUPPORTED_ABIS[0];
return serverIP + "/releases/download/" + vectrasVersion + "/" + abi + "-vectras.tar.gz";
return releaseUrl + vectrasVersion + "/packages/vectras-vm-" + abi + ".tar.gz";
}
public static final String romsJson(Activity activity) {

View file

@ -432,6 +432,7 @@ public class CustomRomActivity extends AppCompatActivity {
title.setText(current.itemName);
icon.setText(current.itemIcon);
drive.setText(current.itemPath);
Pattern pattern = Pattern.compile("-drive index=1,media=cdrom,file='([^']*)'");
Matcher matcher = pattern.matcher(current.itemExtra);
@ -439,7 +440,18 @@ public class CustomRomActivity extends AppCompatActivity {
String cdromPath = matcher.group(1);
cdrom.setText(cdromPath);
}
qemu.setText(current.itemExtra);
File imgFile = new File(icon.getText().toString());
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ImageView ivIcon = findViewById(R.id.ivIcon);
ivIcon.setImageBitmap(myBitmap);
}
}
}

View file

@ -1,12 +1,8 @@
package com.vectras.vm;
import static android.content.Intent.ACTION_OPEN_DOCUMENT;
import static com.vectras.vm.utils.UIUtils.UIAlert;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.vectras.qemu.*;
import android.app.ActivityManager;
import android.app.Dialog;
import android.app.NotificationManager;
@ -22,13 +18,13 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.DocumentsContract;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
@ -55,21 +51,21 @@ import com.google.android.gms.ads.initialization.OnInitializationCompleteListene
import com.google.android.gms.ads.interstitial.InterstitialAd;
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
import com.google.android.material.bottomappbar.BottomAppBar;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.elevation.SurfaceColors;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.textfield.TextInputEditText;
import com.vectras.qemu.Config;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.qemu.MainVNCActivity;
import com.vectras.qemu.utils.RamInfo;
import com.vectras.vm.MainRoms.AdapterMainRoms;
import com.vectras.vm.MainRoms.DataMainRoms;
import com.vectras.vm.adapter.LogsAdapter;
import com.vectras.vm.logger.VectrasStatus;
import com.vectras.vm.utils.AppUpdater;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.UIUtils;
import com.vectras.vterm.Terminal;
import com.vectras.vm.adapter.LogsAdapter;
import org.json.JSONArray;
import org.json.JSONException;
@ -85,7 +81,6 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
@ -396,8 +391,8 @@ public class MainActivity extends AppCompatActivity {
if (bufferedReader.readLine() != null || bufferedReader2.readLine() != null) {
String logLine = bufferedReader.readLine();
String logLine2 = bufferedReader2.readLine();
VectrasStatus.logError("<font color='red'>[E] "+logLine+"</font>");
VectrasStatus.logError("<font color='yellow'>[W] "+logLine2+"</font>");
VectrasStatus.logError("<font color='red'>[E] " + logLine + "</font>");
VectrasStatus.logError("<font color='yellow'>[W] " + logLine2 + "</font>");
}
} catch (IOException e) {
throw new RuntimeException(e);
@ -525,6 +520,7 @@ public class MainActivity extends AppCompatActivity {
private void errorUpdateDialog(String error) {
VectrasStatus.logInfo(String.format(error));
}
public static void loadDataVbi() {
data = new ArrayList<>();
@ -627,21 +623,30 @@ public class MainActivity extends AppCompatActivity {
public static void startVM(String vmName, String env) {
boolean isRunning = isMyServiceRunning(MainService.class);
if (!isRunning) {
Intent serviceIntent = new Intent(activity, MainService.class);
MainService.env = env;
MainService.CHANNEL_ID = vmName;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
activity.startForegroundService(serviceIntent);
} else {
activity.startService(serviceIntent);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
if (!isRunning) {
Intent serviceIntent = new Intent(activity, MainService.class);
if (MainSettingsManager.getVmUi(activity).equals("X11"))
MainService.env = "dwm; " + env;
else
MainService.env = env;
MainService.CHANNEL_ID = vmName;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
activity.startForegroundService(serviceIntent);
} else {
activity.startService(serviceIntent);
}
}
}
}
}, 5000);
if (MainSettingsManager.getVmUi(activity).equals("VNC")) {
activity.startActivity(new Intent(activity, MainVNCActivity.class));
} else if (MainSettingsManager.getVmUi(activity).equals("SPICE")) {
//activity.startActivity(new Intent(activity, RemoteCanvasActivity.class));
} else if (MainSettingsManager.getVmUi(activity).equals("X11")) {
//activity.startActivity(new Intent(activity, X11Activity.class));
}
String[] params = env.split("\\s+");
VectrasStatus.logInfo("Params:");
@ -709,6 +714,7 @@ public class MainActivity extends AppCompatActivity {
Log.d("TAG", "The interstitial ad wasn't ready yet.");
}
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

View file

@ -49,6 +49,7 @@ public class MainService extends Service {
Terminal vterm = new Terminal(this);
//vterm.executeShellCommand("chmod 770 /run/pulse -R");
//vterm.executeShellCommand("pulseaudio --system --disallow-exit --disallow-module-loading --daemonize --log-level=debug --log-time=1");
vterm.executeShellCommand("vncserver :1");
vterm.executeShellCommand(env);
}
} else

View file

@ -1,17 +1,30 @@
package com.vectras.vm;
import static android.content.Intent.ACTION_OPEN_DOCUMENT;
import static com.vectras.vm.utils.UIUtils.UIAlert;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;
import com.google.android.material.button.MaterialButton;
import com.vectras.vterm.view.ZoomableTextView;
@ -19,6 +32,8 @@ import com.vectras.vterm.view.ZoomableTextView;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@ -29,11 +44,12 @@ import java.net.HttpURLConnection;
import java.net.URL;
public class SetupQemuActivity extends AppCompatActivity implements View.OnClickListener {
SetupQemuActivity activity;
Activity activity;
private final String TAG = "SetupQemuActivity";
ZoomableTextView vterm;
MaterialButton inBtn;
ProgressBar progressBar;
AlertDialog alertDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -46,15 +62,41 @@ public class SetupQemuActivity extends AppCompatActivity implements View.OnClick
vterm = findViewById(R.id.tvTerminalOutput);
inBtn = findViewById(R.id.btnInstall);
inBtn.setOnClickListener(activity);
inBtn.setOnClickListener(this);
tarPath = getExternalFilesDir("data") + "/data.tar.gz";
alertDialog = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create();
alertDialog.setTitle("BOOTSTRAP REQUIRED!");
alertDialog.setMessage("U can choose between auto download and setup or manual setup by choosing bootstrap file.");
alertDialog.setCancelable(false);
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "AUTO SETUP", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
startDownload();
return;
}
});
alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "MANUAL SETUP", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// Optionally, specify a URI for the file that should appear in the
// system file picker when it loads.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
}
startActivityForResult(intent, 1001);
}
});
File tarGZ = new File(tarPath);
if (tarGZ.exists()) {
setupVectras();
} else {
startDownload();
alertDialog.show();
}
}
@ -63,10 +105,9 @@ public class SetupQemuActivity extends AppCompatActivity implements View.OnClick
if (id == R.id.btnInstall) {
File tarGZ = new File(tarPath);
if (tarGZ.exists()) {
setupVectras();
} else {
startDownload();
tarGZ.delete();
}
alertDialog.show();
}
}
@ -109,8 +150,10 @@ public class SetupQemuActivity extends AppCompatActivity implements View.OnClick
String filesDir = activity.getFilesDir().getAbsolutePath();
String nativeLibDir = activity.getApplicationInfo().nativeLibraryDir;
File tmpDir = new File(activity.getFilesDir(), "tmp");
// Setup environment for the PRoot process
processBuilder.environment().put("PROOT_TMP_DIR", filesDir + "/tmp");
processBuilder.environment().put("PROOT_TMP_DIR", tmpDir.getAbsolutePath());
processBuilder.environment().put("PROOT_LOADER", nativeLibDir + "/libproot-loader.so");
processBuilder.environment().put("PROOT_LOADER_32", nativeLibDir + "/libproot-loader32.so");
@ -118,7 +161,7 @@ public class SetupQemuActivity extends AppCompatActivity implements View.OnClick
processBuilder.environment().put("USER", "root");
processBuilder.environment().put("PATH", "/bin:/usr/bin:/sbin:/usr/sbin");
processBuilder.environment().put("TERM", "xterm-256color");
processBuilder.environment().put("TMPDIR", "/tmp");
processBuilder.environment().put("TMPDIR", tmpDir.getAbsolutePath());
processBuilder.environment().put("SHELL", "/bin/sh");
// Example PRoot command; replace 'libproot.so' and other paths as needed
@ -308,12 +351,80 @@ public class SetupQemuActivity extends AppCompatActivity implements View.OnClick
executeShellCommand("set -e;" +
" echo 'Starting setup...';" +
" apk update;" +
" apk add libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev libusbredirparser usbredir-dev libiscsi-dev sdl2 sdl2-dev libepoxy-dev virglrenderer-dev tar;" +
" clear;" +
" tar -xvzf " + tarPath + " -C " + filesDir + "/distro;" +
" apk add tar tigervnc dwm libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +
" libusbredirparser usbredir-dev libiscsi-dev sdl2 sdl2-dev libepoxy-dev virglrenderer-dev rdma-core" +
" libusb ncurses-libs curl libnfs sdl2 gtk+3.0 fuse libpulse libseccomp libjack pipewire liburing;" +
" tar -xzvf " + tarPath + " -C /;" +
" rm " + tarPath + ";" +
" clear;" +
" mkdir -p ~/.vnc && echo -e \"555555\\n555555\" | vncpasswd -f > ~/.vnc/passwd && chmod 0600 ~/.vnc/passwd" +
" echo \"installation successful! xssFjnj58Id\"");
}
public String getPath(Uri uri) {
return com.vectras.vm.utils.FileUtils.getPath(this, uri);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent ReturnedIntent) {
super.onActivityResult(requestCode, resultCode, ReturnedIntent);
if (requestCode == 1001 && resultCode == RESULT_OK) {
Uri content_describer = ReturnedIntent.getData();
File selectedFilePath = new File(getPath(content_describer));
ProgressBar loading = progressBar;
String abi = Build.SUPPORTED_ABIS[0];
if (selectedFilePath.toString().endsWith(abi+".tar.gz")) {
loading.setVisibility(View.VISIBLE);
new Thread(new Runnable() {
@Override
public void run() {
FileInputStream File = null;
try {
File = (FileInputStream) getContentResolver().openInputStream(content_describer);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
try {
try {
OutputStream out = new FileOutputStream(new File(tarPath));
try {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = File.read(buf)) > 0) {
out.write(buf, 0, len);
}
} finally {
out.close();
}
} finally {
Runnable runnable = new Runnable() {
@Override
public void run() {
loading.setVisibility(View.GONE);
alertDialog.dismiss();
setupVectras();
}
};
activity.runOnUiThread(runnable);
File.close();
}
} catch (IOException e) {
Runnable runnable = new Runnable() {
@Override
public void run() {
loading.setVisibility(View.GONE);
UIAlert(activity, e.toString(), "error");
}
};
activity.runOnUiThread(runnable);
}
}
}).start();
} else {
alertDialog.show();
UIAlert(activity, "NOT VAILED FILE", "please select vectras-vm-" + abi + ".tar.gz file");
}
} else
alertDialog.show();
}
}

View file

@ -81,9 +81,10 @@ public class SplashActivity extends AppCompatActivity implements Runnable {
String filesDir = activity.getFilesDir().getAbsolutePath();
String nativeLibDir = activity.getApplicationInfo().nativeLibraryDir;
File tmpDir = new File(filesDir + "/tmp/xdg");
if (!tmpDir.exists()) {
File tmpDir = new File(context.getFilesDir(), "tmp");
if (!tmpDir.isDirectory()) {
tmpDir.mkdirs();
FileUtils.chmod(tmpDir, 0771);
}
File vDir = new File(com.vectras.vm.AppConfig.maindirpath);

View file

@ -1,6 +1,7 @@
package com.vectras.vm;
import android.app.Activity;
import android.content.Intent;
import com.vectras.qemu.Config;
import com.vectras.qemu.MainSettingsManager;
@ -93,9 +94,6 @@ public class StartVM {
acclerationStr = "-accel tcg,thread=multi";
acclerationStr += ",tb-size=" + MainSettingsManager.getTbSize(activity);
String spiceStr = "-spice ";
spiceStr += "port=6999,disable-ticketing=on";
String boot = "-boot ";
boot += MainSettingsManager.getBoot(activity);
@ -135,14 +133,19 @@ public class StartVM {
if (MainSettingsManager.getVmUi(activity).equals("VNC")) {
String vncStr = "-vnc ";
params.add(vncStr);
//params.add(vncStr);
// Allow connections only from localhost using localsocket without a password
//params.add(Config.defaultVNCHost+":" + Config.defaultVNCPort);
String qmpParams = "unix:";
qmpParams += Config.getLocalVNCSocketPath();
params.add(qmpParams);
} else if (MainSettingsManager.getVmUi(activity).equals("SPICE"))
//params.add(qmpParams);
} else if (MainSettingsManager.getVmUi(activity).equals("SPICE")) {
String spiceStr = "-spice ";
spiceStr += "port=6999,disable-ticketing=on";
params.add(spiceStr);
} else if (MainSettingsManager.getVmUi(activity).equals("X11")) {
}
params.add("-monitor");
params.add("vc");

View file

@ -39,7 +39,8 @@ public class Terminal {
private String user = "root";
public static Process qemuProcess;
public static String DISPLAY = ":1";
public Terminal(Context context) {
this.context = context;
}
@ -73,8 +74,10 @@ public class Terminal {
String filesDir = context.getFilesDir().getAbsolutePath();
String nativeLibDir = context.getApplicationInfo().nativeLibraryDir;
File tmpDir = new File(context.getFilesDir(), "tmp");
// Setup environment for the PRoot qemuProcess
processBuilder.environment().put("PROOT_TMP_DIR", filesDir + "/tmp");
processBuilder.environment().put("PROOT_TMP_DIR", tmpDir.getAbsolutePath());
processBuilder.environment().put("PROOT_LOADER", nativeLibDir + "/libproot-loader.so");
processBuilder.environment().put("PROOT_LOADER_32", nativeLibDir + "/libproot-loader32.so");
@ -82,10 +85,13 @@ public class Terminal {
processBuilder.environment().put("USER", user);
processBuilder.environment().put("PATH", "/bin:/usr/bin:/sbin:/usr/sbin");
processBuilder.environment().put("TERM", "xterm-256color");
processBuilder.environment().put("TMPDIR", filesDir + "/tmp");
processBuilder.environment().put("TMPDIR", tmpDir.getAbsolutePath());
processBuilder.environment().put("SHELL", "/bin/sh");
processBuilder.environment().put("DISPLAY", DISPLAY);
processBuilder.environment().put("PULSE_SERVER", "/run/pulse/native");
processBuilder.environment().put("XDG_RUNTIME_DIR", "/run");
processBuilder.environment().put("QEMU_AUDIO_DRV", "sdl");
processBuilder.environment().put("SDL_VIDEODRIVER", "x11");
// Example PRoot command; replace 'libproot.so' and other paths as needed
String[] prootCommand = {

View file

@ -102,7 +102,7 @@ public class TerminalBottomSheetDialog {
new Thread(() -> {
String username = null;
// Update the prompt on the UI thread
String finalUsername = username != null ? username : "user";
String finalUsername = username != null ? username : "root";
activity.runOnUiThread(() -> {
promptView.setText(finalUsername + "@localhost:~$ ");
});
@ -154,8 +154,10 @@ public class TerminalBottomSheetDialog {
String filesDir = activity.getFilesDir().getAbsolutePath();
String nativeLibDir = activity.getApplicationInfo().nativeLibraryDir;
File tmpDir = new File(activity.getFilesDir(), "tmp");
// Setup environment for the PRoot process
processBuilder.environment().put("PROOT_TMP_DIR", filesDir + "/tmp");
processBuilder.environment().put("PROOT_TMP_DIR", tmpDir.getAbsolutePath());
processBuilder.environment().put("PROOT_LOADER", nativeLibDir + "/libproot-loader.so");
processBuilder.environment().put("PROOT_LOADER_32", nativeLibDir + "/libproot-loader32.so");
@ -163,9 +165,13 @@ public class TerminalBottomSheetDialog {
processBuilder.environment().put("USER", "root");
processBuilder.environment().put("PATH", "/bin:/usr/bin:/sbin:/usr/sbin");
processBuilder.environment().put("TERM", "xterm-256color");
processBuilder.environment().put("TMPDIR", "/tmp");
processBuilder.environment().put("TMPDIR", tmpDir.getAbsolutePath());
processBuilder.environment().put("SHELL", "/bin/sh");
processBuilder.environment().put("DISPLAY", getLocalIpAddress()+":0");
processBuilder.environment().put("DISPLAY", getLocalIpAddress()+":1");
processBuilder.environment().put("PULSE_SERVER", "/run/pulse/native");
processBuilder.environment().put("XDG_RUNTIME_DIR", "/run");
processBuilder.environment().put("QEMU_AUDIO_DRV", "sdl");
processBuilder.environment().put("SDL_VIDEODRIVER", "x11");
// Example PRoot command; replace 'libproot.so' and other paths as needed
String[] prootCommand = {