package com.vectras.vm; import static android.content.Intent.ACTION_OPEN_DOCUMENT; import static android.content.Intent.ACTION_VIEW; import com.termux.app.TermuxService; import static com.vectras.vm.utils.UIUtils.UIAlert; import android.annotation.SuppressLint; 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.content.pm.PackageManager; 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.provider.Settings; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.ScrollView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import android.Manifest; import android.widget.BaseAdapter; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.preference.PreferenceManager; import com.google.android.material.button.MaterialButton; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.vectras.qemu.MainSettingsManager; import com.vectras.vm.utils.FileUtils; 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; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Objects; public class SetupQemuActivity extends AppCompatActivity implements View.OnClickListener { Activity activity; private final String TAG = "SetupQemuActivity"; ZoomableTextView vterm; MaterialButton inBtn; ProgressBar progressBar; TextView title; LinearLayout linearload; LinearLayout linearcannotconnecttoserver; Button buttontryconnectagain; LinearLayout linearsimplesetupui; LinearLayout linearstartsetup; MaterialButton buttonautosetup; MaterialButton buttonmanualsetup; LinearLayout linearsettingup; TextView textviewsettingup; LinearLayout linearsetupfailed; MaterialButton buttonsetuptryagain; MaterialButton buttonsetupshowlog; TextView textviewshowadvancedsetup; TextView textviewhideadvancedsetup; Spinner spinnerselectmirror; AlertDialog alertDialog; private boolean settingup = false; private boolean libprooterror = false; private RequestNetwork net; private RequestNetwork.RequestListener _net_request_listener; private String contentJSON = ""; private HashMap mmap = new HashMap<>(); private String bootstrapfilelink = ""; private ArrayList> listmapForSelectMirrors = new ArrayList<>(); private String selectedMirrorCommand = ""; private String selectedMirrorLocation = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_setup_qemu); activity = this; linearload = findViewById(R.id.linearload); linearcannotconnecttoserver = findViewById(R.id.linearcannotconnecttoserver); buttontryconnectagain = findViewById(R.id.buttontryconnectagain); linearsimplesetupui = findViewById(R.id.linearsimplesetupui); linearstartsetup = findViewById(R.id.linearstartsetup); buttonautosetup = findViewById(R.id.buttonautosetup); buttonmanualsetup = findViewById(R.id.buttonmanualsetup); linearsettingup = findViewById(R.id.linearsettingup); textviewsettingup = findViewById(R.id.textviewsettingup); linearsetupfailed = findViewById(R.id.linearsetupfailed); buttonsetuptryagain = findViewById(R.id.buttonsetuptryagain); buttonsetupshowlog = findViewById(R.id.buttonsetupshowlog); textviewshowadvancedsetup = findViewById(R.id.textviewshowadvancedsetup); textviewhideadvancedsetup = findViewById(R.id.textviewhideadvancedsetup); spinnerselectmirror = findViewById(R.id.spinnerselectmirror); buttontryconnectagain.setOnClickListener(this); buttonautosetup.setOnClickListener(this); buttonmanualsetup.setOnClickListener(this); buttonsetuptryagain.setOnClickListener(this); buttonsetupshowlog.setOnClickListener(this); textviewshowadvancedsetup.setOnClickListener(this); textviewhideadvancedsetup.setOnClickListener(this); progressBar = findViewById(R.id.progressBar); vterm = findViewById(R.id.tvTerminalOutput); inBtn = findViewById(R.id.btnInstall); title = findViewById(R.id.title); inBtn.setOnClickListener(this); setupSpiner(); tarPath = getExternalFilesDir("data") + "/data.tar.gz"; VectrasApp.prepareDataForAppConfig(activity); spinnerselectmirror.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { selectedMirrorCommand = Objects.requireNonNull(listmapForSelectMirrors.get(position).get("mirror")); selectedMirrorLocation = Objects.requireNonNull(listmapForSelectMirrors.get(position).get("location")); MainSettingsManager.setSelectedMirror(activity, position); } @Override public void onNothingSelected(AdapterView parent) { } }); net = new RequestNetwork(this); _net_request_listener = new RequestNetwork.RequestListener() { @Override public void onResponse(String tag, String response, HashMap responseHeaders) { linearload.setVisibility(View.GONE); contentJSON = response; if (VectrasApp.checkJSONMapIsNormalFromString(contentJSON)) { mmap.clear(); mmap= new Gson().fromJson(contentJSON, new TypeToken>(){}.getType()); if(mmap.containsKey("arm64") && mmap.containsKey("x86_64")) { if (Build.SUPPORTED_ABIS[0].contains("arm64")) { bootstrapfilelink = mmap.get("arm64").toString(); } else { bootstrapfilelink = mmap.get("x86_64").toString(); } linearcannotconnecttoserver.setVisibility(View.GONE); } if (AppConfig.needreinstallsystem) { AppConfig.needreinstallsystem = false; if (!MainSettingsManager.getsetUpWithManualSetupBefore(SetupQemuActivity.this)) { if (AppConfig.getSetupFiles().contains("arm64-v8a") || AppConfig.getSetupFiles().contains("x86_64")) { setupVectras64(); } else { setupVectras32(); } textviewsettingup.setText(getResources().getString(R.string.reinstalling)); simpleSetupUIControler(1); } } } else { linearload.setVisibility(View.GONE); } } @Override public void onErrorResponse(String tag, String message) { linearload.setVisibility(View.GONE); } }; net.startRequestNetwork(RequestNetworkController.GET,AppConfig.bootstrapfileslink,"anbui",_net_request_listener); String filesDir = activity.getFilesDir().getAbsolutePath(); File distroDir = new File(filesDir + "/distro"); File binDir = new File(distroDir + "/bin"); if (!binDir.exists()) { extractBootstraps(); } } public void extractBootstraps() { String filesDir = getFilesDir().getAbsolutePath(); String abi = getDeviceAbi(); String assetPath = "bootstrap/" + abi + ".tar"; String extractedFilePath = filesDir + "/" + abi + ".tar"; ProgressDialog progressDialog = new ProgressDialog(this); progressDialog.setMessage("Extracting data..."); progressDialog.setCancelable(false); progressDialog.show(); new AsyncTask() { String errorMessage = null; @Override protected Boolean doInBackground(Void... voids) { // Step 1: Copy asset to filesDir if (!copyAssetToFile(assetPath, extractedFilePath)) { errorMessage = "Failed to copy asset file."; return false; } // Step 2: Run tar extraction String[] cmdline = {"tar", "xf", extractedFilePath, "-C", filesDir}; Process process = null; try { process = Runtime.getRuntime().exec(cmdline); // Capture standard error output (stderr) BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); StringBuilder errorOutput = new StringBuilder(); String line; while ((line = errorReader.readLine()) != null) { errorOutput.append(line).append("\n"); } errorReader.close(); // Wait for the process to complete int exitCode = process.waitFor(); // If there was any output in stderr, treat it as an error if (exitCode != 0 || errorOutput.length() > 0) { errorMessage = errorOutput.toString().isEmpty() ? "Unknown error" : errorOutput.toString(); return false; } return true; } catch (IOException | InterruptedException e) { errorMessage = e.getMessage(); return false; } finally { if (process != null) { process.destroy(); } } } @Override protected void onPostExecute(Boolean success) { progressDialog.dismiss(); if (success) { Toast.makeText( getApplicationContext(), R.string.extraction_complete, Toast.LENGTH_SHORT) .show(); } else { new AlertDialog.Builder(activity) .setTitle("Extraction Failed") .setMessage("Error: " + errorMessage) .setPositiveButton("OK", null) .show(); } } }.execute(); } /** Copies the specified asset to the given file path. */ private boolean copyAssetToFile(String assetPath, String outputPath) { try (InputStream in = getAssets().open(assetPath); OutputStream out = new FileOutputStream(outputPath)) { byte[] buffer = new byte[1024]; int read; while ((read = in.read(buffer)) != -1) { out.write(buffer, 0, read); } out.flush(); return true; } catch (IOException e) { e.printStackTrace(); return false; } } /** Determines the ABI of the device. */ private String getDeviceAbi() { return Build.SUPPORTED_ABIS[0]; } @Override protected void onResume() { super.onResume(); checkpermissions(); } public void onClick(View v) { int id = v.getId(); if (id == R.id.btnInstall) { File tarGZ = new File(tarPath); if (tarGZ.exists()) { tarGZ.delete(); } alertDialog.show(); } else if (id == R.id.buttonautosetup) { if (AppConfig.getSetupFiles().contains("arm64-v8a") || AppConfig.getSetupFiles().contains("x86_64")) { setupVectras64(); } else { setupVectras32(); } simpleSetupUIControler(1); } else if (id == R.id.buttonmanualsetup) { 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); } else if (id == R.id.buttonsetuptryagain) { simpleSetupUIControler(0); } else if (id == R.id.buttonsetupshowlog) { linearsimplesetupui.setVisibility(View.GONE); } else if (id == R.id.textviewshowadvancedsetup) { linearsimplesetupui.setVisibility(View.GONE); if (linearstartsetup.getVisibility() == View.VISIBLE) { alertDialog.show(); } } else if (id == R.id.buttontryconnectagain) { linearload.setVisibility(View.VISIBLE); net.startRequestNetwork(RequestNetworkController.GET,AppConfig.bootstrapfileslink,"anbui",_net_request_listener); } else if (id == R.id.textviewhideadvancedsetup) { linearsimplesetupui.setVisibility(View.VISIBLE); alertDialog.dismiss(); } } String tarPath; // Function to append text and automatically scroll to bottom @SuppressLint("SetTextI18n") private void appendTextAndScroll(String textToAdd) { ScrollView scrollView = findViewById(R.id.scrollView); // Update the text vterm.append(textToAdd); if (textToAdd.contains("xssFjnj58Id")) { startActivity(new Intent(this, SplashActivity.class)); finish(); } else if (textToAdd.contains("libproot.so --help")){ libprooterror = true; } if (textToAdd.contains("Starting setup...")) { title.setText("Getting ready for you..."); textviewsettingup.setText(R.string.getting_ready_for_you_please_don_t_disconnect_the_network); } else if (textToAdd.contains("fetch http")) { title.setText(getString(R.string.connecting_to_mirror_in) + "\n" + selectedMirrorLocation + "..."); textviewsettingup.setText(getString(R.string.connecting_to_mirror_in) + "\n" + selectedMirrorLocation + "..."); } else if (textToAdd.contains("Installing packages...")) { title.setText(R.string.it_won_t_take_long); textviewsettingup.setText(R.string.completed_10_it_won_t_take_long); } else if (textToAdd.contains("(50/")) { textviewsettingup.setText(R.string.completed_20_it_won_t_take_long); } else if (textToAdd.contains("100/")) { textviewsettingup.setText(R.string.completed_30_it_won_t_take_long); } else if (textToAdd.contains("150/")) { textviewsettingup.setText(R.string.completed_40_it_won_t_take_long); } else if (textToAdd.contains("200/")) { textviewsettingup.setText(R.string.completed_50_it_won_t_take_long); } else if (textToAdd.contains("Downloading Qemu...")) { title.setText(R.string.don_t_disconnect); textviewsettingup.setText(R.string.completed_75_don_t_disconnect); } else if (textToAdd.contains("Installing Qemu...")) { title.setText(R.string.keep_it_up); textviewsettingup.setText(R.string.completed_80_keep_it_up); } else if (textToAdd.contains("qemu-system")) { textviewsettingup.setText(R.string.completed_95_keep_it_up); } else if (textToAdd.contains("Just a sec...")) { title.setText(R.string.almost_there); textviewsettingup.setText(getString(R.string.almost_there)); } // Scroll to the bottom scrollView.post(new Runnable() { @Override public void run() { scrollView.fullScroll(ScrollView.FOCUS_DOWN); } }); } public void onBackPressed() { super.onBackPressed(); return; } // Method to execute the shell command public void executeShellCommand(String userCommand) { new Thread(() -> { try { // Setup the process builder to start PRoot with environmental variables and commands ProcessBuilder processBuilder = new ProcessBuilder(); // Adjust these environment variables as necessary for your app String filesDir = activity.getFilesDir().getAbsolutePath(); String nativeLibDir = activity.getApplicationInfo().nativeLibraryDir; File tmpDir = new File(activity.getFilesDir(), "usr/tmp"); // Setup environment for the PRoot process processBuilder.environment().put("PROOT_TMP_DIR", tmpDir.getAbsolutePath()); processBuilder.environment().put("HOME", "/root"); 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", tmpDir.getAbsolutePath()); processBuilder.environment().put("SHELL", "/bin/sh"); String[] prootCommand = { TermuxService.PREFIX_PATH + "/bin/proot", // PRoot binary path "--kill-on-exit", "--link2symlink", "-0", "-r", filesDir + "/distro", // Path to the rootfs "-b", "/dev", "-b", "/proc", "-b", "/sys", "-b", "/sdcard", "-b", "/storage", "-b", "/data", "-w", "/root", "/bin/sh", "--login"// The shell to execute inside PRoot }; processBuilder.command(prootCommand); Process process = processBuilder.start(); // Get the input and output streams of the process BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); // Send user command to PRoot writer.write(userCommand); writer.newLine(); writer.flush(); writer.close(); // Read the input stream for the output of the command String line; while ((line = reader.readLine()) != null) { final String outputLine = line; activity.runOnUiThread(() -> appendTextAndScroll(outputLine + "\n")); } // Read any errors from the error stream while ((line = errorReader.readLine()) != null) { final String errorLine = line; activity.runOnUiThread(() -> appendTextAndScroll(errorLine + "\n")); } // Clean up reader.close(); errorReader.close(); // Wait for the process to finish process.waitFor(); // Wait for the process to finish int exitValue = process.waitFor(); // Check if the exit value indicates an error if (exitValue != 0) { // If exit value is not zero, display a toast message String toastMessage = "Command failed with exit code: " + exitValue; activity.runOnUiThread(() -> { appendTextAndScroll("Error: " + toastMessage + "\n"); Toast.makeText(activity, toastMessage, Toast.LENGTH_LONG).show(); inBtn.setVisibility(View.VISIBLE); title.setText("Failed!"); simpleSetupUIControler(2); }); if (libprooterror) { AlertDialog alertDialog = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create(); alertDialog.setTitle(getResources().getString(R.string.oops)); alertDialog.setMessage(getResources().getString(R.string.a_serious_problem_has_occurred)); alertDialog.setCancelable(false); alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, getResources().getString(R.string.join_our_community), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(); intent.setAction(ACTION_VIEW); intent.setData(Uri.parse(AppConfig.community)); startActivity(intent); } }); alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getResources().getString(R.string.close), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); alertDialog.show(); } } } catch (IOException | InterruptedException e) { // Handle exceptions by printing the stack trace in the terminal output final String errorMessage = e.getMessage(); activity.runOnUiThread(() -> { appendTextAndScroll("Error: " + errorMessage + "\n"); Toast.makeText(activity, "Error executing command: " + errorMessage, Toast.LENGTH_LONG).show(); inBtn.setVisibility(View.VISIBLE); title.setText("Failed!"); simpleSetupUIControler(2); }); } }).start(); // Execute the command in a separate thread to prevent blocking the UI thread } private void startDownload() { new DownloadFileTask(activity).execute(AppConfig.getSetupFiles()); } private class DownloadFileTask extends AsyncTask { private Context context; private ProgressDialog progressDialog; private int fileLength; public DownloadFileTask(Context context) { this.context = context; } @Override protected void onPreExecute() { progressDialog = new ProgressDialog(context, R.style.MainDialogTheme); progressDialog.setTitle("Downloading... Please do not disconnect from the network."); progressDialog.setMessage(null); progressDialog.setIndeterminate(true); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setCancelable(false); // Allow canceling with back button progressDialog.show(); } @Override protected String doInBackground(String... sUrl) { InputStream input = null; OutputStream output = null; HttpURLConnection connection = null; try { URL url = new URL(sUrl[0]); connection = (HttpURLConnection) url.openConnection(); connection.connect(); if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { return "Server returned HTTP " + connection.getResponseCode() + " " + connection.getResponseMessage(); } fileLength = connection.getContentLength(); input = connection.getInputStream(); output = new FileOutputStream(tarPath); byte data[] = new byte[4096]; long total = 0; int count; while ((count = input.read(data)) != -1) { if (isCancelled()) { input.close(); return null; } total += count; if (fileLength > 0) { publishProgress((int) (total * 100 / fileLength)); } output.write(data, 0, count); } } catch (Exception e) { return e.toString(); } finally { try { if (output != null) output.close(); if (input != null) input.close(); } catch (IOException ignored) { } if (connection != null) connection.disconnect(); } return null; } @Override protected void onProgressUpdate(Integer... progress) { super.onProgressUpdate(progress); // If you get here, the length of the file is known. progressDialog.setIndeterminate(false); progressDialog.setMax(100); progressDialog.setProgress(progress[0]); // Convert the bytes downloaded to MB and update the dialog message accordingly. int progressMB = (int) ((progress[0] / 100.0) * fileLength / (1024 * 1024)); progressDialog.setMessage(progressMB + " MB/" + fileLength / (1024 * 1024) + " MB"); } @Override protected void onPostExecute(String result) { progressDialog.dismiss(); // Dismiss the progress dialog if (result != null) { Toast.makeText(context, "Download error: " + result, Toast.LENGTH_LONG).show(); inBtn.setVisibility(View.VISIBLE); title.setText("Failed!"); } else setupVectras(); } } private void setupVectras() { simpleSetupUIControler(1); inBtn.setVisibility(View.GONE); progressBar.setVisibility(View.VISIBLE); String filesDir = activity.getFilesDir().getAbsolutePath(); String cmd = ""; cmd += selectedMirrorCommand + ";"; executeShellCommand(cmd); executeShellCommand("set -e;" + " echo \"Starting setup...\";" + " apk update;" + " echo \"Installing packages...\";" + " apk add " + AppConfig.neededPkgs + ";" + " echo \"Installing Qemu...\";" + " tar -xzvf " + tarPath + " -C /;" + " rm " + tarPath + ";" + " echo \"Just a sec...\";" + " apk add qemu-audio-sdl pulseaudio;" + " echo export PULSE_SERVER=127.0.0.1 >> /etc/profile;" + " mkdir -p ~/.vnc && echo -e \"555555\\n555555\" | vncpasswd -f > ~/.vnc/passwd && chmod 0600 ~/.vnc/passwd;" + " echo \"installation successful! xssFjnj58Id\""); } private void setupVectras32() { inBtn.setVisibility(View.GONE); progressBar.setVisibility(View.VISIBLE); String filesDir = activity.getFilesDir().getAbsolutePath(); String cmd = ""; cmd += selectedMirrorCommand + ";"; executeShellCommand(cmd); executeShellCommand("set -e;" + " echo \"Starting setup...\";" + " apk update;" + " echo \"Installing packages...\";" + " apk add " + AppConfig.neededPkgs + ";" + //" tar -xzvf " + tarPath + " -C /;" + " echo \"Installing Qemu...\";" + " apk add qemu-system-x86_64 qemu-system-ppc qemu-system-i386 qemu-system-aarch64 qemu-pr-helper qemu-img qemu-audio-sdl pulseaudio mesa-dri-gallium;" + " echo \"Just a sec...\";" + " echo export PULSE_SERVER=127.0.0.1 >> /etc/profile;" + //" rm " + tarPath + ";" + " mkdir -p ~/.vnc && echo -e \"555555\\n555555\" | vncpasswd -f > ~/.vnc/passwd && chmod 0600 ~/.vnc/passwd;" + " echo \"installation successful! xssFjnj58Id\""); } private void setupVectras64() { inBtn.setVisibility(View.GONE); progressBar.setVisibility(View.VISIBLE); String filesDir = activity.getFilesDir().getAbsolutePath(); String cmd = ""; cmd += selectedMirrorCommand + ";"; executeShellCommand(cmd); executeShellCommand("set -e;" + " echo \"Starting setup...\";" + " apk update;" + " echo \"Installing packages...\";" + " apk add " + AppConfig.neededPkgs + ";" + " echo \"Downloading Qemu...\";" + " curl -o setup.tar.gz -L " + bootstrapfilelink + ";" + " echo \"Installing Qemu...\";" + " tar -xzvf setup.tar.gz -C /;" + " rm setup.tar.gz;" + " echo \"Just a sec...\";" + " apk add qemu-audio-sdl pulseaudio;" + " echo export PULSE_SERVER=127.0.0.1 >> /etc/profile;" + " mkdir -p ~/.vnc && echo -e \"555555\\n555555\" | vncpasswd -f > ~/.vnc/passwd && chmod 0600 ~/.vnc/passwd;" + " echo \"installation successful! xssFjnj58Id\""); } private void checkabi() { if (!AppConfig.getSetupFiles().contains("arm64-v8a")) { if (!AppConfig.getSetupFiles().contains("x86_64")) { VectrasApp.oneDialog(getResources().getString(R.string.warning), getResources().getString(R.string.cpu_not_support_64), true, false, activity); } } alertDialog = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create(); alertDialog.setTitle(getString(R.string.bootstrap_required)); alertDialog.setMessage(getString(R.string.you_can_choose_between_auto_download_and_setup_or_manual_setup_by_choosing_bootstrap_file)); alertDialog.setCancelable(false); alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.auto_setup), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //startDownload(); if (AppConfig.getSetupFiles().contains("arm64-v8a") || AppConfig.getSetupFiles().contains("x86_64")) { setupVectras64(); } else { setupVectras32(); } simpleSetupUIControler(1); return; } }); alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.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); } }); } private void checkpermissions() { if (VectrasApp.checkpermissionsgranted(activity, true)) { if (!settingup) { settingup = true; checkabi(); File tarGZ = new File(tarPath); if (tarGZ.exists()) { setupVectras(); } else { if (linearsimplesetupui.getVisibility() == View.GONE) { alertDialog.show(); } } } } } private void simpleSetupUIControler(int status) { if (status == 0) { linearstartsetup.setVisibility(View.VISIBLE); linearsettingup.setVisibility(View.GONE); linearsetupfailed.setVisibility(View.GONE); } else if (status == 1) { linearstartsetup.setVisibility(View.GONE); linearsettingup.setVisibility(View.VISIBLE); linearsetupfailed.setVisibility(View.GONE); } else if (status == 2) { linearstartsetup.setVisibility(View.GONE); linearsettingup.setVisibility(View.GONE); linearsetupfailed.setVisibility(View.VISIBLE); } } 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(); MainSettingsManager.setsetUpWithManualSetupBefore(SetupQemuActivity.this, true); } }; 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 { if (linearsimplesetupui.getVisibility() == View.GONE) { alertDialog.show(); } UIAlert(activity, "INVALID FILE", "please select vectras-vm-" + abi + ".tar.gz file"); } } else if (linearsimplesetupui.getVisibility() == View.GONE) { alertDialog.show(); } } private void setupSpiner() { VectrasApp.setupMirrorListForListmap(listmapForSelectMirrors); spinnerselectmirror.setAdapter(new SpinnerSelectMirrorAdapter(listmapForSelectMirrors)); spinnerselectmirror.setSelection(MainSettingsManager.getSelectedMirror(activity)); } public class SpinnerSelectMirrorAdapter extends BaseAdapter { ArrayList> _data; public SpinnerSelectMirrorAdapter(ArrayList> _arr) { _data = _arr; } @Override public int getCount() { return _data.size(); } @Override public HashMap getItem(int _index) { return _data.get(_index); } @Override public long getItemId(int _index) { return _index; } @Override public View getView(final int _position, View _v, ViewGroup _container) { LayoutInflater _inflater = getLayoutInflater(); View _view = _v; if (_view == null) { _view = _inflater.inflate(R.layout.simple_layout_for_spiner, null); } final TextView textViewLocation = _view.findViewById(R.id.textViewLocation); textViewLocation.setText(Objects.requireNonNull(_data.get((int) _position).get("location"))); return _view; } } }