mirror of
https://github.com/xoureldeen/Vectras-VM-Android.git
synced 2026-05-19 16:42:13 +00:00
commit
e3dc8ff5b6
36 changed files with 55 additions and 2014 deletions
|
|
@ -15,8 +15,8 @@ android {
|
|||
applicationId "com.vectras.vm"
|
||||
minSdk minApi
|
||||
targetSdk targetApi
|
||||
versionCode 59
|
||||
versionName "3.5.5"
|
||||
versionCode 60
|
||||
versionName "3.5.6"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
|
||||
|
|
|
|||
|
|
@ -146,19 +146,6 @@
|
|||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".setupwizard.SetupWizardActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden|smallestScreenSize|screenLayout"
|
||||
android:exported="false"
|
||||
android:hardwareAccelerated="true"
|
||||
tools:ignore="DiscouragedApi" /> <!-- stupid android issue -->
|
||||
<activity
|
||||
android:name=".RomStoreActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden|smallestScreenSize|screenLayout"
|
||||
android:exported="false"
|
||||
android:hardwareAccelerated="true"
|
||||
android:label="Roms"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name=".AboutActivity"
|
||||
android:exported="true"
|
||||
|
|
@ -168,11 +155,6 @@
|
|||
android:name=".ImagePrvActivity"
|
||||
android:exported="true"
|
||||
android:hardwareAccelerated="true" />
|
||||
<activity
|
||||
android:name=".VectrasApp$CrashActivity"
|
||||
android:exported="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:label="App Crash" />
|
||||
<activity
|
||||
android:name="com.vectras.qemu.MainVNCActivity"
|
||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.vectras.vm.Fragment;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
|
||||
|
|
@ -39,12 +40,13 @@ public class CreateImageDialogFragment extends DialogFragment {
|
|||
}
|
||||
|
||||
// If you want to style the dialog to have no title or to adjust the width, etc., override onCreateDialog.
|
||||
@SuppressLint("SetTextI18n")
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(Objects.requireNonNull(getActivity()), R.style.MainDialogTheme);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity(), R.style.MainDialogTheme);
|
||||
|
||||
View view = getActivity().getLayoutInflater().inflate(R.layout.create_vhd, null);
|
||||
View view = requireActivity().getLayoutInflater().inflate(R.layout.create_vhd, null);
|
||||
|
||||
TextInputEditText imageSize = view.findViewById(R.id.size);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
package com.vectras.vm.Fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.vectras.qemu.MainSettingsManager;
|
||||
import com.vectras.vm.MainRoms.AdapterMainRoms;
|
||||
import com.vectras.vm.MainRoms.DataMainRoms;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.utils.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class HomeFragment extends Fragment {
|
||||
|
||||
public static View view;
|
||||
public static RecyclerView mRVMainRoms;
|
||||
public static LinearLayout romsLayout;
|
||||
public static AdapterMainRoms mMainAdapter;
|
||||
public static JSONArray jArray;
|
||||
public static List<DataMainRoms> data;
|
||||
private SwipeRefreshLayout refreshRoms;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
// TODO show the text view in @layout/home_fragment if list empty
|
||||
|
||||
view = inflater.inflate(R.layout.home_fragment, container, false);
|
||||
|
||||
romsLayout = view.findViewById(R.id.romsLayout);
|
||||
|
||||
refreshRoms = view.findViewById(R.id.refreshRoms);
|
||||
|
||||
refreshRoms.setOnRefreshListener(() -> {
|
||||
loadDataVbi();
|
||||
mMainAdapter.notifyItemRangeChanged(0, mMainAdapter.data.size());
|
||||
refreshRoms.setRefreshing(false);
|
||||
});
|
||||
loadDataVbi();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void loadDataVbi() {
|
||||
data = new ArrayList<>();
|
||||
|
||||
try {
|
||||
|
||||
jArray = new JSONArray(FileUtils.readFromFile(requireActivity(), new File(AppConfig.maindirpath
|
||||
+ "roms-data.json")));
|
||||
|
||||
// Extract data from json and store into ArrayList as class objects
|
||||
for (int i = 0; i < jArray.length(); i++) {
|
||||
JSONObject json_data = jArray.getJSONObject(i);
|
||||
DataMainRoms romsMainData = new DataMainRoms();
|
||||
romsMainData.itemName = json_data.getString("imgName");
|
||||
romsMainData.itemIcon = json_data.getString("imgIcon");
|
||||
try {
|
||||
romsMainData.itemArch = json_data.getString("imgArch");
|
||||
} catch (JSONException ignored) {
|
||||
romsMainData.itemArch = "unknown";
|
||||
}
|
||||
romsMainData.itemPath = json_data.getString("imgPath");
|
||||
try {
|
||||
romsMainData.itemDrv1 = json_data.getString("imgDrv1");
|
||||
} catch (JSONException ignored) {
|
||||
romsMainData.itemDrv1 = "";
|
||||
}
|
||||
romsMainData.itemExtra = json_data.getString("imgExtra");
|
||||
try {
|
||||
if (json_data.getString("imgArch").equals(MainSettingsManager.getArch(requireActivity())))
|
||||
data.add(romsMainData);
|
||||
} catch (JSONException ignored) {
|
||||
data.add(romsMainData);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup and Handover data to recyclerview
|
||||
mRVMainRoms = HomeFragment.view.findViewById(R.id.mRVMainRoms);
|
||||
mMainAdapter = new AdapterMainRoms(requireActivity(), data);
|
||||
mRVMainRoms.setAdapter(mMainAdapter);
|
||||
mRVMainRoms.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||
} catch (JSONException e) {
|
||||
Toast.makeText(requireActivity(), e.toString(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
package com.vectras.vm.MainRoms;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||
import com.vectras.qemu.Config;
|
||||
import com.vectras.vm.VMCreatorActivity;
|
||||
import com.vectras.vm.ExportRomActivity;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.StartVM;
|
||||
import com.vectras.vm.VMManager;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class AdapterMainRoms extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
private final Activity activity;
|
||||
private final Context context;
|
||||
private final LayoutInflater inflater;
|
||||
public List<DataMainRoms> data = Collections.emptyList();
|
||||
int currentPos = 0;
|
||||
|
||||
public AdapterMainRoms(Activity activity, List<DataMainRoms> data) {
|
||||
this.activity = activity;
|
||||
this.context = activity.getApplicationContext();
|
||||
inflater = LayoutInflater.from(context);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
// Inflate the layout when viewholder created
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = inflater.inflate(R.layout.container_main_roms, parent, false);
|
||||
return new MyHolder(view);
|
||||
}
|
||||
|
||||
// Bind data
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int _position) {
|
||||
|
||||
int position = holder.getBindingAdapterPosition();
|
||||
if (position == RecyclerView.NO_POSITION) return;
|
||||
|
||||
// Get current position of item in recyclerview to bind data and assign values from list
|
||||
final MyHolder myHolder = (MyHolder) holder;
|
||||
final DataMainRoms current = data.get(position);
|
||||
myHolder.textName.setText(current.itemName);
|
||||
myHolder.textArch.setText(current.itemArch);
|
||||
if (current.itemIcon.isEmpty()){
|
||||
VMManager.setIconWithName(myHolder.ivIcon, current.itemName);
|
||||
} else {
|
||||
Bitmap bmImg = BitmapFactory.decodeFile(current.itemIcon);
|
||||
myHolder.ivIcon.setImageBitmap(bmImg);
|
||||
}
|
||||
myHolder.optionsBtn.setOnClickListener(view -> {
|
||||
|
||||
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(context);
|
||||
View v = activity.getLayoutInflater().inflate(R.layout.rom_options_dialog, null);
|
||||
bottomSheetDialog.setContentView(v);
|
||||
|
||||
Button modifyRomBtn = v.findViewById(R.id.modifyRomBtn);
|
||||
modifyRomBtn.setOnClickListener(v3 -> {
|
||||
VMCreatorActivity.current = data.get(position);
|
||||
VMManager.setArch(current.itemArch, activity);
|
||||
context.startActivity(new Intent(context, VMCreatorActivity.class).putExtra("POS", position).putExtra("MODIFY", true).putExtra("VMID", current.vmID));
|
||||
bottomSheetDialog.cancel();
|
||||
});
|
||||
|
||||
Button exportRomBtn = v.findViewById(R.id.exportRomBtn);
|
||||
exportRomBtn.setOnClickListener(v2 -> {
|
||||
ExportRomActivity.pendingPosition = position;
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(context.getApplicationContext(), ExportRomActivity.class);
|
||||
context.startActivity(intent);
|
||||
bottomSheetDialog.cancel();
|
||||
});
|
||||
|
||||
Button removeRomBtn = v.findViewById(R.id.removeRomBtn);
|
||||
removeRomBtn.setOnClickListener(v1 -> {
|
||||
VMManager.deleteVMDialog(current.itemName, position, activity);
|
||||
bottomSheetDialog.cancel();
|
||||
});
|
||||
bottomSheetDialog.show();
|
||||
});
|
||||
|
||||
myHolder.cdRoms.setOnClickListener(view -> {
|
||||
VMManager.setArch(current.itemArch, activity);
|
||||
StartVM.cdrompath = current.imgCdrom;
|
||||
if (current.qmpPort == 0) {
|
||||
Config.setDefault();
|
||||
} else {
|
||||
Config.QMPPort = current.qmpPort;
|
||||
}
|
||||
Config.vmID = current.vmID;
|
||||
String env = StartVM.env(activity, current.itemExtra, current.itemPath, false);
|
||||
//MainActivity.startVM(current.itemName, env, current.itemExtra, current.itemPath);
|
||||
});
|
||||
|
||||
myHolder.cdRoms.setOnLongClickListener(v -> {
|
||||
VMManager.deleteVMDialog(current.itemName, position, activity);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// return total item from List
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
static class MyHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
CardView cdRoms;
|
||||
TextView textName, textArch;
|
||||
ImageView ivIcon;
|
||||
ImageButton optionsBtn;
|
||||
|
||||
// create constructor to get widget reference
|
||||
public MyHolder(View itemView) {
|
||||
super(itemView);
|
||||
cdRoms = itemView.findViewById(R.id.cdItem);
|
||||
textName = itemView.findViewById(R.id.textName);
|
||||
textArch = itemView.findViewById(R.id.textArch);
|
||||
ivIcon = itemView.findViewById(R.id.ivIcon);
|
||||
optionsBtn = itemView.findViewById(R.id.optionsButton);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package com.vectras.vm;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
|
|
@ -14,13 +13,8 @@ import android.util.Log;
|
|||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.vectras.qemu.MainVNCActivity;
|
||||
import com.vectras.vm.core.PulseAudio;
|
||||
import com.vectras.vterm.Terminal;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MainService extends Service {
|
||||
public static String CHANNEL_ID = "Vectras VM Service";
|
||||
private static final int NOTIFICATION_ID = 1;
|
||||
|
|
@ -28,6 +22,7 @@ public class MainService extends Service {
|
|||
public static String env = null;
|
||||
private String TAG = "MainService";
|
||||
public static MainService service;
|
||||
public static Context activityContext;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
|
|
@ -49,8 +44,8 @@ public class MainService extends Service {
|
|||
|
||||
if (env != null) {
|
||||
if (service != null) {
|
||||
Terminal vterm = new Terminal(this);
|
||||
vterm.executeShellCommand2(env, true, this);
|
||||
Terminal vterm = new Terminal(activityContext);
|
||||
vterm.executeShellCommand2(env, true, activityContext);
|
||||
}
|
||||
} else
|
||||
Log.e(TAG, "env is null");
|
||||
|
|
|
|||
|
|
@ -1,207 +0,0 @@
|
|||
package com.vectras.vm;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.StrictMode;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.vectras.vm.databinding.ActivityRomStoreBinding;
|
||||
import com.vectras.vm.main.romstore.RomStoreHomeAdapterSearch;
|
||||
import com.vectras.vm.Roms.AdapterRoms;
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
import com.vectras.vm.network.RequestNetwork;
|
||||
import com.vectras.vm.network.RequestNetworkController;
|
||||
import com.vectras.vm.utils.UIUtils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class RomStoreActivity extends AppCompatActivity {
|
||||
|
||||
ActivityRomStoreBinding binding;
|
||||
private RequestNetwork net;
|
||||
private RequestNetwork.RequestListener _net_request_listener;
|
||||
private String contentJSON = "[]";
|
||||
public static String license;
|
||||
private RomStoreHomeAdapterSearch mAdapterSearch;
|
||||
private List<DataRoms> data = new ArrayList<>();
|
||||
private List<DataRoms> dataSearch = new ArrayList<>();
|
||||
public static boolean isFinishNow = false;
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
super.onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
|
||||
StrictMode.setThreadPolicy(policy);
|
||||
|
||||
UIUtils.edgeToEdge(this);
|
||||
binding = ActivityRomStoreBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
UIUtils.setOnApplyWindowInsetsListenerTop(findViewById(R.id.appbar));
|
||||
UIUtils.setOnApplyWindowInsetsListenerBottom(findViewById(R.id.romsRv));
|
||||
UIUtils.setOnApplyWindowInsetsListenerBottom(findViewById(R.id.romsSearch));
|
||||
UIUtils.setOnApplyWindowInsetsListenerBottom(findViewById(R.id.linear_search_emty));
|
||||
|
||||
binding.searchBar.setNavigationOnClickListener(v -> onBackPressed());
|
||||
|
||||
binding.searchView.getEditText().addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
search(s.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence newText, int start, int before, int count) {
|
||||
}
|
||||
});
|
||||
|
||||
net = new RequestNetwork(this);
|
||||
_net_request_listener = new RequestNetwork.RequestListener() {
|
||||
@Override
|
||||
public void onResponse(String tag, String response, HashMap<String, Object> responseHeaders) {
|
||||
if (!response.isEmpty())
|
||||
contentJSON = response;
|
||||
loadData();
|
||||
binding.linearload.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onErrorResponse(String tag, String message) {
|
||||
binding.linearload.setVisibility(View.GONE);
|
||||
binding.linearnothinghere.setVisibility(View.VISIBLE);
|
||||
}
|
||||
};
|
||||
|
||||
binding.buttontryagain.setOnClickListener(v -> {
|
||||
binding.linearload.setVisibility(View.VISIBLE);
|
||||
net.startRequestNetwork(RequestNetworkController.GET,AppConfig.vectrasRaw + "vroms-store.json","",_net_request_listener);
|
||||
});
|
||||
|
||||
net.startRequestNetwork(RequestNetworkController.GET,AppConfig.vectrasRaw + "vroms-store.json","",_net_request_listener);
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (isFinishNow)
|
||||
finish();
|
||||
isFinishNow = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (binding.searchView.isShowing())
|
||||
binding.searchView.hide();
|
||||
else
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private void loadData() {
|
||||
AdapterRoms mAdapter = new AdapterRoms(this, data);
|
||||
binding.romsRv.setAdapter(mAdapter);
|
||||
binding.romsRv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
|
||||
|
||||
mAdapterSearch = new RomStoreHomeAdapterSearch(this, dataSearch);
|
||||
binding.romsSearch.setAdapter(mAdapterSearch);
|
||||
binding.romsSearch.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
|
||||
|
||||
List<DataRoms> dataRoms = new ArrayList<>();
|
||||
|
||||
try {
|
||||
Gson gson = new Gson();
|
||||
Type listType = new TypeToken<List<DataRoms>>() {}.getType();
|
||||
dataRoms = gson.fromJson(contentJSON, listType);
|
||||
} catch (Exception e) {
|
||||
binding.linearload.setVisibility(View.GONE);
|
||||
binding.linearnothinghere.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
data.clear();
|
||||
data.addAll(dataRoms);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
|
||||
dataSearch.clear();
|
||||
dataSearch.addAll(dataRoms);
|
||||
mAdapterSearch.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private void search(String keyword) {
|
||||
try {
|
||||
// Extract data from json and store into ArrayList as class objects
|
||||
Gson gson = new Gson();
|
||||
Type listType = new TypeToken<List<DataRoms>>() {}.getType();
|
||||
List<DataRoms> allData = gson.fromJson(contentJSON, listType);
|
||||
List<DataRoms> filteredData = new ArrayList<>();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
filteredData = allData.stream()
|
||||
.filter(rom -> {
|
||||
String romName = (rom.romName != null) ? rom.romName : "";
|
||||
String romKernel = (rom.romKernel != null) ? rom.romKernel : "";
|
||||
|
||||
return romName.toLowerCase().contains(keyword.toLowerCase())
|
||||
|| romKernel.toLowerCase().contains(keyword.toLowerCase());
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
for (DataRoms rom : allData) {
|
||||
if (rom.romName.toLowerCase().contains(keyword.toLowerCase()) ||
|
||||
rom.romKernel.toLowerCase().contains(keyword.toLowerCase())) {
|
||||
filteredData.add(rom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataSearch.clear();
|
||||
dataSearch.addAll(filteredData);
|
||||
} catch (Exception e) {
|
||||
Log.e("RomManagerActivity", "Json parsing error: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (dataSearch.isEmpty())
|
||||
binding.romsSearch.setVisibility(View.GONE);
|
||||
else
|
||||
binding.romsSearch.setVisibility(View.VISIBLE);
|
||||
|
||||
mAdapterSearch.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
package com.vectras.vm.Roms;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.RomInfo;
|
||||
import com.vectras.vm.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class AdapterRoms extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
Context context;
|
||||
private final LayoutInflater inflater;
|
||||
static List<DataRoms> dataRom = Collections.emptyList();
|
||||
private final String TAG = "AdapterRoms";
|
||||
|
||||
public AdapterRoms(Context context, List<DataRoms> data) {
|
||||
this.context = context;
|
||||
inflater = LayoutInflater.from(context);
|
||||
dataRom = data;
|
||||
}
|
||||
|
||||
// Inflate the layout when viewholder created
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = inflater.inflate(R.layout.container_roms, parent, false);
|
||||
return new MyHolder(view);
|
||||
}
|
||||
|
||||
// Bind data
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
|
||||
|
||||
// Get current position of item in recyclerview to bind data and assign values from list
|
||||
final MyHolder myHolder = (MyHolder) holder;
|
||||
final DataRoms current = dataRom.get(position);
|
||||
Glide.with(context).load(current.romIcon).placeholder(R.drawable.ic_computer_180dp_with_padding).error(R.drawable.ic_computer_180dp_with_padding).into(myHolder.ivIcon);
|
||||
myHolder.textName.setText(current.romName);
|
||||
myHolder.textSize.setText(current.romArch + " - " + current.fileSize);
|
||||
if (current.romAvail) {
|
||||
myHolder.linearItem.setOnClickListener(v -> {
|
||||
notifyItemRangeChanged(0, dataRom.size());
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(context, RomInfo.class);
|
||||
intent.putExtra("title", current.romName);
|
||||
intent.putExtra("shortdesc", current.romSize);
|
||||
intent.putExtra("getrom", current.romUrl);
|
||||
intent.putExtra("desc", current.desc);
|
||||
intent.putExtra("icon", current.romIcon);
|
||||
intent.putExtra("filename", current.romPath);
|
||||
intent.putExtra("finalromfilename", current.finalromfilename);
|
||||
intent.putExtra("extra", current.romExtra);
|
||||
intent.putExtra("arch", current.romArch);
|
||||
intent.putExtra("verified", current.verified);
|
||||
intent.putExtra("creator", current.creator);
|
||||
intent.putExtra("size", current.fileSize);
|
||||
context.startActivity(intent);
|
||||
});
|
||||
} else {
|
||||
myHolder.textAvail.setText(context.getString(R.string.unavailable));
|
||||
myHolder.textAvail.setTextColor(Color.RED);
|
||||
}
|
||||
|
||||
if (dataRom.size() == 1) {
|
||||
myHolder.linearItem.setBackground(AppCompatResources.getDrawable(context, R.drawable.object_shape_single));
|
||||
} else if (position == 0) {
|
||||
myHolder.linearItem.setBackground(AppCompatResources.getDrawable(context, R.drawable.object_shape_top));
|
||||
} else if (position == dataRom.size() - 1) {
|
||||
myHolder.linearItem.setBackground(AppCompatResources.getDrawable(context, R.drawable.object_shape_bottom));
|
||||
} else {
|
||||
myHolder.linearItem.setBackground(AppCompatResources.getDrawable(context, R.drawable.object_shape_middle));
|
||||
}
|
||||
}
|
||||
|
||||
// return total item from List
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return dataRom.size();
|
||||
}
|
||||
|
||||
static class MyHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
TextView textName, textAvail, textSize;
|
||||
ImageView ivIcon;
|
||||
LinearLayout linearItem;
|
||||
|
||||
// create constructor to get widget reference
|
||||
public MyHolder(View itemView) {
|
||||
super(itemView);
|
||||
textName = itemView.findViewById(R.id.textName);
|
||||
ivIcon = itemView.findViewById(R.id.ivIcon);
|
||||
textSize = itemView.findViewById(R.id.textSize);
|
||||
textAvail = itemView.findViewById(R.id.textAvail);
|
||||
|
||||
linearItem = itemView.findViewById(R.id.linearItem);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.vectras.qemu.MainSettingsManager;
|
||||
import com.vectras.vm.Fragment.CreateImageDialogFragment;
|
||||
import com.vectras.vm.MainRoms.DataMainRoms;
|
||||
import com.vectras.vm.main.vms.DataMainRoms;
|
||||
import com.vectras.vm.databinding.ActivityVmCreatorBinding;
|
||||
import com.vectras.vm.databinding.DialogProgressStyleBinding;
|
||||
import com.vectras.vm.main.MainActivity;
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
package com.vectras.vm;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.vectras.vm.main.MainActivity;
|
||||
|
||||
public class WidgetProvider extends AppWidgetProvider {
|
||||
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
// Perform this loop procedure for each widget that belongs to this
|
||||
// provider.
|
||||
for (int i=0; i < appWidgetIds.length; i++) {
|
||||
int appWidgetId = appWidgetIds[i];
|
||||
// Create an Intent to launch ExampleActivity
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ 0,
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
|
||||
);
|
||||
|
||||
// Get the layout for the widget and attach an onClick listener to
|
||||
// the button.
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
|
||||
views.setOnClickPendingIntent(R.id.button, pendingIntent);
|
||||
views.setRemoteAdapter(R.id.mRVMainRoms, intent);
|
||||
// Tell the AppWidgetManager to perform an update on the current app
|
||||
// widget.
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +37,6 @@ import com.google.android.material.floatingactionbutton.ExtendedFloatingActionBu
|
|||
import com.termux.app.TermuxActivity;
|
||||
import com.vectras.qemu.Config;
|
||||
import com.vectras.qemu.MainSettingsManager;
|
||||
import com.vectras.qemu.MainVNCActivity;
|
||||
import com.vectras.vm.AboutActivity;
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.VMCreatorActivity;
|
||||
|
|
@ -53,7 +52,7 @@ import com.vectras.vm.network.RequestNetworkController;
|
|||
import com.vectras.vm.databinding.BottomsheetdialogLoggerBinding;
|
||||
import com.vectras.vm.databinding.UpdateBottomDialogLayoutBinding;
|
||||
import com.vectras.vm.main.romstore.RomStoreHomeAdapterSearch;
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
import com.vectras.vm.main.romstore.DataRoms;
|
||||
import com.vectras.vm.SetArchActivity;
|
||||
import com.vectras.vm.VMManager;
|
||||
import com.vectras.vm.adapter.LogsAdapter;
|
||||
|
|
@ -565,7 +564,7 @@ public class MainActivity extends AppCompatActivity implements RomStoreFragment.
|
|||
@SuppressLint("NotifyDataSetChanged")
|
||||
private void search(String keyword) {
|
||||
try {
|
||||
// Extract data from json and store into ArrayList as class objects
|
||||
// Extract data from JSON and store into ArrayList as class objects
|
||||
List<DataRoms> filteredData = new ArrayList<>();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
|
|
@ -598,7 +597,11 @@ public class MainActivity extends AppCompatActivity implements RomStoreFragment.
|
|||
else
|
||||
binding.rvRomstoresearch.setVisibility(View.VISIBLE);
|
||||
|
||||
adapterRomStoreSearch.notifyDataSetChanged();
|
||||
if (currentSearchMode == SEARCH_ROM_STORE ) {
|
||||
if (adapterRomStoreSearch != null) adapterRomStoreSearch.notifyDataSetChanged();
|
||||
} else {
|
||||
if (adapterSoftwareStoreSearch != null) adapterSoftwareStoreSearch.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void showLogsDialog() {
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ public class MainStartVM {
|
|||
MainService.startCommand(finalCommand, context);
|
||||
} else {
|
||||
Intent serviceIntent = new Intent(context, MainService.class);
|
||||
MainService.activityContext = context;
|
||||
MainService.env = finalCommand;
|
||||
MainService.CHANNEL_ID = vmName;
|
||||
if (SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import android.widget.Button;
|
|||
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||
import com.vectras.vm.VMCreatorActivity;
|
||||
import com.vectras.vm.ExportRomActivity;
|
||||
import com.vectras.vm.MainRoms.DataMainRoms;
|
||||
import com.vectras.vm.main.vms.DataMainRoms;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.VMManager;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.vectras.vm.main.core;
|
||||
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
import com.vectras.vm.main.romstore.DataRoms;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.vectras.vm.Roms;
|
||||
package com.vectras.vm.main.romstore;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
|
|
@ -4,8 +4,6 @@ import androidx.lifecycle.LiveData;
|
|||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import com.google.gson.Gson;
|
|||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.network.RequestNetwork;
|
||||
import com.vectras.vm.network.RequestNetworkController;
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
import com.vectras.vm.databinding.FragmentHomeRomStoreBinding;
|
||||
import com.vectras.vm.main.core.SharedData;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import com.bumptech.glide.Glide;
|
|||
|
||||
import com.vectras.vm.RomInfo;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import com.bumptech.glide.Glide;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.RomInfo;
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
|
|
|||
|
|
@ -16,11 +16,10 @@ import com.google.android.material.transition.MaterialFadeThrough;
|
|||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
import com.vectras.vm.main.romstore.DataRoms;
|
||||
import com.vectras.vm.databinding.FragmentHomeSoftwareStoreBinding;
|
||||
import com.vectras.vm.main.core.SharedData;
|
||||
import com.vectras.vm.main.romstore.RomStoreFragment;
|
||||
import com.vectras.vm.main.romstore.RomStoreHomeAdpater;
|
||||
import com.vectras.vm.network.RequestNetwork;
|
||||
import com.vectras.vm.network.RequestNetworkController;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import com.bumptech.glide.Glide;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.RomInfo;
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
import com.vectras.vm.main.romstore.DataRoms;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import com.bumptech.glide.Glide;
|
|||
|
||||
import com.vectras.vm.RomInfo;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
import com.vectras.vm.main.romstore.DataRoms;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import androidx.lifecycle.LiveData;
|
|||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import com.vectras.vm.Roms.DataRoms;
|
||||
import com.vectras.vm.main.romstore.DataRoms;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.vectras.vm.MainRoms;
|
||||
package com.vectras.vm.main.vms;
|
||||
public class DataMainRoms {
|
||||
public String itemIcon;
|
||||
public String itemName;
|
||||
|
|
@ -2,8 +2,6 @@ package com.vectras.vm.main.vms;
|
|||
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
|
||||
import com.vectras.vm.MainRoms.DataMainRoms;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VmsDiffUtil extends DiffUtil.Callback {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import android.view.ViewGroup;
|
|||
|
||||
import com.google.android.material.transition.MaterialFadeThrough;
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.MainRoms.DataMainRoms;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.VMManager;
|
||||
import com.vectras.vm.databinding.FragmentHomeVmsBinding;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import androidx.recyclerview.widget.DiffUtil;
|
|||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.vectras.qemu.Config;
|
||||
import com.vectras.vm.MainRoms.DataMainRoms;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.StartVM;
|
||||
import com.vectras.vm.VMManager;
|
||||
|
|
|
|||
|
|
@ -1,734 +0,0 @@
|
|||
package com.vectras.vm.setupwizard;
|
||||
|
||||
import static android.content.Intent.ACTION_VIEW;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.termux.app.TermuxActivity;
|
||||
import com.termux.app.TermuxService;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.BaseAdapter;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.vectras.qemu.MainSettingsManager;
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.network.RequestNetwork;
|
||||
import com.vectras.vm.network.RequestNetworkController;
|
||||
import com.vectras.vm.databinding.ActivitySetupWizardBinding;
|
||||
import com.vectras.vm.databinding.SetupQemuAdvancedBinding;
|
||||
import com.vectras.vm.databinding.SetupQemuDoneBinding;
|
||||
import com.vectras.vm.databinding.SimpleLayoutForSpinerBinding;
|
||||
import com.vectras.vm.main.MainActivity;
|
||||
import com.vectras.vm.utils.ClipboardUltils;
|
||||
import com.vectras.vm.utils.DeviceUtils;
|
||||
import com.vectras.vm.utils.DialogUtils;
|
||||
import com.vectras.vm.utils.FileUtils;
|
||||
import com.vectras.vm.utils.JSONUtils;
|
||||
import com.vectras.vm.utils.ListUtils;
|
||||
import com.vectras.vm.utils.UIUtils;
|
||||
import com.vectras.vm.utils.PermissionUtils;
|
||||
import com.vectras.vterm.TerminalBottomSheetDialog;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SetupWizardActivity extends AppCompatActivity {
|
||||
ActivitySetupWizardBinding binding;
|
||||
SetupQemuAdvancedBinding bindingAdvancedSetup;
|
||||
SetupQemuDoneBinding bindingFinalSteps;
|
||||
private final String TAG = "SetupWizardActivity";
|
||||
private boolean isFirstLaunch = false;
|
||||
private boolean libprooterror = false;
|
||||
private RequestNetwork net;
|
||||
private RequestNetwork.RequestListener _net_request_listener;
|
||||
private String contentJSON = "";
|
||||
private HashMap<String, Object> mmap = new HashMap<>();
|
||||
private String bootstrapfilelink = "";
|
||||
private final ArrayList<HashMap<String, String>> listmapForSelectMirrors = new ArrayList<>();
|
||||
private String selectedMirrorCommand = "echo ";
|
||||
private String selectedMirrorLocation = "";
|
||||
private String downloadBootstrapsCommand = "";
|
||||
private boolean aria2Error = false;
|
||||
private boolean isexecutingCommand = false;
|
||||
private boolean isServerError = false;
|
||||
private boolean isManualMode = false;
|
||||
private boolean isAllowCheckPermissions = false;
|
||||
String tarPath;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
UIUtils.edgeToEdge(this);
|
||||
binding = ActivitySetupWizardBinding.inflate(getLayoutInflater());
|
||||
bindingAdvancedSetup = binding.advancedsetup;
|
||||
bindingFinalSteps = binding.finalsteps;
|
||||
setContentView(binding.getRoot());
|
||||
UIUtils.setOnApplyWindowInsetsListener(findViewById(R.id.main));
|
||||
|
||||
setupSpiner();
|
||||
|
||||
tarPath = getExternalFilesDir("data") + "/data.tar.gz";
|
||||
|
||||
binding.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(SetupWizardActivity.this, 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<String, Object> responseHeaders) {
|
||||
binding.linearload.setVisibility(View.GONE);
|
||||
contentJSON = response;
|
||||
if (JSONUtils.isValidFromString(contentJSON)) {
|
||||
mmap.clear();
|
||||
mmap = new Gson().fromJson(contentJSON, new TypeToken<HashMap<String, Object>>() {
|
||||
}.getType());
|
||||
if (mmap.containsKey("arm64-v8a") && mmap.containsKey("amd64")) {
|
||||
if (Build.SUPPORTED_ABIS[0].contains("arm64")) {
|
||||
bootstrapfilelink = Objects.requireNonNull(mmap.get("arm64-v8a")).toString();
|
||||
} else {
|
||||
bootstrapfilelink = Objects.requireNonNull(mmap.get("amd64")).toString();
|
||||
}
|
||||
downloadBootstrapsCommand = " aria2c -x 4 --async-dns=false --disable-ipv6 --check-certificate=false -o setup.tar.gz " + bootstrapfilelink;
|
||||
if (!bootstrapfilelink.isEmpty()) {
|
||||
binding.linearcannotconnecttoserver.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onErrorResponse(String tag, String message) {
|
||||
binding.linearload.setVisibility(View.GONE);
|
||||
}
|
||||
};
|
||||
|
||||
setupOnClick();
|
||||
|
||||
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
if (isexecutingCommand) {
|
||||
if (binding.linearsimplesetupui.getVisibility() == View.GONE)
|
||||
binding.linearsimplesetupui.setVisibility(View.VISIBLE);
|
||||
} else if (bindingAdvancedSetup.lnAdvancedsetup.getVisibility() == View.GONE) {
|
||||
onBackInFinalSteps();
|
||||
} else {
|
||||
setEnabled(false);
|
||||
getOnBackPressedDispatcher().onBackPressed();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
extractSystemFiles();
|
||||
}
|
||||
|
||||
private void extractSystemFiles() {
|
||||
View progressView = LayoutInflater.from(this).inflate(R.layout.dialog_progress_style, null);
|
||||
TextView progress_text = progressView.findViewById(R.id.progress_text);
|
||||
progress_text.setText(getString(R.string.installing));
|
||||
AlertDialog progressDialog = new MaterialAlertDialogBuilder(this, R.style.CenteredDialogTheme)
|
||||
.setView(progressView)
|
||||
.setCancelable(false)
|
||||
.create();
|
||||
progressDialog.show();
|
||||
|
||||
new Thread(() -> {
|
||||
boolean result = SetupFeatureCore.startExtractSystemFiles(this);
|
||||
|
||||
runOnUiThread(() -> {
|
||||
progressDialog.dismiss();
|
||||
|
||||
if (!result) DialogUtils.oneDialog(
|
||||
this,
|
||||
getString(R.string.oops),
|
||||
getString(R.string.system_files_installation_failed_content),
|
||||
getString(R.string.try_again),
|
||||
true,
|
||||
R.drawable.error_96px,
|
||||
false,
|
||||
this::extractSystemFiles,
|
||||
null);
|
||||
});
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
checkpermissions();
|
||||
}
|
||||
|
||||
// Function to append text and automatically scroll to bottom
|
||||
@SuppressLint("SetTextI18n")
|
||||
private void appendTextAndScroll(String textToAdd) {
|
||||
// Update the text
|
||||
bindingAdvancedSetup.tvTerminalOutput.append(textToAdd);
|
||||
|
||||
if (textToAdd.contains("xssFjnj58Id")) {
|
||||
isexecutingCommand = false;
|
||||
binding.linearsimplesetupui.setVisibility(View.GONE);
|
||||
bindingAdvancedSetup.lnAdvancedsetup.setVisibility(View.GONE);
|
||||
} else if (textToAdd.contains("libproot.so --help") || textToAdd.contains("/bin/sh: can't fork:")) {
|
||||
libprooterror = true;
|
||||
} else if (textToAdd.contains("not complete: /root/setup.tar.gz")) {
|
||||
aria2Error = true;
|
||||
} else if (textToAdd.contains("temporary error")) {
|
||||
isServerError = true;
|
||||
}
|
||||
|
||||
if (textToAdd.contains("Starting setup...")) {
|
||||
setTextStatus(getString(R.string.getting_ready_for_you_please_don_t_disconnect_the_network));
|
||||
} else if (textToAdd.contains("fetch http")) {
|
||||
setTextStatus(getString(R.string.connecting_to_mirror_in) + "\n" + selectedMirrorLocation + "...");
|
||||
} else if (textToAdd.contains("Installing packages...")) {
|
||||
setTextStatus(getString(R.string.completed_10_it_won_t_take_long));
|
||||
} else if (textToAdd.contains("(50/")) {
|
||||
setTextStatus(getString(R.string.completed_20_it_won_t_take_long));
|
||||
} else if (textToAdd.contains("100/")) {
|
||||
setTextStatus(getString(R.string.completed_30_it_won_t_take_long));
|
||||
} else if (textToAdd.contains("150/")) {
|
||||
setTextStatus(getString(R.string.completed_40_it_won_t_take_long));
|
||||
} else if (textToAdd.contains("200/")) {
|
||||
setTextStatus(getString(R.string.completed_50_it_won_t_take_long));
|
||||
} else if (textToAdd.contains("Downloading Qemu...")) {
|
||||
setTextStatus(getString(R.string.completed_75_don_t_disconnect));
|
||||
} else if (textToAdd.contains("Installing Qemu...")) {
|
||||
setTextStatus(getString(R.string.keep_it_up));
|
||||
} else if (textToAdd.contains("qemu-system")) {
|
||||
setTextStatus(getString(R.string.completed_95_keep_it_up));
|
||||
} else if (textToAdd.contains("Just a sec...")) {
|
||||
setTextStatus(getString(R.string.almost_there));
|
||||
}
|
||||
|
||||
// Scroll to the bottom
|
||||
bindingAdvancedSetup.scrollView.post(() -> bindingAdvancedSetup.scrollView.fullScroll(ScrollView.FOCUS_DOWN));
|
||||
}
|
||||
|
||||
private void setTextStatus(String content) {
|
||||
bindingAdvancedSetup.title.setText(content.replaceAll("\n", ". "));
|
||||
binding.textviewsettingup.setText(content);
|
||||
}
|
||||
|
||||
private void startSetup() {
|
||||
aria2Error = false;
|
||||
isServerError = false;
|
||||
simpleSetupUIControler(1);
|
||||
uiControllerAdvancedSetup(true);
|
||||
String cmd = selectedMirrorCommand + ";" +
|
||||
" set -e;" +
|
||||
" echo \"Starting setup...\";" +
|
||||
" apk update;" +
|
||||
" echo \"Installing packages...\";" +
|
||||
" apk add " + (DeviceUtils.is64bit() ? AppConfig.neededPkgs() : AppConfig.neededPkgs32bit()) + ";" +
|
||||
" echo \"Downloading Qemu...\";";
|
||||
|
||||
if (isManualMode) {
|
||||
cmd += " tar -xzvf " + tarPath + " -C /;" +
|
||||
" rm " + tarPath + ";" +
|
||||
" chmod 775 /usr/local/bin/*;";
|
||||
} else if (DeviceUtils.is64bit()) {
|
||||
cmd += downloadBootstrapsCommand + ";" +
|
||||
" echo \"Installing Qemu...\";" +
|
||||
" tar -xzvf setup.tar.gz -C /;" +
|
||||
" rm setup.tar.gz;" +
|
||||
" chmod 775 /usr/local/bin/*;";
|
||||
} else {
|
||||
cmd += " apk add qemu-system-x86_64 qemu-system-ppc qemu-system-i386 qemu-system-aarch64" +
|
||||
" qemu-pr-helper qemu-img mesa-dri-gallium;";
|
||||
}
|
||||
|
||||
cmd += " echo \"Just a sec...\";" +
|
||||
" echo export TMPDIR=/tmp >> /etc/profile;" +
|
||||
" mkdir -p $TMPDIR/pulse;" +
|
||||
" 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\"";
|
||||
|
||||
bindingAdvancedSetup.tvCommandsetup.setText(cmd);
|
||||
executeShellCommand(cmd);
|
||||
}
|
||||
|
||||
private void checkpermissions() {
|
||||
if (!isAllowCheckPermissions) return;
|
||||
|
||||
if (PermissionUtils.storagepermission(this, true)) {
|
||||
if (!isFirstLaunch) {
|
||||
isFirstLaunch = true;
|
||||
SetupFeatureCore.checkabi(this);
|
||||
|
||||
if (binding.linearsimplesetupui.getVisibility() == View.GONE) {
|
||||
showAdvancedSetupDialog();
|
||||
}
|
||||
}
|
||||
|
||||
if (DeviceUtils.isStorageLow(this, false)) {
|
||||
DialogUtils.oneDialog(this,
|
||||
getResources().getString(R.string.oops),
|
||||
getResources().getString(R.string.not_enough_storage_to_set_up_content),
|
||||
getResources().getString(R.string.ok),
|
||||
true,
|
||||
R.drawable.warning_48px,
|
||||
true,
|
||||
null,
|
||||
() -> {
|
||||
if (DeviceUtils.isStorageLow(this, false)) finish();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void simpleSetupUIControler(int status) {
|
||||
if (status == 0) {
|
||||
//Before setup.
|
||||
binding.linearstartsetup.setVisibility(View.VISIBLE);
|
||||
binding.linearsettingup.setVisibility(View.GONE);
|
||||
binding.linearsetupfailed.setVisibility(View.GONE);
|
||||
|
||||
File tarGZ = new File(tarPath);
|
||||
if (tarGZ.exists()) {
|
||||
if (!tarGZ.delete()) Log.e(TAG, "simpleSetupUIControler: Unable to delete " + tarPath);
|
||||
}
|
||||
} else if (status == 1) {
|
||||
//Setting up.
|
||||
binding.linearstartsetup.setVisibility(View.GONE);
|
||||
binding.linearsettingup.setVisibility(View.VISIBLE);
|
||||
binding.linearsetupfailed.setVisibility(View.GONE);
|
||||
} else if (status == 2) {
|
||||
//Failed.
|
||||
binding.linearstartsetup.setVisibility(View.GONE);
|
||||
binding.linearsettingup.setVisibility(View.GONE);
|
||||
binding.linearsetupfailed.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private final ActivityResultLauncher<String> bootstrapFilePicker =
|
||||
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
||||
if (uri != null) {
|
||||
String abi = Build.SUPPORTED_ABIS[0];
|
||||
if (FileUtils.getFileNameFromUri(this, uri).endsWith(abi + ".tar.gz")) {
|
||||
simpleSetupUIControler(1);
|
||||
new Thread(() -> {
|
||||
try {
|
||||
setTextStatus(getString(R.string.copying_file));
|
||||
FileUtils.copyFileFromUri(this, uri, tarPath);
|
||||
runOnUiThread(() -> {
|
||||
isManualMode = true;
|
||||
startSetup();
|
||||
MainSettingsManager.setsetUpWithManualSetupBefore(SetupWizardActivity.this, true);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
runOnUiThread(() -> {
|
||||
DialogUtils.oneDialog(this,
|
||||
getString(R.string.oops),
|
||||
getString(R.string.the_file_could_not_be_processed_content),
|
||||
getResources().getString(R.string.ok),
|
||||
true,
|
||||
R.drawable.warning_48px,
|
||||
true,
|
||||
null,
|
||||
() -> {
|
||||
if (binding.linearsimplesetupui.getVisibility() == View.GONE) {
|
||||
showAdvancedSetupDialog();
|
||||
}
|
||||
});
|
||||
simpleSetupUIControler(0);
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
} else {
|
||||
DialogUtils.oneDialog(this,
|
||||
getString(R.string.invalid_file),
|
||||
getString(R.string.please_select) + " vectras-vm-" + abi + ".tar.gz.",
|
||||
getResources().getString(R.string.ok),
|
||||
true,
|
||||
R.drawable.warning_48px,
|
||||
true,
|
||||
null,
|
||||
() -> {
|
||||
if (binding.linearsimplesetupui.getVisibility() == View.GONE) {
|
||||
showAdvancedSetupDialog();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (binding.linearsimplesetupui.getVisibility() == View.GONE) {
|
||||
showAdvancedSetupDialog();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private void onBackInFinalSteps() {
|
||||
if (bindingFinalSteps.lineardonate.getVisibility() == View.GONE) {
|
||||
bindingFinalSteps.lineardonate.setVisibility(View.VISIBLE);
|
||||
} else if (bindingFinalSteps.linearcommunity.getVisibility() == View.GONE) {
|
||||
bindingFinalSteps.linearcommunity.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (bindingFinalSteps.tvLater.getVisibility() == View.GONE) {
|
||||
bindingFinalSteps.tvLater.setVisibility(View.VISIBLE);
|
||||
bindingFinalSteps.btnContinue.setText(getString(R.string.join));
|
||||
}
|
||||
}
|
||||
|
||||
private void setupOnClick() {
|
||||
//Simple setup
|
||||
binding.buttonletstart.setOnClickListener(v -> {
|
||||
binding.linearwelcome.setVisibility(View.GONE);
|
||||
isAllowCheckPermissions = true;
|
||||
checkpermissions();
|
||||
net.startRequestNetwork(RequestNetworkController.GET, AppConfig.bootstrapfileslink, "", _net_request_listener);
|
||||
});
|
||||
|
||||
binding.buttontryconnectagain.setOnClickListener(v -> {
|
||||
binding.linearload.setVisibility(View.VISIBLE);
|
||||
net.startRequestNetwork(RequestNetworkController.GET, AppConfig.bootstrapfileslink, "", _net_request_listener);
|
||||
});
|
||||
|
||||
binding.buttonautosetup.setOnClickListener(v -> {
|
||||
isManualMode = false;
|
||||
startSetup();
|
||||
simpleSetupUIControler(1);
|
||||
});
|
||||
|
||||
binding.buttonmanualsetup.setOnClickListener(v -> bootstrapFilePicker.launch("*/*"));
|
||||
|
||||
binding.buttonsetuptryagain.setOnClickListener(v -> simpleSetupUIControler(0));
|
||||
|
||||
binding.buttonsetupshowlog.setOnClickListener(v -> binding.linearsimplesetupui.setVisibility(View.GONE));
|
||||
|
||||
binding.textviewshowadvancedsetup.setOnClickListener(v -> {
|
||||
binding.linearsimplesetupui.setVisibility(View.GONE);
|
||||
if (binding.linearstartsetup.getVisibility() == View.VISIBLE) {
|
||||
showAdvancedSetupDialog();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//Advanced setup
|
||||
bindingAdvancedSetup.ivClose.setOnClickListener(v -> binding.linearsimplesetupui.setVisibility(View.VISIBLE));
|
||||
|
||||
bindingAdvancedSetup.ivOpenterminal.setOnClickListener(v -> {
|
||||
if (DeviceUtils.is64bit()) {
|
||||
startActivity(new Intent(this, TermuxActivity.class));
|
||||
} else {
|
||||
TerminalBottomSheetDialog VTERM = new TerminalBottomSheetDialog(this);
|
||||
VTERM.showVterm();
|
||||
}
|
||||
});
|
||||
|
||||
bindingAdvancedSetup.btnInstall.setOnClickListener(v -> {
|
||||
File tarGZ = new File(tarPath);
|
||||
if (tarGZ.exists()) {
|
||||
if (!tarGZ.delete()) Log.e(TAG, "btnInstall: Unable to delete " + tarPath);
|
||||
}
|
||||
showAdvancedSetupDialog();
|
||||
});
|
||||
|
||||
bindingAdvancedSetup.ivCopycommandsetup.setOnClickListener(v -> ClipboardUltils.copyToClipboard(SetupWizardActivity.this, bindingAdvancedSetup.tvCommandsetup.getText().toString()));
|
||||
|
||||
|
||||
//Final steps
|
||||
bindingFinalSteps.tvLater.setOnClickListener(v -> {
|
||||
if (bindingFinalSteps.linearcommunity.getVisibility() == View.VISIBLE) {
|
||||
bindingFinalSteps.linearcommunity.setVisibility(View.GONE);
|
||||
} else if (bindingFinalSteps.lineardonate.getVisibility() == View.VISIBLE) {
|
||||
bindingFinalSteps.tvLater.setVisibility(View.GONE);
|
||||
bindingFinalSteps.lineardonate.setVisibility(View.GONE);
|
||||
bindingFinalSteps.btnContinue.setText(getString(R.string.done));
|
||||
}
|
||||
});
|
||||
|
||||
bindingFinalSteps.btnContinue.setOnClickListener(v -> {
|
||||
if (bindingFinalSteps.linearcommunity.getVisibility() == View.VISIBLE) {
|
||||
bindingFinalSteps.linearcommunity.setVisibility(View.GONE);
|
||||
Intent intent = new Intent(ACTION_VIEW, Uri.parse(AppConfig.telegramLink));
|
||||
startActivity(intent);
|
||||
//Don't show join Telegram dialog again
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
SharedPreferences.Editor edit = prefs.edit();
|
||||
edit.putBoolean("tgDialog", true);
|
||||
edit.apply();
|
||||
} else if (bindingFinalSteps.lineardonate.getVisibility() == View.VISIBLE) {
|
||||
bindingFinalSteps.tvLater.setVisibility(View.GONE);
|
||||
bindingFinalSteps.lineardonate.setVisibility(View.GONE);
|
||||
bindingFinalSteps.btnContinue.setText(getString(R.string.done));
|
||||
Intent intent = new Intent(ACTION_VIEW, Uri.parse(AppConfig.patreonLink));
|
||||
startActivity(intent);
|
||||
} else {
|
||||
startActivity(new Intent(SetupWizardActivity.this, MainActivity.class));
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void uiControllerAdvancedSetup(boolean isStartSetup) {
|
||||
bindingAdvancedSetup.lnBntinstall.setVisibility(isStartSetup ? View.GONE : View.VISIBLE);
|
||||
bindingAdvancedSetup.progressBar.setVisibility(isStartSetup ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void showAdvancedSetupDialog() {
|
||||
DialogUtils.twoDialog(
|
||||
this,
|
||||
getResources().getString(R.string.bootstrap_required),
|
||||
getResources().getString(R.string.you_can_choose_between_auto_download_and_setup_or_manual_setup_by_choosing_bootstrap_file),
|
||||
getString(R.string.auto_setup),
|
||||
getString(R.string.manual_setup),
|
||||
true, R.drawable.system_update_24px,
|
||||
false,
|
||||
() -> {
|
||||
//startDownload();
|
||||
isManualMode = false;
|
||||
startSetup();
|
||||
simpleSetupUIControler(1);
|
||||
},
|
||||
() -> bootstrapFilePicker.launch("*/*"),
|
||||
null);
|
||||
}
|
||||
|
||||
private void setupSpiner() {
|
||||
ListUtils.setupMirrorListForListmap(listmapForSelectMirrors);
|
||||
|
||||
binding.spinnerselectmirror.setAdapter(new SpinnerSelectMirrorAdapter(getApplicationContext(), listmapForSelectMirrors));
|
||||
binding.spinnerselectmirror.setSelection(MainSettingsManager.getSelectedMirror(this));
|
||||
}
|
||||
|
||||
public static class SpinnerSelectMirrorAdapter extends BaseAdapter {
|
||||
|
||||
private final ArrayList<HashMap<String, String>> data;
|
||||
private final LayoutInflater inflater;
|
||||
|
||||
public SpinnerSelectMirrorAdapter(Context context, ArrayList<HashMap<String, String>> arr) {
|
||||
this.data = arr;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, String> getItem(int position) {
|
||||
return data.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder holder;
|
||||
|
||||
if (convertView == null) {
|
||||
// Inflate binding only once for each new item
|
||||
SimpleLayoutForSpinerBinding binding =
|
||||
SimpleLayoutForSpinerBinding.inflate(inflater, parent, false);
|
||||
|
||||
// Create ViewHolder to hold binding
|
||||
holder = new ViewHolder(binding);
|
||||
convertView = binding.getRoot();
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
// Get back the saved ViewHolder
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
// Assign data
|
||||
HashMap<String, String> item = data.get(position);
|
||||
holder.binding.textViewLocation.setText(item.get("location"));
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
// ViewHolder holds binding for reuse
|
||||
record ViewHolder(SimpleLayoutForSpinerBinding binding) {
|
||||
}
|
||||
}
|
||||
|
||||
// Method to execute the shell command
|
||||
public void executeShellCommand(String userCommand) {
|
||||
isexecutingCommand = true;
|
||||
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 = getFilesDir().getAbsolutePath();
|
||||
|
||||
File tmpDir = new File(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;
|
||||
runOnUiThread(() -> appendTextAndScroll(outputLine + "\n"));
|
||||
}
|
||||
|
||||
// Read any errors from the error stream
|
||||
while ((line = errorReader.readLine()) != null) {
|
||||
final String errorLine = line;
|
||||
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) {
|
||||
isexecutingCommand = false;
|
||||
// If exit value is not zero, display a toast message
|
||||
if (!aria2Error) {
|
||||
String toastMessage = "Command failed with exit code: " + exitValue;
|
||||
runOnUiThread(() -> {
|
||||
appendTextAndScroll("Error: " + toastMessage + "\n");
|
||||
Toast.makeText(this, toastMessage, Toast.LENGTH_LONG).show();
|
||||
uiControllerAdvancedSetup(false);
|
||||
bindingAdvancedSetup.title.setText(getString(R.string.failed));
|
||||
simpleSetupUIControler(2);
|
||||
});
|
||||
}
|
||||
if (libprooterror) {
|
||||
runOnUiThread(() -> DialogUtils.twoDialog(
|
||||
this,
|
||||
getResources().getString(R.string.oops),
|
||||
getResources().getString(R.string.a_serious_problem_has_occurred),
|
||||
getString(R.string.join_our_community),
|
||||
getString(R.string.close),
|
||||
true, R.drawable.system_update_24px,
|
||||
true,
|
||||
() -> {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_VIEW);
|
||||
intent.setData(Uri.parse(AppConfig.community));
|
||||
startActivity(intent);
|
||||
},
|
||||
null,
|
||||
null));
|
||||
} else if (aria2Error && downloadBootstrapsCommand.contains("aria2c")) {
|
||||
runOnUiThread(() -> {
|
||||
downloadBootstrapsCommand = " curl -o setup.tar.gz -L " + bootstrapfilelink;
|
||||
startSetup();
|
||||
});
|
||||
} else if (isServerError) {
|
||||
runOnUiThread(() -> DialogUtils.oneDialog(
|
||||
this,
|
||||
getResources().getString(R.string.oops),
|
||||
getResources().getString(R.string.unable_to_connect_to_alpine_linux_server_content),
|
||||
getString(R.string.ok),
|
||||
true,
|
||||
R.drawable.warning_48px,
|
||||
true,
|
||||
null,
|
||||
null));
|
||||
}
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
isexecutingCommand = false;
|
||||
// Handle exceptions by printing the stack trace in the terminal output
|
||||
final String errorMessage = e.getMessage();
|
||||
runOnUiThread(() -> {
|
||||
appendTextAndScroll("Error: " + errorMessage + "\n");
|
||||
Toast.makeText(this, "Error executing command: " + errorMessage, Toast.LENGTH_LONG).show();
|
||||
uiControllerAdvancedSetup(false);
|
||||
bindingAdvancedSetup.title.setText(getString(R.string.failed));
|
||||
simpleSetupUIControler(2);
|
||||
});
|
||||
}
|
||||
}).start(); // Execute the command in a separate thread to prevent blocking the UI thread
|
||||
}
|
||||
|
||||
public String getPath(Uri uri) {
|
||||
return FileUtils.getPath(this, uri);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.vectras.vm.utils;
|
|||
|
||||
import static android.content.Intent.ACTION_VIEW;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
|
@ -31,6 +32,8 @@ public class DialogUtils {
|
|||
}
|
||||
|
||||
public static void oneDialog(Context context, String _title, String _message, String _textPositiveButton, boolean _isicon, int _iconid, boolean _cancel, Runnable _onPositive, Runnable _onDismiss) {
|
||||
if (!isAllowShow(context)) return;
|
||||
|
||||
View buttonsView = LayoutInflater.from(context).inflate(R.layout.dialog_layout, null);
|
||||
|
||||
AlertDialog dialog = new AlertDialog.Builder(context).create();
|
||||
|
|
@ -89,6 +92,8 @@ public class DialogUtils {
|
|||
}
|
||||
|
||||
public static void twoDialog(Context context, String _title, String _message, String _textPositiveButton, String _textNegativeButton, boolean _isicon, int _iconid, boolean _cancel, Runnable _onPositive, Runnable _onNegative, Runnable _onDismiss) {
|
||||
if (!isAllowShow(context)) return;
|
||||
|
||||
View buttonsView = LayoutInflater.from(context).inflate(R.layout.dialog_layout, null);
|
||||
|
||||
AlertDialog dialog = new AlertDialog.Builder(context).create();
|
||||
|
|
@ -156,6 +161,8 @@ public class DialogUtils {
|
|||
}
|
||||
|
||||
public static void threeDialog(Context context, String _title, String _message, String _textPositiveButton, String _textNegativeButton, String _textNeutralButton, boolean _isicon, int _iconid, boolean _cancel, Runnable _onPositive, Runnable _onNegative, Runnable _onNeutral, Runnable _onDismiss) {
|
||||
if (!isAllowShow(context)) return;
|
||||
|
||||
View buttonsView = LayoutInflater.from(context).inflate(R.layout.dialog_layout, null);
|
||||
|
||||
AlertDialog dialog = new AlertDialog.Builder(context).create();
|
||||
|
|
@ -232,6 +239,10 @@ public class DialogUtils {
|
|||
dialog.show();
|
||||
}
|
||||
|
||||
public static boolean isAllowShow(Context context) {
|
||||
return context instanceof Activity;
|
||||
}
|
||||
|
||||
public static void joinTelegram(Context _context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(_context);
|
||||
if (!prefs.getBoolean("tgDialog", false)) {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public class LibraryChecker {
|
|||
.setMessage("The following libraries are missing:\n\n" + missingLibraries)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("Install", (dialog, which) -> {
|
||||
// Create the install command
|
||||
// Create the installation command
|
||||
String installCommand = "apk add " + missingLibraries.replace("\n", " ");
|
||||
new Terminal(context).executeShellCommand(installCommand, true, true, activity);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.vectras.vterm;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
|
@ -26,10 +24,7 @@ import java.net.NetworkInterface;
|
|||
import java.net.SocketException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.vectras.qemu.MainVNCActivity;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.VMManager;
|
||||
import com.vectras.vm.AppConfig;
|
||||
|
|
@ -57,8 +52,8 @@ public class Terminal {
|
|||
NetworkInterface intf = en.nextElement();
|
||||
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
|
||||
InetAddress inetAddress = enumIpAddr.nextElement();
|
||||
if (!inetAddress.isLoopbackAddress() && inetAddress.getHostAddress().toString().contains(".")) {
|
||||
return inetAddress.getHostAddress().toString();
|
||||
if (!inetAddress.isLoopbackAddress() && Objects.requireNonNull(inetAddress.getHostAddress()).contains(".")) {
|
||||
return inetAddress.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -187,7 +182,7 @@ public class Terminal {
|
|||
com.vectras.vm.logger.VectrasStatus.logError("<font color='#4db6ac'>VTERM: >" + userCommand + "</font>");
|
||||
new Thread(() -> {
|
||||
try {
|
||||
// Setup the qemuProcess builder to start PRoot with environmental variables and commands
|
||||
// Set up the qemuProcess builder to start PRoot with environmental variables and commands
|
||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
|
||||
// Adjust these environment variables as necessary for your app
|
||||
|
|
@ -264,13 +259,11 @@ public class Terminal {
|
|||
int exitCode = qemuProcess.waitFor(); // Wait for the process to finish
|
||||
if (exitCode == 0) {
|
||||
output.append("Execution finished successfully.\n");
|
||||
output.append(reader.readLine()).append("\n");
|
||||
Log.i(TAG, reader.readLine());
|
||||
} else {
|
||||
output.append("Execution finished with exit code: ").append(exitCode).append("\n");
|
||||
output.append(reader.readLine()).append("\n");
|
||||
Log.i(TAG, reader.readLine());
|
||||
}
|
||||
output.append(reader.readLine()).append("\n");
|
||||
Log.i(TAG, reader.readLine());
|
||||
} catch (IOException | InterruptedException e) {
|
||||
output.append(e.getMessage());
|
||||
errors.append(Log.getStackTraceString(e));
|
||||
|
|
@ -367,109 +360,6 @@ public class Terminal {
|
|||
return output.toString();
|
||||
}
|
||||
|
||||
public void extractQemuVersion(String userCommand, boolean showResultDialog, Activity dialogActivity, CommandCallback callback) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
StringBuilder errors = new StringBuilder();
|
||||
Log.d(TAG, userCommand);
|
||||
com.vectras.vm.logger.VectrasStatus.logError("<font color='#4db6ac'>VTERM: >" + userCommand + "</font>");
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
// Process setup (same as your original code)
|
||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
|
||||
String filesDir = Objects.requireNonNull(context.getFilesDir().getAbsolutePath());
|
||||
File tmpDir = new File(Objects.requireNonNull(context.getFilesDir()), "usr/tmp");
|
||||
|
||||
processBuilder.environment().put("PROOT_TMP_DIR", tmpDir.getAbsolutePath());
|
||||
processBuilder.environment().put("HOME", "/root");
|
||||
processBuilder.environment().put("USER", user);
|
||||
processBuilder.environment().put("TERM", "xterm-256color");
|
||||
processBuilder.environment().put("TMPDIR", "/tmp");
|
||||
processBuilder.environment().put("SHELL", "/bin/sh");
|
||||
processBuilder.environment().put("DISPLAY", DISPLAY);
|
||||
processBuilder.environment().put("PULSE_SERVER", "127.0.0.1");
|
||||
processBuilder.environment().put("XDG_RUNTIME_DIR", "${TMPDIR}");
|
||||
processBuilder.environment().put("SDL_VIDEODRIVER", "x11");
|
||||
|
||||
String[] prootCommand = {
|
||||
TermuxService.PREFIX_PATH + "/bin/proot",
|
||||
"--kill-on-exit",
|
||||
"--link2symlink",
|
||||
"-0",
|
||||
"-r", filesDir + "/distro",
|
||||
"-b", "/dev",
|
||||
"-b", "/proc",
|
||||
"-b", "/sys",
|
||||
"-b", AppConfig.internalDataDirPath + "distro/root:/dev/shm",
|
||||
"-b", "/sdcard",
|
||||
"-b", "/storage",
|
||||
"-b", "/data",
|
||||
"-b", AppConfig.internalDataDirPath + "usr/tmp:/tmp",
|
||||
"-w", "/root",
|
||||
"/bin/sh",
|
||||
"--login"
|
||||
};
|
||||
|
||||
processBuilder.command(prootCommand);
|
||||
qemuProcess = processBuilder.start();
|
||||
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(qemuProcess.getOutputStream()));
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(qemuProcess.getInputStream()));
|
||||
BufferedReader errorReader = new BufferedReader(new InputStreamReader(qemuProcess.getErrorStream()));
|
||||
|
||||
writer.write(userCommand);
|
||||
writer.newLine();
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
output.append(line).append("\n");
|
||||
}
|
||||
|
||||
while ((line = errorReader.readLine()) != null) {
|
||||
errors.append(line).append("\n");
|
||||
}
|
||||
|
||||
reader.close();
|
||||
errorReader.close();
|
||||
|
||||
qemuProcess.waitFor();
|
||||
|
||||
} catch (IOException | InterruptedException e) {
|
||||
output.append(e.getMessage());
|
||||
errors.append(Log.getStackTraceString(e));
|
||||
} finally {
|
||||
String finalOutput = output.toString();
|
||||
String finalErrors = errors.toString();
|
||||
|
||||
// Extract version using regex
|
||||
String version = extractVersion(finalOutput);
|
||||
|
||||
// Run callback on main thread
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
if (callback != null) {
|
||||
callback.onCommandCompleted(version != null ? version : finalOutput, finalErrors);
|
||||
}
|
||||
if (showResultDialog) {
|
||||
showDialog(finalOutput.isEmpty() ? finalErrors : finalOutput, dialogActivity, userCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private String extractVersion(String output) {
|
||||
String regex = "QEMU emulator version ([\\d.]+)";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(output);
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1); // Return the version number
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public interface CommandCallback {
|
||||
void onCommandCompleted(String output, String errors);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,135 +0,0 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
app:liftOnScrollColor="@android:color/transparent"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior">
|
||||
|
||||
<com.google.android.material.search.SearchBar
|
||||
android:id="@+id/search_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:hint="@string/search"
|
||||
app:defaultMarginsEnabled="true"
|
||||
app:layout_collapseMode="pin"
|
||||
app:navigationIcon="@drawable/arrow_back_24px" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/romsRv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:fillViewport="true"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<com.google.android.material.search.SearchView
|
||||
android:id="@+id/searchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:hint="@string/search"
|
||||
app:layout_anchor="@id/search_bar">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear_search_emty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/search_96px" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/no_matching_results_found" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/romsSearch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurfaceContainerHigh"
|
||||
android:paddingVertical="8dp"
|
||||
android:clipToPadding="false"/>
|
||||
</com.google.android.material.search.SearchView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearload"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible">
|
||||
|
||||
<com.google.android.material.loadingindicator.LoadingIndicator
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textviewsettingup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/just_a_moment" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearnothinghere"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/cloud_off_96px" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/oops"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/unable_to_connect_to_server" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/buttontryagain"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:padding="8dp"
|
||||
android:text="@string/try_again" />
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
@ -1,303 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearwelcome"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"
|
||||
android:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/vectrasvm200" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:text="@string/welcome"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:text="@string/welcome_to_vectras_vm_lets_get_started" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/buttonletstart"
|
||||
style="@style/Widget.Material3Expressive.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:padding="8dp"
|
||||
android:text="@string/letstart" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearload"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible">
|
||||
|
||||
<com.google.android.material.loadingindicator.LoadingIndicator
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textviewconnecting"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/just_a_moment" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearcannotconnecttoserver"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/cloud_off_96px" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/oops"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/unable_to_connect_to_server" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/buttontryconnectagain"
|
||||
style="@style/Widget.Material3Expressive.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:padding="8dp"
|
||||
android:text="@string/try_again" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearsimplesetupui"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearstartsetup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:text="@string/start_setup"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:text="@string/do_you_want_to_set_it_up_automatically_or_select_the_bootstrap_file_manually" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear5"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/buttonautosetup"
|
||||
style="@style/Widget.Material3Expressive.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="4dp"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:padding="8dp"
|
||||
android:text="@string/auto_setup" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/buttonmanualsetup"
|
||||
style="@style/Widget.Material3Expressive.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:padding="8dp"
|
||||
android:text="@string/manual" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear6"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/do_you_want_to_change_the_mirror_before_setting_up_the_current_mirror_is" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerselectmirror"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:spinnerMode="dialog"
|
||||
tools:listitem="@layout/simple_layout_for_spiner" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearsettingup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<com.google.android.material.loadingindicator.LoadingIndicator
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textviewsettingup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/getting_ready_for_you" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearsetupfailed"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview5"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:text="@string/failed"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview6"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:text="@string/something_went_wrong_during_setup_would_you_like_to_try_again" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear8"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/buttonsetuptryagain"
|
||||
style="@style/Widget.Material3Expressive.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="4dp"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:padding="8dp"
|
||||
android:text="@string/try_again" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/buttonsetupshowlog"
|
||||
style="@style/Widget.Material3Expressive.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:padding="8dp"
|
||||
android:text="@string/show_log" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textviewshowadvancedsetup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:text="@string/show_advanced_setup" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/advancedsetup"
|
||||
layout="@layout/setup_qemu_advanced" />
|
||||
|
||||
<include
|
||||
android:id="@+id/finalsteps"
|
||||
layout="@layout/setup_qemu_done" />
|
||||
</LinearLayout>
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/romsLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/refreshRoms"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/mRVMainRoms"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.0"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/container_main_roms" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/imported_roms_will_be_shown_here"
|
||||
android:gravity="center" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -5,11 +5,11 @@
|
|||
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
|
||||
"Message": "<h2>3.5.0</h2>\n3dfx is back!",
|
||||
"cancellable": true,
|
||||
"versionCodeBeta":"59",
|
||||
"versionNameBeta":"3.5.5",
|
||||
"versionNameBetas":"3.0.0,3.1.0,3.2.1,3.2.2,3.2.3,3.2.4,3.2.5,3.2.6,3.2.7,3.2.8,3.2.9,3.2.10,3.3.1,3.3.2,3.3.3,3.3.4,3.3.5,3.3.6,3.3.7,3.3.8,3.3.9,3.4.1,3.4.2,3.4.3,3.4.4,3.4.5,3.4.6,3.4.7,3.4.8,3.4.9,3.5.1,3.5.2,3.5.3,3.5.4,3.5.5",
|
||||
"versionCodeBeta":"60",
|
||||
"versionNameBeta":"3.5.6",
|
||||
"versionNameBetas":"3.0.0,3.1.0,3.2.1,3.2.2,3.2.3,3.2.4,3.2.5,3.2.6,3.2.7,3.2.8,3.2.9,3.2.10,3.3.1,3.3.2,3.3.3,3.3.4,3.3.5,3.3.6,3.3.7,3.3.8,3.3.9,3.4.1,3.4.2,3.4.3,3.4.4,3.4.5,3.4.6,3.4.7,3.4.8,3.4.9,3.5.1,3.5.2,3.5.3,3.5.4,3.5.5,3.5.6",
|
||||
"sizeBeta": "46 MB",
|
||||
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
|
||||
"MessageBeta": "<h2>3.5.5</h2>Bugs fixed.",
|
||||
"MessageBeta": "<h2>3.5.6</h2>Bugs fixed.",
|
||||
"cancellableBeta": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,21 +126,21 @@
|
|||
"id": ""
|
||||
},
|
||||
{
|
||||
"rom_name": "VMware SVGA 3D",
|
||||
"rom_icon": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Vmware_workstation_16_icon.svg/2051px-Vmware_workstation_16_icon.svg.png",
|
||||
"rom_url": "https://archive.org/details/vmware-drivers-x-64-for-video-wddm",
|
||||
"rom_path": "VMware_Drivers_x64_for_video_wddm.iso",
|
||||
"rom_name": "Half-Life 2",
|
||||
"rom_icon": "https://upload.wikimedia.org/wikipedia/en/thumb/2/25/Half-Life_2_cover.jpg/250px-Half-Life_2_cover.jpg",
|
||||
"rom_url": "https://archive.org/details/half-life-2_202512",
|
||||
"rom_path": "Half Life 2.iso",
|
||||
"rom_avail": true,
|
||||
"rom_size": "8.15.1.50 x64",
|
||||
"rom_size": "2004",
|
||||
"rom_arch": "X86_64",
|
||||
"rom_kernel": "",
|
||||
"rom_extra": "",
|
||||
"final_rom_file_name": "",
|
||||
"desc": "VMware SVGA 3D is a virtual graphics adapter and driver for VMware virtual machines (VMs), enabling 2D/3D acceleration (DirectX 9.0c, OpenGL 2.1+) for better guest OS performance, higher resolutions, and smoother graphics, installed via VMware Tools. It replaces basic VGA, offers dynamic switching between software/hardware rendering, and provides features like increased VRAM (up to 8GB for modern guests).",
|
||||
"file_size": "33 MB",
|
||||
"desc": "Half-Life 2 is a 2004 first-person shooter game developed and published by Valve Corporation. It was published for Windows on Valve's digital distribution service, Steam. Like the original Half-Life (1998), Half-Life 2 is played from a first-person perspective, combining combat, puzzles, and storytelling. It adds features such as vehicles and physics-based gameplay. The player controls Gordon Freeman, who joins a resistance effort to liberate Earth from the alien Combine empire.",
|
||||
"file_size": "2 GB",
|
||||
"creator": "tokaevUser",
|
||||
"verified": true,
|
||||
"vecid": "vmwaredriversx64forvideowddmiso",
|
||||
"vecid": "halflife2iso",
|
||||
"id": ""
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue