mirror of
https://github.com/xoureldeen/Vectras-VM-Android.git
synced 2026-04-29 23:09:48 +00:00
1678 lines
65 KiB
Java
1678 lines
65 KiB
Java
package com.vectras.vm;
|
|
|
|
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
|
|
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
|
|
import static android.Manifest.permission.POST_NOTIFICATIONS;
|
|
import static android.content.Intent.ACTION_OPEN_DOCUMENT;
|
|
import static android.os.Build.VERSION.SDK_INT;
|
|
|
|
import android.androidVNC.RfbProto;
|
|
import android.androidVNC.VncCanvas;
|
|
import android.animation.ObjectAnimator;
|
|
import android.animation.ValueAnimator;
|
|
import android.annotation.SuppressLint;
|
|
import android.app.Activity;
|
|
import android.app.ActivityManager;
|
|
import android.app.Dialog;
|
|
import android.app.NotificationManager;
|
|
import android.app.ProgressDialog;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.content.SharedPreferences;
|
|
import android.content.pm.PackageInfo;
|
|
import android.content.pm.PackageManager;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.BitmapFactory;
|
|
import android.graphics.Color;
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
import android.net.Uri;
|
|
import android.os.AsyncTask;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.Environment;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.os.StrictMode;
|
|
import android.preference.PreferenceManager;
|
|
import android.provider.DocumentsContract;
|
|
import android.text.Html;
|
|
import android.util.Log;
|
|
import android.view.KeyEvent;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.Window;
|
|
import android.view.WindowManager;
|
|
import android.widget.Button;
|
|
import android.widget.EditText;
|
|
import android.widget.ImageView;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.ProgressBar;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.appcompat.app.ActionBarDrawerToggle;
|
|
import androidx.appcompat.app.AlertDialog;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import androidx.appcompat.widget.Toolbar;
|
|
import androidx.core.app.ActivityCompat;
|
|
import androidx.core.content.ContextCompat;
|
|
import androidx.core.view.GravityCompat;
|
|
import androidx.drawerlayout.widget.DrawerLayout;
|
|
import androidx.fragment.app.Fragment;
|
|
import androidx.fragment.app.FragmentManager;
|
|
import androidx.fragment.app.FragmentPagerAdapter;
|
|
import androidx.recyclerview.widget.GridLayoutManager;
|
|
import androidx.vectordrawable.graphics.drawable.ArgbEvaluator;
|
|
import androidx.viewpager.widget.ViewPager;
|
|
|
|
import com.google.android.gms.ads.LoadAdError;
|
|
import com.google.android.gms.ads.MobileAds;
|
|
import com.google.android.gms.ads.initialization.InitializationStatus;
|
|
import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
|
|
import com.google.android.gms.ads.interstitial.InterstitialAd;
|
|
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
|
|
import com.google.android.material.button.MaterialButton;
|
|
import com.google.android.material.elevation.SurfaceColors;
|
|
import com.google.android.material.textfield.TextInputEditText;
|
|
import com.google.firebase.auth.FirebaseAuth;
|
|
import com.google.firebase.auth.FirebaseUser;
|
|
import com.vectras.qemu.Config;
|
|
import com.vectras.qemu.MainSDLActivity;
|
|
import com.vectras.qemu.MainService;
|
|
import com.vectras.qemu.MainSettingsManager;
|
|
import com.vectras.qemu.jni.StartVM;
|
|
import com.vectras.qemu.utils.FileUtils;
|
|
import com.vectras.qemu.utils.Machine;
|
|
import com.vectras.qemu.utils.QmpClient;
|
|
import com.vectras.vm.Fragment.HomeFragment;
|
|
import com.vectras.vm.Fragment.LoggerFragment;
|
|
import com.vectras.vm.MainRoms.AdapterMainRoms;
|
|
import com.vectras.vm.logger.VectrasStatus;
|
|
import com.vectras.vm.ui.login.VerifyEmailActivity;
|
|
import com.vectras.vm.utils.AppUpdater;
|
|
import com.vectras.qemu.utils.FileInstaller;
|
|
import com.vectras.qemu.utils.RamInfo;
|
|
import com.google.android.gms.ads.AdRequest;
|
|
import com.google.android.gms.ads.AdView;
|
|
import com.google.android.material.appbar.AppBarLayout;
|
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
|
import com.google.android.material.navigation.NavigationView;
|
|
import com.vectras.vm.utils.UIUtils;
|
|
|
|
import org.json.JSONException;
|
|
import org.json.JSONObject;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.net.InetAddress;
|
|
import java.net.NetworkInterface;
|
|
import java.net.SocketException;
|
|
import java.util.Enumeration;
|
|
import java.util.Objects;
|
|
import java.util.TimerTask;
|
|
import java.util.Timer;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
|
|
public class MainActivity extends AppCompatActivity {
|
|
|
|
public static String curRomName;
|
|
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
|
|
public static final String TAG = "Main Activity";
|
|
// Static
|
|
public static final String CREDENTIAL_SHARED_PREF = "settings_prefs";
|
|
|
|
public static MainActivity activity = null;
|
|
//private FirebaseAuth mAuth;
|
|
public DrawerLayout mainDrawer;
|
|
public Toolbar mainToolbar;
|
|
public static TextView totalRam;
|
|
public static TextView usedRam;
|
|
public static TextView freeRam;
|
|
public static TextView ipTxt;
|
|
private Timer _timer = new Timer();
|
|
private TimerTask t;
|
|
public ViewPager viewPager;
|
|
MenuItem prevMenuItem;
|
|
int pager_number = 2;
|
|
private InterstitialAd mInterstitialAd;
|
|
private AdRequest adRequest;
|
|
public static AppBarLayout appbar;
|
|
|
|
public static void UIAlert(String title, String body, Activity activity) {
|
|
AlertDialog ad;
|
|
ad = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create();
|
|
ad.setTitle(title);
|
|
ad.setMessage(body);
|
|
ad.setCancelable(false);
|
|
ad.setButton(Dialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
return;
|
|
}
|
|
});
|
|
ad.show();
|
|
}
|
|
|
|
/**
|
|
* Called when the activity is first created.
|
|
*/
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
activity = this;
|
|
clearNotifications();
|
|
setupFolders();
|
|
setupStrictMode();
|
|
execTimer();
|
|
checkAndLoadLibs();
|
|
activity = this;
|
|
this.setContentView(R.layout.main);
|
|
this.setupWidgets();
|
|
initNavigationMenu();
|
|
FileInstaller.installFiles(activity, false);
|
|
getWindow().setNavigationBarColor(SurfaceColors.SURFACE_2.getColor(this));
|
|
requestPermissions();
|
|
//updateApp(true);
|
|
//mAuth = FirebaseAuth.getInstance();
|
|
}
|
|
|
|
//ANDROID 14 FIX BY SENZ
|
|
private void requestPermissions() {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
if (ContextCompat.checkSelfPermission(this, POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
|
|
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this, R.style.MainDialogTheme);
|
|
alertDialog.setTitle(R.string.permission_title);
|
|
alertDialog.setMessage(R.string.permission_notification_text);
|
|
alertDialog.setPositiveButton("ALLOW", new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface, int i) {
|
|
ActivityCompat.requestPermissions(MainActivity.this, new String[]{POST_NOTIFICATIONS}, 11003);
|
|
}
|
|
});
|
|
alertDialog.create().show();
|
|
} else {
|
|
ActivityCompat.shouldShowRequestPermissionRationale(this, POST_NOTIFICATIONS);
|
|
}
|
|
if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
|
ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION}, 11003);
|
|
} else {
|
|
ActivityCompat.shouldShowRequestPermissionRationale(this, ACCESS_FINE_LOCATION);
|
|
}
|
|
if (ContextCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
|
ActivityCompat.requestPermissions(this, new String[]{ACCESS_COARSE_LOCATION}, 11003);
|
|
} else {
|
|
ActivityCompat.shouldShowRequestPermissionRationale(this, ACCESS_COARSE_LOCATION);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static PackageInfo getAppInfo(Context context) {
|
|
try {
|
|
return context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
|
} catch (PackageManager.NameNotFoundException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
public void updateApp(final boolean showDialog) {
|
|
new AppUpdater(this, new AppUpdater.OnUpdateListener() {
|
|
@Override
|
|
public void onUpdateListener(String result) {
|
|
try {
|
|
if (!result.contains("Error on getting data")) {
|
|
final JSONObject obj = new JSONObject(result);
|
|
PackageInfo pinfo = getAppInfo(getApplicationContext());
|
|
int versionCode = pinfo.versionCode;
|
|
if (versionCode < obj.getInt("versionCode")) {
|
|
AlertDialog.Builder alert = new AlertDialog.Builder(activity, R.style.MainDialogTheme);
|
|
alert.setTitle("Install the latest version")
|
|
.setMessage(Html.fromHtml(obj.getString("Message") + "<br><br>update size:<br>" + obj.getString("size")))
|
|
.setCancelable(obj.getBoolean("cancellable"))
|
|
.setNegativeButton("Update", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
try {
|
|
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(obj.getString("url"))));
|
|
} catch (JSONException e) {
|
|
|
|
}
|
|
}
|
|
}).show();
|
|
|
|
}
|
|
} else if (result.contains("Error on getting data") && showDialog) {
|
|
errorUpdateDialog(result);
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}).start(showDialog);
|
|
}
|
|
|
|
private void errorUpdateDialog(String error) {
|
|
VectrasStatus.logInfo(String.format(error));
|
|
}
|
|
|
|
private MenuItem vectrasInfo;
|
|
|
|
@Override
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
// Inflate the menu; this adds items to the action bar if it is present.
|
|
getMenuInflater().inflate(R.menu.home_toolbar_menu, menu);
|
|
vectrasInfo = menu.findItem(R.id.vectrasInfo);
|
|
return true;
|
|
|
|
}
|
|
|
|
@Override
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
// Menu items
|
|
int id = item.getItemId();
|
|
if (id == R.id.vectrasInfo) {
|
|
appbar = findViewById(R.id.appbar);
|
|
if (appbar.getTop() < 0)
|
|
appbar.setExpanded(true);
|
|
else
|
|
appbar.setExpanded(false);
|
|
|
|
} else if (id == R.id.installRoms) {
|
|
startActivity(new Intent(activity, RomsManagerActivity.class));
|
|
} else if (id == R.id.arch) {
|
|
startActivity(new Intent(activity, SetArchActivity.class));
|
|
}
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
}
|
|
|
|
private void initNavigationMenu() {
|
|
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bNav);
|
|
|
|
bottomNavigationView
|
|
.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
|
|
@Override
|
|
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
|
int id = item.getItemId();
|
|
if (id == R.id.menu_home) {
|
|
viewPager.setCurrentItem(0);
|
|
} else if (id == R.id.menu_logger) {
|
|
viewPager.setCurrentItem(1);
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
public class MyAdapter extends FragmentPagerAdapter {
|
|
|
|
MyAdapter(FragmentManager fm) {
|
|
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
|
}
|
|
|
|
@Override
|
|
public Fragment getItem(int position) {
|
|
|
|
switch (position) {
|
|
case 0:
|
|
return new HomeFragment();
|
|
case 1:
|
|
return new LoggerFragment();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public int getCount() {
|
|
return pager_number;
|
|
}
|
|
}
|
|
|
|
public static LinearLayout extVncLayout;
|
|
public MaterialButton stopBtn;
|
|
FirebaseAuth mAuth;
|
|
FirebaseUser mCurrentUser;
|
|
|
|
// Setting up the UI
|
|
public void setupWidgets() {
|
|
extVncLayout = findViewById(R.id.extVnc);
|
|
stopBtn = findViewById(R.id.stopBtn);
|
|
stopBtn.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
onStopButton(true);
|
|
}
|
|
});
|
|
viewPager = findViewById(R.id.viewPager);
|
|
viewPager.setAdapter(new MyAdapter(getSupportFragmentManager()));
|
|
viewPager.setOffscreenPageLimit(pager_number);
|
|
final BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bNav);
|
|
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
|
@Override
|
|
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
|
}
|
|
|
|
@Override
|
|
public void onPageSelected(int position) {
|
|
if (prevMenuItem != null) {
|
|
prevMenuItem.setChecked(false);
|
|
} else {
|
|
bottomNavigationView.getMenu().getItem(0).setChecked(false);
|
|
}
|
|
bottomNavigationView.getMenu().getItem(position).setChecked(true);
|
|
prevMenuItem = bottomNavigationView.getMenu().getItem(position);
|
|
}
|
|
|
|
@Override
|
|
public void onPageScrollStateChanged(int state) {
|
|
|
|
}
|
|
});
|
|
|
|
appbar = findViewById(R.id.appbar);
|
|
appbar.setExpanded(false);
|
|
mainToolbar = (Toolbar) findViewById(R.id.toolbar);
|
|
setSupportActionBar(mainToolbar);
|
|
mainDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
|
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mainDrawer, mainToolbar,
|
|
R.string.navigation_drawer_open, R.string.navigation_drawer_close);
|
|
mainDrawer.setDrawerListener(toggle);
|
|
toggle.syncState();
|
|
|
|
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
|
|
|
|
View headerView = navigationView.getHeaderView(0);
|
|
mAuth = FirebaseAuth.getInstance();
|
|
mCurrentUser = mAuth.getCurrentUser();
|
|
assert mCurrentUser != null;
|
|
String name = mCurrentUser.getDisplayName();
|
|
String email = mCurrentUser.getEmail();
|
|
Uri picture = mCurrentUser.getPhotoUrl();
|
|
TextView navUsername = (TextView) headerView.findViewById(R.id.usernameTxt);
|
|
navUsername.setText(name);
|
|
TextView navEmail = (TextView) headerView.findViewById(R.id.emailTxt);
|
|
navEmail.setText(email);
|
|
TextView viewProfile = (TextView) headerView.findViewById(R.id.viewProfile);
|
|
TextView appNameTxt = (TextView) headerView.findViewById(R.id.appNameTxt);
|
|
|
|
/*ObjectAnimator rgbAnim=ObjectAnimator.ofObject(navUsername,"textColor",new ArgbEvaluator(), Color.RED,Color.GREEN,Color.BLUE);
|
|
rgbAnim.setDuration(500);
|
|
rgbAnim.setRepeatMode(ValueAnimator.REVERSE);
|
|
rgbAnim.setRepeatCount(ValueAnimator.INFINITE);
|
|
rgbAnim.start();*/
|
|
ImageView ivProfile = (ImageView) headerView.findViewById(R.id.profilePic2);
|
|
|
|
viewProfile.setOnClickListener(new View.OnClickListener() {
|
|
public void onClick(View view) {
|
|
|
|
startActivity(new Intent(activity, ProfileActivity.class));
|
|
|
|
}
|
|
});
|
|
|
|
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
|
|
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
|
|
|
|
// This method will trigger on item Click of navigation menu
|
|
@Override
|
|
public boolean onNavigationItemSelected(MenuItem menuItem) {
|
|
//Closing drawer on item click
|
|
mainDrawer.closeDrawers();
|
|
|
|
//Check to see which item was being clicked and perform appropriate action
|
|
int id = menuItem.getItemId();
|
|
if (id == R.id.navigation_item_info) {
|
|
if (SDK_INT > 33)
|
|
UIAlert("ANDROID 13+", "sorry android 13+ have storage issues and we are working on it", activity);
|
|
else
|
|
startActivity(new Intent(activity, AboutActivity.class));
|
|
} else if (id == R.id.navigation_item_website) {
|
|
String tw = AppConfig.vectrasWebsite;
|
|
Intent w = new Intent(Intent.ACTION_VIEW);
|
|
w.setData(Uri.parse(tw));
|
|
startActivity(w);
|
|
} else if (id == R.id.navigation_item_import_iso) {
|
|
if (new File(AppConfig.maindirpath + "/drive.iso").exists()) {
|
|
AlertDialog ad;
|
|
ad = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create();
|
|
ad.setTitle("REPLACE ISO");
|
|
ad.setMessage("there is iso imported you want to replace it?");
|
|
ad.setButton(Dialog.BUTTON_POSITIVE, "REPLACE", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
intent.setType("*/*");
|
|
|
|
// Optionally, specify a URI for the file that should appear in the
|
|
// system file picker when it loads.
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
|
|
}
|
|
|
|
startActivityForResult(intent, 1004);
|
|
return;
|
|
}
|
|
});
|
|
ad.setButton(Dialog.BUTTON_NEGATIVE, "REMOVE", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
File isoFile = new File(AppConfig.maindirpath + "/drive.iso");
|
|
try {
|
|
isoFile.delete();
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
return;
|
|
}
|
|
});
|
|
ad.show();
|
|
} else {
|
|
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
intent.setType("*/*");
|
|
|
|
// Optionally, specify a URI for the file that should appear in the
|
|
// system file picker when it loads.
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
|
|
}
|
|
|
|
startActivityForResult(intent, 1004);
|
|
}
|
|
} else if (id == R.id.navigation_item_hdd1) {
|
|
if (new File(AppConfig.maindirpath + "/hdd1.qcow2").exists()) {
|
|
AlertDialog ad;
|
|
ad = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create();
|
|
ad.setTitle("REPLACE HDD1");
|
|
ad.setMessage("there is hdd1 imported you want to replace it?");
|
|
ad.setButton(Dialog.BUTTON_POSITIVE, "REPLACE", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
intent.setType("*/*");
|
|
|
|
// Optionally, specify a URI for the file that should appear in the
|
|
// system file picker when it loads.
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
|
|
}
|
|
|
|
startActivityForResult(intent, 1006);
|
|
return;
|
|
}
|
|
});
|
|
ad.setButton(Dialog.BUTTON_NEGATIVE, "REMOVE", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
File isoFile = new File(AppConfig.maindirpath + "/hdd1.qcow2");
|
|
try {
|
|
isoFile.delete();
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
return;
|
|
}
|
|
});
|
|
ad.setButton(Dialog.BUTTON_NEUTRAL, "SHARE", new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
Intent intentShareFile = new Intent(Intent.ACTION_SEND);
|
|
File fileWithinMyDir = new File(AppConfig.maindirpath + "/hdd1.qcow2");
|
|
|
|
if (fileWithinMyDir.exists()) {
|
|
intentShareFile.setType("*/*");
|
|
intentShareFile.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + AppConfig.maindirpath + "/hdd1.qcow2"));
|
|
|
|
intentShareFile.putExtra(Intent.EXTRA_SUBJECT,
|
|
"Sharing File...");
|
|
intentShareFile.putExtra(Intent.EXTRA_TEXT, "Sharing File...");
|
|
|
|
startActivity(Intent.createChooser(intentShareFile, "Share File"));
|
|
}
|
|
}
|
|
});
|
|
ad.show();
|
|
} else {
|
|
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
intent.setType("*/*");
|
|
|
|
// Optionally, specify a URI for the file that should appear in the
|
|
// system file picker when it loads.
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
|
|
}
|
|
|
|
startActivityForResult(intent, 1005);
|
|
}
|
|
} else if (id == R.id.navigation_item_hdd2) {
|
|
if (new File(AppConfig.maindirpath + "/hdd2.qcow2").exists()) {
|
|
AlertDialog ad;
|
|
ad = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create();
|
|
ad.setTitle("REPLACE HDD2");
|
|
ad.setMessage("there is hdd2 imported you want to replace it?");
|
|
ad.setButton(Dialog.BUTTON_POSITIVE, "REPLACE", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
intent.setType("*/*");
|
|
|
|
// Optionally, specify a URI for the file that should appear in the
|
|
// system file picker when it loads.
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
|
|
}
|
|
|
|
startActivityForResult(intent, 1006);
|
|
return;
|
|
}
|
|
});
|
|
ad.setButton(Dialog.BUTTON_NEGATIVE, "REMOVE", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
File isoFile = new File(AppConfig.maindirpath + "/hdd2.qcow2");
|
|
try {
|
|
isoFile.delete();
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
return;
|
|
}
|
|
});
|
|
ad.setButton(Dialog.BUTTON_NEUTRAL, "SHARE", new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
Intent intentShareFile = new Intent(Intent.ACTION_SEND);
|
|
File fileWithinMyDir = new File(AppConfig.maindirpath + "/hdd2.qcow2");
|
|
|
|
if (fileWithinMyDir.exists()) {
|
|
intentShareFile.setType("*/*");
|
|
intentShareFile.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + AppConfig.maindirpath + "/hdd2.qcow2"));
|
|
|
|
intentShareFile.putExtra(Intent.EXTRA_SUBJECT,
|
|
"Sharing File...");
|
|
intentShareFile.putExtra(Intent.EXTRA_TEXT, "Sharing File...");
|
|
|
|
startActivity(Intent.createChooser(intentShareFile, "Share File"));
|
|
}
|
|
}
|
|
});
|
|
ad.show();
|
|
} else {
|
|
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
intent.setType("*/*");
|
|
|
|
// Optionally, specify a URI for the file that should appear in the
|
|
// system file picker when it loads.
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
|
|
}
|
|
|
|
startActivityForResult(intent, 1006);
|
|
}
|
|
} else if (id == R.id.navigation_item_view_logs) {
|
|
FileUtils.viewVectrasLog(activity);
|
|
} else if (id == R.id.navigation_item_settings) {
|
|
startActivity(new Intent(activity, MainSettingsManager.class));
|
|
} else if (id == R.id.navigation_item_store) {
|
|
startActivity(new Intent(activity, StoreActivity.class));
|
|
} else if (id == R.id.navigation_data_explorer) {
|
|
startActivity(new Intent(activity, DataExplorerActivity.class));
|
|
} else if (id == R.id.navigation_item_donate) {
|
|
String tw = "https://www.buymeacoffee.com/vectrasvm/";
|
|
Intent w = new Intent(Intent.ACTION_VIEW);
|
|
w.setData(Uri.parse(tw));
|
|
startActivity(w);
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
|
|
ipTxt = findViewById(R.id.ipTxt);
|
|
|
|
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
|
|
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
|
|
activityManager.getMemoryInfo(mi);
|
|
|
|
long freeMem = mi.availMem / 1048576L;
|
|
long totalMem = mi.totalMem / 1048576L;
|
|
long usedMem = totalMem - freeMem;
|
|
int freeRamInt = safeLongToInt(freeMem);
|
|
int totalRamInt = safeLongToInt(totalMem);
|
|
ipTxt.setText("Local Ip Address: " + getLocalIpAddress());
|
|
|
|
SharedPreferences credentials = activity.getSharedPreferences(CREDENTIAL_SHARED_PREF, Context.MODE_PRIVATE);
|
|
|
|
totalRam = findViewById(R.id.totalRam);
|
|
usedRam = findViewById(R.id.usedRam);
|
|
freeRam = findViewById(R.id.freeRam);
|
|
|
|
ipTxt.setVisibility(View.GONE);
|
|
String vectrasMemory = String.valueOf(RamInfo.vectrasMemory());
|
|
t = new TimerTask() {
|
|
@Override
|
|
public void run() {
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
ActivityManager.MemoryInfo miI = new ActivityManager.MemoryInfo();
|
|
ActivityManager activityManagerr = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
|
|
activityManagerr.getMemoryInfo(miI);
|
|
long freeMemory = miI.availMem / 1048576L;
|
|
long totalMemory = miI.totalMem / 1048576L;
|
|
long usedMemory = totalMemory - freeMemory;
|
|
|
|
totalRam.setText("Total Memory: " + totalMemory + " MB");
|
|
usedRam.setText("Used Memory: " + usedMemory + " MB");
|
|
freeRam.setText("Free Memory: " + freeMemory + " MB (" + vectrasMemory + " used)");
|
|
ProgressBar progressBar = findViewById(R.id.progressBar);
|
|
progressBar.setMax((int) totalMemory);
|
|
if (SDK_INT >= Build.VERSION_CODES.N) {
|
|
progressBar.setProgress((int) usedMemory, true);
|
|
} else {
|
|
progressBar.setProgress((int) usedMemory);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
_timer.scheduleAtFixedRate(t, (int) (0), (int) (1000));
|
|
|
|
AdView mAdView = findViewById(R.id.adView);
|
|
adRequest = new AdRequest.Builder().build();
|
|
mAdView.loadAd(adRequest);
|
|
|
|
MobileAds.initialize(this, new OnInitializationCompleteListener() {
|
|
@Override
|
|
public void onInitializationComplete(InitializationStatus initializationStatus) {
|
|
}
|
|
});
|
|
if (MainSettingsManager.getPromptUpdateVersion(activity))
|
|
updateApp(false);
|
|
/*FirebaseUser user = mAuth.getCurrentUser();
|
|
TextView usernameTxt = findViewById(R.id.usernameTxt);
|
|
TextView emailTxt = findViewById(R.id.emailTxt);
|
|
ImageView profilePic = findViewById(R.id.profilePic);
|
|
if (user != null) {
|
|
// Name, email address, and profile photo Url
|
|
String name = user.getDisplayName();
|
|
String email = user.getEmail();
|
|
Uri photoUrl = user.getPhotoUrl();
|
|
|
|
// Check if user's email is verified
|
|
boolean emailVerified = user.isEmailVerified();
|
|
|
|
// The user's ID, unique to the Firebase project. Do NOT use this value to
|
|
// authenticate with your backend server, if you have one. Use
|
|
// FirebaseUser.getIdToken() instead.
|
|
String uid = user.getUid();
|
|
|
|
usernameTxt.setText(name);
|
|
emailTxt.setText(email);
|
|
if (photoUrl != null)
|
|
Glide.with(activity).load(photoUrl.toString()).into(profilePic);
|
|
}*/
|
|
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
|
if (!prefs.getBoolean("tgDialog", false)) {
|
|
AlertDialog alertDialog;
|
|
alertDialog = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create();
|
|
alertDialog.setTitle("JOIN US ON TELEGRAM");
|
|
TextView title = alertDialog.findViewById(android.R.id.title);
|
|
ObjectAnimator rgbAnim = ObjectAnimator.ofObject(title, "textColor", new ArgbEvaluator(), Color.RED, Color.GREEN, Color.BLUE);
|
|
rgbAnim.setDuration(1000);
|
|
rgbAnim.setRepeatMode(ValueAnimator.REVERSE);
|
|
rgbAnim.setRepeatCount(ValueAnimator.INFINITE);
|
|
rgbAnim.start();
|
|
alertDialog.setMessage("Join us on Telegram where we publish all the news and updates and receive your opinions and bugs");
|
|
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "JOIN", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
String tg = "https://t.me/vectras_os";
|
|
Intent f = new Intent(Intent.ACTION_VIEW);
|
|
f.setData(Uri.parse(tg));
|
|
startActivity(f);
|
|
return;
|
|
}
|
|
});
|
|
alertDialog.setButton(DialogInterface.BUTTON_NEUTRAL, "CANCEL", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
return;
|
|
}
|
|
});
|
|
alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "DONT SHOW AGAIN", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
|
SharedPreferences.Editor edit = prefs.edit();
|
|
edit.putBoolean("tgDialog", true);
|
|
edit.apply();
|
|
return;
|
|
}
|
|
});
|
|
alertDialog.show();
|
|
}
|
|
}
|
|
|
|
public static int safeLongToInt(long l) {
|
|
if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
|
|
throw new IllegalArgumentException(l + " cannot be cast to int without changing its value.");
|
|
}
|
|
return (int) l;
|
|
}
|
|
|
|
@Override
|
|
public void onBackPressed() {
|
|
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
|
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
|
drawer.closeDrawer(GravityCompat.START);
|
|
} else {
|
|
super.onBackPressed();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onStop() {
|
|
super.onStop();
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
super.onDestroy();
|
|
stopTimeListener();
|
|
|
|
}
|
|
|
|
@SuppressLint("NotifyDataSetChanged")
|
|
@Override
|
|
public void onStart() {
|
|
super.onStart();
|
|
if (!mCurrentUser.isEmailVerified() &&
|
|
!mAuth.getCurrentUser().isAnonymous()) {
|
|
startActivity(new Intent(activity, VerifyEmailActivity.class));
|
|
}
|
|
try {
|
|
HomeFragment.loadDataVbi();
|
|
} catch (Exception ignored) {
|
|
|
|
}
|
|
if (MainSettingsManager.getArch(activity) == "X86_64") {
|
|
if (MainSettingsManager.getVirtio(activity)) {
|
|
Config.hd_if_type = "virtio";
|
|
} else {
|
|
Config.hd_if_type = "ide";
|
|
}
|
|
} else if (MainSettingsManager.getArch(activity) == "ARM") {
|
|
Config.hd_if_type = "scsi";
|
|
}
|
|
setupFolders();
|
|
Config.ui = MainSettingsManager.getVmUi(activity);
|
|
InterstitialAd.load(this, "ca-app-pub-3568137780412047/7745973511", adRequest,
|
|
new InterstitialAdLoadCallback() {
|
|
@Override
|
|
public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
|
|
// The mInterstitialAd reference will be null until
|
|
// an ad is loaded.
|
|
mInterstitialAd = interstitialAd;
|
|
Log.i(TAG, "onAdLoaded");
|
|
}
|
|
|
|
@Override
|
|
public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
|
|
// Handle the error
|
|
Log.d(TAG, loadAdError.toString());
|
|
mInterstitialAd = null;
|
|
}
|
|
});
|
|
if (mInterstitialAd != null && !MainService.isRunning) {
|
|
mInterstitialAd.show(this);
|
|
} else {
|
|
Log.d("TAG", "The interstitial ad wasn't ready yet.");
|
|
}
|
|
}
|
|
|
|
public void onPause() {
|
|
super.onPause();
|
|
stopTimeListener();
|
|
}
|
|
|
|
public boolean loaded = false;
|
|
|
|
public void onResume() {
|
|
super.onResume();
|
|
if (MainService.isRunning && Objects.equals(Config.ui, "VNC")) {
|
|
startvnc();
|
|
}
|
|
execTimer();
|
|
}
|
|
|
|
public static VMStatus currStatus = VMStatus.Ready;
|
|
public static boolean vmStarted = false;
|
|
public static StartVM vmexecutor;
|
|
public static String vnc_passwd = "vectras";
|
|
public static int vnc_allow_external = 1;
|
|
public static int qmp_allow_external = 0;
|
|
public static ProgressDialog progDialog;
|
|
public static View parent;
|
|
public static InstallerTask installerTaskTask;
|
|
public static boolean timeQuit = false;
|
|
public static Object lockTime = new Object();
|
|
|
|
public static boolean libLoaded;
|
|
|
|
|
|
static public void onInstall(boolean force) {
|
|
FileInstaller.installFiles(activity, force);
|
|
}
|
|
|
|
public static String getVnc_passwd() {
|
|
return vnc_passwd;
|
|
}
|
|
|
|
public static void setVnc_passwd(String vnc_passwd) {
|
|
vnc_passwd = vnc_passwd;
|
|
}
|
|
|
|
public static String getLocalIpAddress() {
|
|
try {
|
|
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
} catch (SocketException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Start calling the JNI interface
|
|
public static void startvm(Activity activity, int UI) {
|
|
QmpClient.allow_external = (qmp_allow_external == 1);
|
|
vmexecutor.qmp_allow_external = qmp_allow_external;
|
|
|
|
if (UI == Config.UI_VNC) {
|
|
// disable sound card with VNC
|
|
vmexecutor.enablevnc = 1;
|
|
vmexecutor.enablespice = 0;
|
|
vmexecutor.sound_card = null;
|
|
vmexecutor.vnc_allow_external = vnc_allow_external;
|
|
RfbProto.allow_external = (vnc_allow_external == 1);
|
|
vmexecutor.vnc_passwd = vnc_passwd;
|
|
} else if (UI == Config.UI_SDL) {
|
|
vmexecutor.enablevnc = 0;
|
|
vmexecutor.enablespice = 0;
|
|
} else if (UI == Config.UI_SPICE) {
|
|
vmexecutor.vnc_allow_external = vnc_allow_external;
|
|
vmexecutor.vnc_passwd = vnc_passwd;
|
|
vmexecutor.enablevnc = 0;
|
|
vmexecutor.enablespice = 1;
|
|
}
|
|
vmexecutor.startvm(activity, UI);
|
|
|
|
}
|
|
|
|
|
|
public static void cleanup() {
|
|
|
|
vmStarted = false;
|
|
|
|
//XXX flush and close all file descriptors if we haven't already
|
|
FileUtils.close_fds();
|
|
|
|
////XXX; we wait till fds flush and close
|
|
try {
|
|
Thread.sleep(1000);
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
//set the exit code
|
|
MainSettingsManager.setExitCode(activity, 1);
|
|
|
|
//XXX: SDL seems to lock the keyboard events
|
|
// unless we finish the starting activity
|
|
activity.finish();
|
|
|
|
Log.v(TAG, "Exit");
|
|
//XXX: We exit here to force unload the native libs
|
|
System.exit(0);
|
|
|
|
|
|
}
|
|
|
|
public static void changeStatus(final VMStatus status_changed) {
|
|
activity.runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (status_changed == VMStatus.Running) {
|
|
|
|
vmStarted = true;
|
|
} else if (status_changed == VMStatus.Ready || status_changed == VMStatus.Stopped) {
|
|
|
|
} else if (status_changed == VMStatus.Saving) {
|
|
|
|
} else if (status_changed == VMStatus.Paused) {
|
|
|
|
}
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
public static void install(boolean force) {
|
|
progDialog = ProgressDialog.show(activity, "Please Wait", "Installing BIOS...", true);
|
|
installerTaskTask = new InstallerTask();
|
|
installerTaskTask.force = force;
|
|
installerTaskTask.execute();
|
|
}
|
|
|
|
public static void checkAndLoadLibs() {
|
|
if (Config.loadNativeLibsEarly)
|
|
if (Config.loadNativeLibsMainThread)
|
|
setupNativeLibs();
|
|
else
|
|
setupNativeLibsAsync();
|
|
}
|
|
|
|
public static void clearNotifications() {
|
|
NotificationManager notificationManager = (NotificationManager) activity.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
|
notificationManager.cancelAll();
|
|
}
|
|
|
|
public static void setupNativeLibsAsync() {
|
|
|
|
Thread thread = new Thread(new Runnable() {
|
|
public void run() {
|
|
setupNativeLibs();
|
|
}
|
|
});
|
|
thread.setPriority(Thread.MIN_PRIORITY);
|
|
thread.start();
|
|
|
|
}
|
|
|
|
public static void savePendingEditText() {
|
|
View currentView = activity.getCurrentFocus();
|
|
if (currentView != null && currentView instanceof EditText) {
|
|
((EditText) currentView).setFocusable(false);
|
|
}
|
|
}
|
|
|
|
public static void checkLog() {
|
|
|
|
Thread t = new Thread(new Runnable() {
|
|
public void run() {
|
|
|
|
if (MainSettingsManager.getExitCode(activity) != 1) {
|
|
MainSettingsManager.setExitCode(activity, 1);
|
|
activity.runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
UIUtils.promptShowLog(activity);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
t.start();
|
|
}
|
|
|
|
public static void setupFolders() {
|
|
try {
|
|
Config.cacheDir = activity.getCacheDir().getAbsolutePath();
|
|
Config.storagedir = Environment.getDataDirectory().toString();
|
|
} catch (Exception ignored) {
|
|
|
|
}
|
|
}
|
|
|
|
//XXX: sometimes this needs to be called from the main thread otherwise
|
|
// qemu crashes when it is started later
|
|
public static void setupNativeLibs() {
|
|
|
|
if (libLoaded)
|
|
return;
|
|
|
|
//Some devices need stl loaded upfront
|
|
//System.loadLibrary("stlport_shared");
|
|
|
|
//Compatibility lib
|
|
System.loadLibrary("compat-vectras");
|
|
|
|
//Glib deps
|
|
System.loadLibrary("compat-musl");
|
|
|
|
|
|
//Glib
|
|
System.loadLibrary("glib-2.0");
|
|
|
|
//Pixman for qemu
|
|
System.loadLibrary("pixman-1");
|
|
|
|
//Spice server
|
|
if (Config.enable_SPICE) {
|
|
System.loadLibrary("crypto");
|
|
System.loadLibrary("ssl");
|
|
System.loadLibrary("spice");
|
|
}
|
|
|
|
// //Load SDL library
|
|
if (Config.enable_SDL) {
|
|
System.loadLibrary("SDL2");
|
|
}
|
|
|
|
System.loadLibrary("compat-SDL2-ext");
|
|
|
|
//Vectras needed for vmexecutor
|
|
System.loadLibrary("vectras");
|
|
|
|
loadQEMULib();
|
|
|
|
libLoaded = true;
|
|
}
|
|
|
|
public static void loadQEMULib() {
|
|
|
|
if (Objects.equals(MainSettingsManager.getArch(activity), "X86_64")) {
|
|
try {
|
|
System.loadLibrary("qemu-system-i386");
|
|
} catch (Error ex) {
|
|
System.loadLibrary("qemu-system-x86_64");
|
|
}
|
|
} else if (Objects.equals(MainSettingsManager.getArch(activity), "ARM")) {
|
|
try {
|
|
System.loadLibrary("qemu-system-arm");
|
|
} catch (Error ex) {
|
|
System.loadLibrary("qemu-system-aarch64");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static void setupStrictMode() {
|
|
|
|
if (Config.debugStrictMode) {
|
|
StrictMode.setThreadPolicy(
|
|
new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork()
|
|
//.penaltyDeath()
|
|
.penaltyLog().build());
|
|
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects()
|
|
.detectLeakedClosableObjects().penaltyLog()
|
|
// .penaltyDeath()
|
|
.build());
|
|
}
|
|
|
|
}
|
|
|
|
public static void onLicense() {
|
|
PackageInfo pInfo = null;
|
|
|
|
try {
|
|
pInfo = activity.getPackageManager().getPackageInfo(activity.getClass().getPackage().getName(), PackageManager.GET_META_DATA);
|
|
} catch (PackageManager.NameNotFoundException e) {
|
|
e.printStackTrace();
|
|
return;
|
|
}
|
|
|
|
final PackageInfo finalPInfo = pInfo;
|
|
activity.runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
// Main event function
|
|
// Retrives values from saved preferences
|
|
public static void onStartButton() {
|
|
if (MainService.isRunning) {
|
|
startvnc();
|
|
} else {
|
|
if (vmexecutor == null) {
|
|
|
|
try {
|
|
vmexecutor = new StartVM(activity);
|
|
} catch (Exception ex) {
|
|
UIUtils.toastLong(activity, "Error: " + ex);
|
|
return;
|
|
|
|
}
|
|
}
|
|
// dns
|
|
vmexecutor.dns_addr = Config.defaultDNSServer;
|
|
|
|
vmexecutor.paused = 0;
|
|
|
|
if (!vmStarted) {
|
|
UIUtils.toastShort(activity, "Starting VM");
|
|
//XXX: make sure that bios files are installed in case we ran out of space in the last
|
|
// run
|
|
FileInstaller.installFiles(activity, false);
|
|
} else {
|
|
UIUtils.toastShort(activity, "Connecting to VM");
|
|
}
|
|
|
|
if (Config.ui.equals("VNC")) {
|
|
vmexecutor.enableqmp = 1; // We enable qemu monitor
|
|
startVNC();
|
|
|
|
} else if (Config.ui.equals("SDL")) {
|
|
vmexecutor.enableqmp = 0; // We disable qemu monitor
|
|
startSDL();
|
|
} else {
|
|
vmexecutor.enableqmp = 1; // We enable qemu monitor
|
|
startSPICE();
|
|
}
|
|
}
|
|
}
|
|
|
|
public static String getLanguageCode(int index) {
|
|
// TODO: Add more languages from /assets/roms/keymaps
|
|
switch (index) {
|
|
case 0:
|
|
return "en-us";
|
|
case 1:
|
|
return "es";
|
|
case 2:
|
|
return "fr";
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static void startSDL() {
|
|
|
|
Thread tsdl = new Thread(new Runnable() {
|
|
public void run() {
|
|
startsdl();
|
|
}
|
|
});
|
|
if (Config.maxPriority)
|
|
tsdl.setPriority(Thread.MAX_PRIORITY);
|
|
tsdl.start();
|
|
}
|
|
|
|
public static void startVNC() {
|
|
|
|
VncCanvas.retries = 0;
|
|
if (!vmStarted) {
|
|
|
|
Thread tvm = new Thread(new Runnable() {
|
|
public void run() {
|
|
startvm(activity, Config.UI_VNC);
|
|
}
|
|
});
|
|
if (Config.maxPriority)
|
|
tvm.setPriority(Thread.MAX_PRIORITY);
|
|
tvm.start();
|
|
} else {
|
|
startvnc();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public static void startSPICE() {
|
|
|
|
if (!vmStarted) {
|
|
|
|
Thread tvm = new Thread(new Runnable() {
|
|
public void run() {
|
|
startvm(activity, Config.UI_SPICE);
|
|
}
|
|
});
|
|
if (Config.maxPriority)
|
|
tvm.setPriority(Thread.MAX_PRIORITY);
|
|
tvm.start();
|
|
}
|
|
|
|
}
|
|
|
|
public static void onStopButton(boolean exit) {
|
|
stopVM(exit);
|
|
}
|
|
|
|
public static void onRestartButton() {
|
|
|
|
execTimer();
|
|
|
|
Machine.resetVM(activity);
|
|
}
|
|
|
|
public static void onResumeButton() {
|
|
|
|
// TODO: This probably has no effect
|
|
Thread t = new Thread(new Runnable() {
|
|
public void run() {
|
|
resumevm();
|
|
}
|
|
});
|
|
t.start();
|
|
}
|
|
|
|
public String getPath(Uri uri) {
|
|
return com.vectras.vm.utils.FileUtils.getPath(this, uri);
|
|
}
|
|
|
|
@Override
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent ReturnedIntent) {
|
|
super.onActivityResult(requestCode, resultCode, ReturnedIntent);
|
|
if (requestCode == 1004 && resultCode == RESULT_OK) {
|
|
Uri content_describer = ReturnedIntent.getData();
|
|
File selectedFilePath = new File(getPath(content_describer));
|
|
ProgressBar loading = findViewById(R.id.loading);
|
|
if (selectedFilePath.toString().endsWith(".iso")) {
|
|
loading.setVisibility(View.VISIBLE);
|
|
new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
FileInputStream File = null;
|
|
try {
|
|
File = (FileInputStream) getContentResolver().openInputStream(content_describer);
|
|
} catch (FileNotFoundException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
try {
|
|
try {
|
|
OutputStream out = new FileOutputStream(new File(AppConfig.maindirpath + "/drive.iso"));
|
|
try {
|
|
// Transfer bytes from in to out
|
|
byte[] buf = new byte[1024];
|
|
int len;
|
|
while ((len = File.read(buf)) > 0) {
|
|
out.write(buf, 0, len);
|
|
}
|
|
} finally {
|
|
out.close();
|
|
}
|
|
} finally {
|
|
Runnable runnable = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
loading.setVisibility(View.GONE);
|
|
}
|
|
};
|
|
activity.runOnUiThread(runnable);
|
|
File.close();
|
|
}
|
|
} catch (IOException e) {
|
|
Runnable runnable = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
loading.setVisibility(View.GONE);
|
|
UIAlert("error", e.toString(), activity);
|
|
}
|
|
};
|
|
activity.runOnUiThread(runnable);
|
|
}
|
|
}
|
|
}).start();
|
|
} else
|
|
UIAlert("NOT VAILED FILE", "please select iso file", activity);
|
|
} else if (requestCode == 1005 && resultCode == RESULT_OK) {
|
|
Uri content_describer = ReturnedIntent.getData();
|
|
File selectedFilePath = new File(getPath(content_describer));
|
|
ProgressBar loading = findViewById(R.id.loading);
|
|
loading.setVisibility(View.VISIBLE);
|
|
new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
FileInputStream File = null;
|
|
try {
|
|
File = (FileInputStream) getContentResolver().openInputStream(content_describer);
|
|
} catch (FileNotFoundException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
try {
|
|
try {
|
|
OutputStream out = new FileOutputStream(new File(AppConfig.maindirpath + "/hdd1.qcow2"));
|
|
try {
|
|
// Transfer bytes from in to out
|
|
byte[] buf = new byte[1024];
|
|
int len;
|
|
while ((len = File.read(buf)) > 0) {
|
|
out.write(buf, 0, len);
|
|
}
|
|
} finally {
|
|
out.close();
|
|
}
|
|
} finally {
|
|
Runnable runnable = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
loading.setVisibility(View.GONE);
|
|
}
|
|
};
|
|
activity.runOnUiThread(runnable);
|
|
File.close();
|
|
}
|
|
} catch (IOException e) {
|
|
Runnable runnable = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
loading.setVisibility(View.GONE);
|
|
UIAlert("error", e.toString(), activity);
|
|
}
|
|
};
|
|
activity.runOnUiThread(runnable);
|
|
}
|
|
}
|
|
}).start();
|
|
} else if (requestCode == 1006 && resultCode == RESULT_OK) {
|
|
Uri content_describer = ReturnedIntent.getData();
|
|
File selectedFilePath = new File(getPath(content_describer));
|
|
ProgressBar loading = findViewById(R.id.loading);
|
|
loading.setVisibility(View.VISIBLE);
|
|
new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
FileInputStream File = null;
|
|
try {
|
|
File = (FileInputStream) getContentResolver().openInputStream(content_describer);
|
|
} catch (FileNotFoundException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
try {
|
|
try {
|
|
OutputStream out = new FileOutputStream(new File(AppConfig.maindirpath + "/hdd2.qcow2"));
|
|
try {
|
|
// Transfer bytes from in to out
|
|
byte[] buf = new byte[1024];
|
|
int len;
|
|
while ((len = File.read(buf)) > 0) {
|
|
out.write(buf, 0, len);
|
|
}
|
|
} finally {
|
|
out.close();
|
|
}
|
|
} finally {
|
|
Runnable runnable = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
loading.setVisibility(View.GONE);
|
|
}
|
|
};
|
|
activity.runOnUiThread(runnable);
|
|
File.close();
|
|
}
|
|
} catch (IOException e) {
|
|
Runnable runnable = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
loading.setVisibility(View.GONE);
|
|
UIAlert("error", e.toString(), activity);
|
|
}
|
|
};
|
|
activity.runOnUiThread(runnable);
|
|
}
|
|
}
|
|
}).start();
|
|
} else if (requestCode == 122 && resultCode == RESULT_OK) {
|
|
Uri content_describer = ReturnedIntent.getData();
|
|
File selectedFilePath = new File(getPath(content_describer));
|
|
ProgressBar loading = findViewById(R.id.loading);
|
|
TextInputEditText drv1 = AdapterMainRoms.d.findViewById(R.id.drive1);
|
|
Button saveB = AdapterMainRoms.d.findViewById(R.id.saveRomBtn);
|
|
loading.setVisibility(View.VISIBLE);
|
|
saveB.setVisibility(View.GONE);
|
|
new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
FileInputStream File = null;
|
|
try {
|
|
File = (FileInputStream) getContentResolver().openInputStream(content_describer);
|
|
} catch (FileNotFoundException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
try {
|
|
try {
|
|
File romDir = new File(AppConfig.maindirpath + curRomName + "/");
|
|
if (!romDir.exists()) {
|
|
romDir.mkdirs();
|
|
}
|
|
OutputStream out = new FileOutputStream(new File(AppConfig.maindirpath + curRomName + "/" + "drv1-" + selectedFilePath.getName()));
|
|
try {
|
|
// Transfer bytes from in to out
|
|
byte[] buf = new byte[1024];
|
|
int len;
|
|
while ((len = File.read(buf)) > 0) {
|
|
out.write(buf, 0, len);
|
|
}
|
|
} finally {
|
|
out.close();
|
|
}
|
|
} finally {
|
|
Runnable runnable = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
loading.setVisibility(View.GONE);
|
|
saveB.setVisibility(View.VISIBLE);
|
|
drv1.setText(AppConfig.maindirpath + curRomName + "/" + "drv1-" + selectedFilePath.getName());
|
|
}
|
|
};
|
|
activity.runOnUiThread(runnable);
|
|
File.close();
|
|
}
|
|
} catch (IOException e) {
|
|
Runnable runnable = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
loading.setVisibility(View.GONE);
|
|
saveB.setVisibility(View.VISIBLE);
|
|
UIAlert("error", e.toString(), activity);
|
|
}
|
|
};
|
|
activity.runOnUiThread(runnable);
|
|
}
|
|
}
|
|
}).start();
|
|
}
|
|
}
|
|
|
|
public static void startvnc() {
|
|
|
|
// Wait till Qemu settles
|
|
try {
|
|
Thread.sleep(2000);
|
|
} catch (InterruptedException ex) {
|
|
Logger.getLogger(activity.getClass().getName()).log(Level.SEVERE, null, ex);
|
|
}
|
|
if (MainSettingsManager.getVncExternal(activity)) {
|
|
|
|
} else {
|
|
connectLocally();
|
|
}
|
|
}
|
|
|
|
public static void promptConnectLocally(final Activity activity) {
|
|
|
|
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
final AlertDialog alertDialog;
|
|
alertDialog = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create();
|
|
alertDialog.setTitle("VNC Started");
|
|
TextView stateView = new TextView(activity);
|
|
stateView.setText("VNC Server started: " + getLocalIpAddress() + ":" + Config.defaultVNCPort + "\n"
|
|
+ "Warning: VNC Connection is Unencrypted and not secure make sure you're on a private network!\n");
|
|
|
|
stateView.setPadding(20, 20, 20, 20);
|
|
alertDialog.setView(stateView);
|
|
|
|
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
alertDialog.dismiss();
|
|
}
|
|
});
|
|
alertDialog.setButton(DialogInterface.BUTTON_NEUTRAL, "Connect Locally", new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
connectLocally();
|
|
}
|
|
});
|
|
alertDialog.show();
|
|
}
|
|
}, 100);
|
|
|
|
|
|
}
|
|
|
|
public static void connectLocally() {
|
|
//UIUtils.toastShort(this, "Connecting to VM Display");
|
|
Intent intent = getVNCIntent();
|
|
activity.startActivityForResult(intent, Config.VNC_REQUEST_CODE);
|
|
}
|
|
|
|
public static void startsdl() {
|
|
|
|
Intent intent = null;
|
|
|
|
intent = new Intent(activity, MainSDLActivity.class);
|
|
|
|
android.content.ContentValues values = new android.content.ContentValues();
|
|
activity.startActivityForResult(intent, Config.SDL_REQUEST_CODE);
|
|
}
|
|
|
|
|
|
public static void resumevm() {
|
|
if (vmexecutor != null) {
|
|
vmexecutor.resumevm();
|
|
UIUtils.toastShort(activity, "VM Reset");
|
|
} else {
|
|
|
|
UIUtils.toastShort(activity, "VM not running");
|
|
}
|
|
|
|
}
|
|
|
|
public static Intent getVNCIntent() {
|
|
return new Intent(activity, com.vectras.qemu.MainVNCActivity.class);
|
|
|
|
}
|
|
|
|
|
|
public static void goToSettings() {
|
|
Intent i = new Intent(activity, MainSettingsManager.class);
|
|
activity.startActivity(i);
|
|
}
|
|
|
|
public static void onViewLog() {
|
|
|
|
Thread t = new Thread(new Runnable() {
|
|
public void run() {
|
|
FileUtils.viewVectrasLog(activity);
|
|
}
|
|
});
|
|
t.start();
|
|
}
|
|
|
|
public static void goToURL(String url) {
|
|
|
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
|
i.setData(Uri.parse(url));
|
|
activity.startActivity(i);
|
|
|
|
}
|
|
|
|
public static void stopVM(boolean exit) {
|
|
execTimer();
|
|
Machine.stopVM(activity);
|
|
}
|
|
|
|
public static void stopTimeListener() {
|
|
|
|
synchronized (lockTime) {
|
|
timeQuit = true;
|
|
lockTime.notifyAll();
|
|
}
|
|
}
|
|
|
|
|
|
public static void timer() {
|
|
//XXX: No timers just ping a few times
|
|
for (int i = 0; i < 3; i++) {
|
|
checkAndUpdateStatus(false);
|
|
|
|
try {
|
|
Thread.sleep(1000);
|
|
} catch (InterruptedException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public static void checkAndUpdateStatus(boolean force) {
|
|
if (vmexecutor != null) {
|
|
VMStatus status = checkStatus();
|
|
if (force || status != currStatus) {
|
|
currStatus = status;
|
|
changeStatus(status);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void execTimer() {
|
|
|
|
Thread t = new Thread(new Runnable() {
|
|
public void run() {
|
|
startTimer();
|
|
}
|
|
});
|
|
t.start();
|
|
}
|
|
|
|
public static void startTimer() {
|
|
stopTimeListener();
|
|
|
|
timeQuit = false;
|
|
try {
|
|
timer();
|
|
} catch (Exception ex) {
|
|
ex.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static enum VMStatus {
|
|
Ready, Stopped, Saving, Paused, Completed, Failed, Unknown, Running
|
|
}
|
|
|
|
public static VMStatus checkStatus() {
|
|
VMStatus state = VMStatus.Ready;
|
|
if (vmexecutor != null && libLoaded && vmexecutor.get_state().toUpperCase().equals("RUNNING")) {
|
|
state = VMStatus.Running;
|
|
}
|
|
return state;
|
|
}
|
|
|
|
public static class InstallerTask extends AsyncTask<Void, Void, Void> {
|
|
public boolean force;
|
|
|
|
@Override
|
|
protected Void doInBackground(Void... arg0) {
|
|
onInstall(force);
|
|
if (progDialog.isShowing()) {
|
|
progDialog.dismiss();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(Void test) {
|
|
|
|
}
|
|
}
|
|
|
|
}
|