cut devmenu

This commit is contained in:
2024-12-15 22:13:06 +03:00
parent 7b5bcdb978
commit 49a2d575c0
17 changed files with 0 additions and 2143 deletions
@@ -1,65 +0,0 @@
package com.ea.ironmonkey.devmenu;
import static com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper.MAIN_TABLE_NAME;
import static com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper.PATH_TO_REPLACED_ELEMENT;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.TwoLineListItem;
import com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper;
import com.ea.ironmonkey.devmenu.util.UtilitiesAndData;
import java.io.File;
import java.util.List;
class FileAdapter extends ArrayAdapter<File> {
private static int count = 0;
private List files;
private Context context;
private ReplacementDataBaseHelper dataBaseHelper;
private SQLiteDatabase database;
public FileAdapter(Context context, List files) {
super(context, android.R.layout.simple_list_item_2, files);
dataBaseHelper = new ReplacementDataBaseHelper(context);
database = dataBaseHelper.getDatabase();
this.context = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
String name = getItem(position).getName();
Cursor query = database.query(MAIN_TABLE_NAME, new String[]{PATH_TO_REPLACED_ELEMENT},
PATH_TO_REPLACED_ELEMENT + " = \"" + getItem(position).getAbsolutePath() + "\""
, null, null, null, null);
if (query.getCount() > 0) {
TwoLineListItem listItem = (TwoLineListItem) inflater.inflate(android.R.layout.simple_list_item_2, null, true);
listItem.getText1().setText(name);
listItem.getText2().setText("Заменен");
view = listItem;
} else {
TextView textView = (TextView) inflater.inflate(android.R.layout.simple_list_item_1, null, true);
textView.setText(name);
view = textView;
}
query.close();
return view;
}
public List getFiles() {
return files;
}
}
@@ -1,458 +0,0 @@
package com.ea.ironmonkey.devmenu;
import static com.ea.ironmonkey.devmenu.util.UtilitiesAndData.OPEN_FILE_ON_REPLACE_REQUEST;
import static com.ea.ironmonkey.devmenu.util.UtilitiesAndData.copy;
import static com.ea.ironmonkey.devmenu.util.UtilitiesAndData.generateMD5;
import static com.ea.ironmonkey.devmenu.util.UtilitiesAndData.isFirstRun;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.TwoLineListItem;
import com.ea.games.nfs13_na.BuildConfig;
import com.ea.games.nfs13_na.R;
import com.ea.ironmonkey.GameActivity;
import com.ea.ironmonkey.devmenu.components.LongPressContextMenu;
import com.ea.ironmonkey.devmenu.util.ResultListener;
import com.ea.ironmonkey.devmenu.util.UtilitiesAndData;
import com.ea.nimble.Utility;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Random;
//TODO сделать нормальный файл сохранения
//TODO сделать его нрмальное отображние
//TODO сделать нормальное отслеживние файлов сохранений
//TODO сдлеать настройки отслеживания файла
//TODO сделать отображение текущего пути в проводнике
//TODO добавить иконки к проводику
//TODO сделать динамическое контекстное меню файла
//TODO реализовать сохранение файлов в память телефона из внутреннего хранилища
public class MainActivity extends Activity{
private final String LOG_TAG = "InjectedActivity";
private String internalFiles;
private String externalFiles;
private ResultListener resultListener;
private ResultListener openResult = new ResultListener() {};
private static Thread observerThread;
private String globalPath = "";
private ListView fileList;
private Button backButton;
private static final int READ_FILE_REQUEST_CODE = 101;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UtilitiesAndData.init(this);
internalFiles = UtilitiesAndData.getInternalStorage();
externalFiles = UtilitiesAndData.getExternalStorage();
File replacements = new File(UtilitiesAndData.getReplacementsStorage());
if(!replacements.exists()) replacements.mkdir();
File activityFlag = new File(externalFiles + File.separator + BuildConfig.DEV_MENU_ID);
// TODO доделать проверку первого запуска
if(isFirstRun()){
File data = new File(UtilitiesAndData.getExternalStorage());
if(!data.exists()){
File data1 = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + getPackageName() + "_");
if(data1.exists()) {
String path = data1.getPath();
data1.renameTo(new File(path.substring(0, path.length() - 2)));
activityFlag = data1;
}
}
try {
File temp = new File(UtilitiesAndData.getInternalStorage() + File.separator + "load");
temp.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
if(!activityFlag.exists()){
updateLanguage();
runGame();
return;
}
setContentView(R.layout.custom);
String title = String.format(getString(R.string.dev_menu_title), /*BuildConfig.DEV_MENU_VERSION*/"");
getActionBar().setTitle(title);
fileList = (ListView) findViewById(R.id.FileList);
fileList.setAdapter(new FileAdapter(this, asList(externalFiles)));
globalPath = externalFiles;
RadioGroup group = (RadioGroup) findViewById(R.id.switcherFiles);
fileList.setOnItemClickListener((parent, view, position, id) -> {
String chosenElem =
(view instanceof TwoLineListItem) ?
((TwoLineListItem) view).getText1().getText().toString() :
((TextView) view).getText().toString(); // получаем текст нажатого элемента
File intermid = new File(globalPath + "/" + chosenElem);
if(intermid.isDirectory()) {
globalPath += "/" + chosenElem;
updateListView();
}
else{
openFile(intermid);
}
});
fileList.setOnItemLongClickListener((parent, view, position, id) -> {
String chosenElem =
(view instanceof TwoLineListItem) ?
((TwoLineListItem) view).getText1().getText().toString() :
((TextView) view).getText().toString();
LongPressContextMenu ninja = new LongPressContextMenu(this, globalPath + "/" + chosenElem);
return true;
});
group.setOnCheckedChangeListener((group1, checkedId) -> {
globalPath = (checkedId == R.id.externalStoreButton) ? externalFiles : internalFiles;
updateListView();
});
backButton = (Button)findViewById(R.id.back_button);
backButton.setOnClickListener(v -> {
if(!( globalPath.equals(internalFiles) | globalPath.equals(externalFiles) )
& !globalPath.isEmpty()
& (new File(globalPath).exists())) {
globalPath = globalPath.substring(0, globalPath.lastIndexOf("/"));
updateListView();
}
});
//Настройка языка игры
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
}
public void readAndSortNumbersFromFile(String fileName) {
List<Integer> numbersList = new ArrayList<>();
try {
File file = new File(fileName);
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String line;
while ((line = bufferedReader.readLine()) != null) {
try {
// Попытайтесь преобразовать строку в целое число и добавить его в список
int number = Integer.parseInt(line);
numbersList.add(number);
} catch (NumberFormatException e) {
// Если строка не является числом, проигнорируйте ее
Log.e("FileOperations", "Ошибка при чтении числа: " + line);
}
}
bufferedReader.close();
// Отсортируйте числа в списке
Collections.sort(numbersList);
} catch (IOException e) {
Log.e("Time", "Ошибка при чтении файла: " + e.getMessage());
}
}
@Override
public void onBackPressed() {
backButton.callOnClick();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.options, menu);
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case OPEN_FILE_ON_REPLACE_REQUEST:{
resultListener.onResult(data);
}break;
case READ_FILE_REQUEST_CODE:{
openResult.onResult(data);
}
}
}
@SuppressLint("NonConstantResourceId")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.optionRunTheGame) {
updateLanguage();
runGame();
} else if (itemId == R.id.optionSettings) {
Intent goToSettings = new Intent(this, SettingsActivity.class);
startActivity(goToSettings);
} else if (itemId == R.id.optionDeleteData) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.remove_action_title));
builder.setMessage(getString(R.string.sure_remove_all_data_title));
builder.setPositiveButton(R.string.ok_title, (dialogInterface, i) -> {
File[] internals = new File(UtilitiesAndData.getInternalStorage()).listFiles();
for (File internal : internals) {
if (!UtilitiesAndData.isExclusionName(internal.getName())) {
internal.delete();
}
}
});
builder.setNegativeButton(R.string.cancel_title, null);
builder.show();
} else if (itemId == R.id.optionCheckRecovers) {
Intent goToRecovers = new Intent(this, RecoverListActivity.class);
startActivity(goToRecovers);
}
return super.onOptionsItemSelected(item);
}
public void openFile(File url) {
File tempFile = null;
Intent intent = new Intent(Intent.ACTION_VIEW);
if(url.getAbsolutePath().contains(UtilitiesAndData.getInternalStorage())){
Log.wtf(LOG_TAG, "WTF, man, you cant read my files!!!");
//Создаем временный файл, там где можем его прочитать
Random random = new Random();
tempFile = new File(UtilitiesAndData.getExternalStorage() + File.separator + "temp_" + random.nextInt());
//Копируем тот файл который хотим посмотреть
copy(url.getAbsolutePath(), tempFile.getAbsolutePath());
//Сохраняем ссылку на окрытый файл, в случае его изменения
final File openedFile = url;
url = tempFile;
File finalTempFile = tempFile;
//Создаем хеш файла для того чтобы его потом сравнить
final byte[] compTemp = generateMD5(finalTempFile);
openResult = new ResultListener(){
@Override
public void onResult(Object data) {
byte[] bytes = generateMD5(finalTempFile);
//Если хеши не одинаковы то заменяем одно на другое
if(!Arrays.equals(bytes, compTemp))
copy(finalTempFile.getAbsolutePath(), openedFile.getAbsolutePath());
finalTempFile.delete();
}
};
intent.putExtra("pathToTemp", tempFile.getAbsolutePath());
}
// Create URI
Uri uri = Uri.fromFile(url);
if (url.toString().contains(".doc") || url.toString().contains(".docx"))
intent.setDataAndType(uri, "application/msword");
else if(url.toString().contains(".pdf")) {
intent.setDataAndType(uri, "application/pdf");
} else if(url.toString().contains(".ppt") || url.toString().contains(".pptx")) {
intent.setDataAndType(uri, "application/vnd.ms-powerpoint");
} else if(url.toString().contains(".xls") || url.toString().contains(".xlsx")) {
intent.setDataAndType(uri, "application/vnd.ms-excel");
} else if(url.toString().contains(".zip") || url.toString().contains(".rar")) {
intent.setDataAndType(uri, "application/x-wav");
} else if(url.toString().contains(".rtf")) {
intent.setDataAndType(uri, "application/rtf");
} else if(url.toString().contains(".wav") || url.toString().contains(".mp3")) {
intent.setDataAndType(uri, "audio/x-wav");
} else if(url.toString().contains(".gif")) {
intent.setDataAndType(uri, "image/gif");
} else if(url.toString().contains(".jpg") || url.toString().contains(".jpeg") || url.toString().contains(".png")) {
intent.setDataAndType(uri, "image/jpeg");
} else if(url.toString().contains(".txt")) {
intent.setDataAndType(uri, "text/plain");
} else if(url.toString().contains(".3gp") || url.toString().contains(".mpg") || url.toString().contains(".mpeg") || url.toString().contains(".mpe") || url.toString().contains(".mp4") || url.toString().contains(".avi")) {
intent.setDataAndType(uri, "video/*");
} else {
intent.setDataAndType(uri, "*/*");
}
//intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(intent, READ_FILE_REQUEST_CODE);
}
private void runGame() {
Intent GoToGame = new Intent(this, GameActivity.class);
startActivity(GoToGame);
}
// TODO Сделать номальную систему учета измения файлов
public static void observ(){
File save = new File(UtilitiesAndData.getInternalStorage() + File.separator + "files/var/nfstr_save.sb");
File fileOut = new File(UtilitiesAndData.getExternalStorage() + File.separator + "Log.txt");
File pathToSave = new File(UtilitiesAndData.getExternalStorage() + File.separator + "saves");
pathToSave.mkdir();
if(!fileOut.exists()) {
try {
fileOut.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
UtilitiesAndData.setLogger(fileOut);
observerThread = new Thread(() -> {
int count = 1;
byte[] lastMD5 = new byte[10];
while (true){
byte[] md5 = generateMD5(save);
if(!Arrays.equals(md5, lastMD5)) {
UtilitiesAndData.printLog(format.format(new Date()) + " | " + Utility.bytesToHexString(md5) + "\n");
File change = new File(pathToSave.getAbsolutePath() + File.separator + "nfs_save_change_"+ count +".sb");
try {
change.createNewFile();
copy(save, change);
} catch (IOException e) {
e.printStackTrace();
}
}
lastMD5 = md5;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
});
observerThread.start();
}
private <T> List<T> asList(T[] a){
return Arrays.asList(a);
}
// TODO реализовать сокрытие лишних папок
private List<File> asList(String path){
return asList(new File(path).listFiles());
}
private void updateLanguage(){
//Получаем текущий язык
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String current_lang = preferences.getString(getString(R.string.current_lang), "00");
if(current_lang.equals("00")) {
Log.e(LOG_TAG, "Not found currentLang preference(");
return;
}
if(current_lang.equals("sys"))
current_lang = Locale.getDefault().getLanguage();
byte[] current_lang_bytes = current_lang.getBytes();
//Открываем языковой файл и создаем поток чтения
File locale = new File(internalFiles + "/files/var/locale");
FileInputStream inputStream;
//Байтовое представление файла
byte[] bytes_locale = new byte[4];
try {
inputStream = new FileInputStream(locale);
inputStream.read(bytes_locale);
} catch (FileNotFoundException e) {
Log.wtf(LOG_TAG, "No found locale(((((");
return;
}catch (IOException e){
Log.wtf(LOG_TAG, "Couldn't read the locale file((((((");
return;
}
try {
if (
bytes_locale[2] != current_lang_bytes[0] &
bytes_locale[3] != current_lang_bytes[1]
) {
bytes_locale[2] = current_lang_bytes[0];
bytes_locale[3] = current_lang_bytes[1];
} else return;
}catch (Exception e){
return;
}
FileOutputStream outputStream;
try {
outputStream = new FileOutputStream(locale, false);
outputStream.write(bytes_locale, 0, 4);
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}
public void setResultListener(ResultListener resultListener) {
this.resultListener = resultListener;
}
public void updateListView(){
fileList.setAdapter(new FileAdapter(getApplicationContext(), asList(globalPath)));
}
}
@@ -1,72 +0,0 @@
package com.ea.ironmonkey.devmenu;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import com.ea.nimble.ApplicationLifecycle;
//Активность-марионетка для проверки работы нативных методов жизненного цикла
public class PuppetActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ApplicationLifecycle.onActivityCreate(savedInstanceState, this);
}
@Override
protected void onResume() {
super.onResume();
ApplicationLifecycle.onActivityResume(this);
}
@Override
protected void onStart() {
super.onStart();
ApplicationLifecycle.onActivityStart(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ApplicationLifecycle.onActivityDestroy(this);
}
@Override
public void onBackPressed() {
super.onBackPressed();
ApplicationLifecycle.onBackPressed();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
ApplicationLifecycle.onActivityResult(resultCode, requestCode, data, this);
}
@Override
protected void onPause() {
super.onPause();
ApplicationLifecycle.onActivityPause(this);
}
@Override
protected void onRestart() {
super.onRestart();
ApplicationLifecycle.onActivityRestart(this);
}
@Override
protected void onStop() {
super.onStop();
ApplicationLifecycle.onActivityStop(this);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
ApplicationLifecycle.onActivityRestoreInstanceState(savedInstanceState, this);
}
}
@@ -1,91 +0,0 @@
package com.ea.ironmonkey.devmenu;
import android.app.Activity;
import android.app.AlertDialog;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import androidx.annotation.Nullable;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.ea.games.nfs13_na.R;
import com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper;
import com.ea.ironmonkey.devmenu.util.UtilitiesAndData;
import java.util.ArrayList;
public class RecoverListActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean flag = true;
getActionBar().setTitle(R.string.recover_file_title);
ListView view = new ListView(this);
SQLiteDatabase database = new ReplacementDataBaseHelper(this).getDatabase();
Cursor cursor = database.rawQuery("SELECT " + ReplacementDataBaseHelper.PATH_TO_REPLACED_ELEMENT + " FROM " + ReplacementDataBaseHelper.MAIN_TABLE_NAME, null);
ArrayList<String> arrayList = new ArrayList<>();
ArrayList<String> fullNames = new ArrayList<>();
ArrayList<String> shortNames = new ArrayList<>();
while (cursor.moveToNext()) {
String string = cursor.getString(0);
fullNames.add(string);
int from = string.lastIndexOf("/files/");
shortNames.add(string.substring(from));
}
if(fullNames.isEmpty()){
shortNames.add("Не чего заменять!!");
flag = false;
}
boolean thereIsSmthToRecover = flag;
ArrayAdapter<String> adapter;
view.setOnItemClickListener((parent, view1, position, id) -> {
if(thereIsSmthToRecover){
TextView textView = (TextView) view1;
String s = textView.getText().toString();
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
//TODO сделать нормальные строки
dialog.setTitle("Воостановить?");
dialog.setPositiveButton(R.string.ok_title, (dialog1, which) -> {
shortNames.remove(s);
view.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, shortNames));
String fullName = fullNames.get(position);
fullNames.remove(fullName);
UtilitiesAndData.recoverFile(fullName);
//System.out.println();
//TODO Сделать воостановление
});
dialog.setNegativeButton(R.string.cancel_title, (dialog1, which) -> {
});
dialog.show();
}
});
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, shortNames);
view.setAdapter(adapter);
setContentView(view);
cursor.close();
}
}
@@ -1,136 +0,0 @@
package com.ea.ironmonkey.devmenu;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.view.MenuItem;
import com.ea.games.nfs13_na.BuildConfig;
import com.ea.games.nfs13_na.R;
import com.ea.ironmonkey.devmenu.dialog.OpenFileDialog;
import com.ea.ironmonkey.devmenu.util.SaveManager;
import com.ea.ironmonkey.devmenu.dialog.SvmwCreatorDialog;
import com.ea.ironmonkey.devmenu.dialog.SvmwInspectorDialog;
import com.ea.ironmonkey.devmenu.util.UtilitiesAndData;
import com.ea.nimble.ApplicationLifecycle;
import java.io.File;
public class SettingsActivity extends PreferenceActivity {
public static final String LOG_TAG = "SettingActivity";
private static final int PICKFILE_REQUEST_CODE = 128;
public static final int PICK_SVMW_REQUEST_CODE = 129;
public static final int PICK_SVMW_IN_CREATE = 228;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_xml);
ApplicationLifecycle.onActivityCreate(savedInstanceState, this);
String title = String.format(getString(R.string.dev_menu_title), BuildConfig.DEV_MENU_VERSION);
getActionBar().setTitle(title);
Preference chooseSaveFileButton = findPreference(getString(R.string.choose_save_file_title));
Preference chooseSVMWfileButton = findPreference(getString(R.string.choose_svmw_file_title));
Preference createSVMWfileButton = findPreference(getString(R.string.create_svmw_file_title));
Preference turnOffTheDevMenuButton = findPreference(getString(R.string.switch_off_devmenu_title));
final Context myContext = this;
turnOffTheDevMenuButton.setOnPreferenceClickListener(preference -> {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.switch_off_devmenu_title);
builder.setMessage(R.string.msg_devmenu_off);
builder.setPositiveButton(R.string.ok_title, (dialog, which) -> UtilitiesAndData.getDevMenuSwitcher().delete());
builder.setNegativeButton(R.string.cancel_title, null);
builder.show();
return true;
});
chooseSaveFileButton.setOnPreferenceClickListener(preference -> {
OpenFileDialog fileDialog = new OpenFileDialog(myContext);
fileDialog
.setFilter(".*\\.sb")
.setOpenDialogListener(fileName -> {
File save = new File(fileName);
SaveManager manager = new SaveManager(this);
manager.loadSaveFile(save);
});
fileDialog.show();
return true;
});
chooseSVMWfileButton.setOnPreferenceClickListener(preference -> {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
startActivityForResult(intent, PICK_SVMW_REQUEST_CODE);
//TODO реализовать выбор svmw
return true;
});
//По нажатии на кнопку создания svmw файла осуществляется переход в диалог создания svmw
createSVMWfileButton.setOnPreferenceClickListener(preference -> {
SvmwCreatorDialog dialog = new SvmwCreatorDialog(this);
dialog.show();
return true;
});
getActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(data != null) {
switch (requestCode) {
case PICKFILE_REQUEST_CODE: {
String s = data.getData().toString();
String s1 = s.replaceAll("file://", "");
File file = new File(s1);
}
break;
case PICK_SVMW_REQUEST_CODE: {
String s = data.getData().toString();
String s1 = s.replaceAll("file://", "");
File file = new File(s1);
SvmwInspectorDialog inspectorDialog = new SvmwInspectorDialog(this, file);
inspectorDialog.show();
}
break;
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}
@@ -1,60 +0,0 @@
package com.ea.ironmonkey.devmenu.components;
import android.content.Context;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/** Динамический список для контекстного меню файла LongPressContextMenu */
public class DynamicOptionsListView extends ListView {
/** Названия позиций в контекстном меню */
private List<String> names = new ArrayList<>();
private List<OptionAction> actions = new ArrayList<>();
private Context context;
public DynamicOptionsListView(Context context) {
super(context);
this.context = context;
updateList();
setOnItemClickListener((parent, view, position, id) -> {
try {
actions.get(position).action();
}catch (IndexOutOfBoundsException e){
Log.i("DynamicListView", "No found action to do( in position " + position);
}
});
}
private void updateList(){
setAdapter(
new ArrayAdapter<>(
context,
android.R.layout.simple_list_item_1,
names
));
}
public void addOption(String title, OptionAction action){
names.add(title);
actions.add(action);
updateList();
}
public void deleteOption(String title){
boolean removeInt = names.remove(title);
actions.remove(removeInt);
updateList();
}
public String deleteOption(int position){
String result = names.remove(position);
actions.remove(position);
updateList();
return result;
}
}
@@ -1,17 +0,0 @@
package com.ea.ironmonkey.devmenu.components;
public interface FileAction {
void actionReplaceFile();
void actionRecoverFile();
void actionRemoveFile();
void actionTrackTheFile();
void actionGetPropsOfFile();
void actionHideTheFile();
//sfhsadfhsdjf
}
@@ -1,205 +0,0 @@
package com.ea.ironmonkey.devmenu.components;
import static com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper.MAIN_TABLE_NAME;
import static com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper.NAME_OF_BACKUPED_ELEMENT;
import static com.ea.ironmonkey.devmenu.util.UtilitiesAndData.OPEN_FILE_ON_REPLACE_REQUEST;
import static com.ea.ironmonkey.devmenu.util.UtilitiesAndData.copy;
import static com.ea.ironmonkey.devmenu.util.UtilitiesAndData.getFileSize;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.widget.Toast;
import com.ea.games.nfs13_na.R;
import com.ea.ironmonkey.devmenu.MainActivity;
import com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper;
import com.ea.ironmonkey.devmenu.util.ResultListener;
import com.ea.ironmonkey.devmenu.util.UtilitiesAndData;
import java.io.File;
import java.io.IOException;
import java.text.CharacterIterator;
import java.text.SimpleDateFormat;
import java.text.StringCharacterIterator;
import java.util.Date;
import java.util.Random;
/**
* Контекстное меню управления данными
*/
public class LongPressContextMenu extends AlertDialog.Builder implements FileAction {
private File chosenFile;
private MainActivity activity;
private static final String LOG_TAG = "LongPressContextMenu";
private AlertDialog show;
private ReplacementDataBaseHelper dataBaseHelper;
private SQLiteDatabase writableDatabase;
private ContentValues values;
private File generateReplacementFile(){
Random random = new Random();
int index = random.nextInt();
index = (index < 0) ? index * -1 : index;
String nameReplacedOriginal = "replacement_" + index + "";
File original = new File(UtilitiesAndData.getReplacementsStorage() + File.separator + nameReplacedOriginal);
try {
original.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
return original;
}
public static String humanReadableByteCountSI(long bytes) {
if (-1000 < bytes && bytes < 1000) {
return bytes + " B";
}
CharacterIterator ci = new StringCharacterIterator("kMGTPE");
while (bytes <= -999_950 || bytes >= 999_950) {
bytes /= 1000;
ci.next();
}
return String.format("%.1f %cB", bytes / 1000.0, ci.current());
}
public LongPressContextMenu(MainActivity activity, String pathToChosenElem) {
super(activity);
this.activity = activity;
chosenFile = new File(pathToChosenElem);
DynamicOptionsListView optionsView = new DynamicOptionsListView(activity);
this.dataBaseHelper = new ReplacementDataBaseHelper(activity);
this.writableDatabase = dataBaseHelper.getDatabase();
this.values = new ContentValues();
optionsView.addOption(activity.getString(R.string.replace_file_title), this::actionReplaceFile);
optionsView.addOption(activity.getString(R.string.recover_file_title), this::actionRecoverFile);
optionsView.addOption(activity.getString(R.string.remove_file_title), this::actionRemoveFile);
optionsView.addOption(activity.getString(R.string.track_file_title), this::actionTrackTheFile);
optionsView.addOption(activity.getString(R.string.file_props_title), this::actionGetPropsOfFile);
optionsView.addOption(activity.getString(R.string.hide_file_title), this::actionHideTheFile);
setView(optionsView);
setTitle(chosenFile.getName()
+ " - " +
((chosenFile.isDirectory()) ?
activity.getString(R.string.folder_title) :
activity.getString(R.string.file_title)));
this.show = show();
}
@Override
public void actionReplaceFile() {
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.addCategory(Intent.CATEGORY_OPENABLE);
chooseFile.setType("text/plain");
activity.setResultListener(new ResultListener() {
@Override
public void onResult(Object object) {
//Реализовать замену и воостановление данных
Intent data;
if(object instanceof Intent)
data = (Intent) object;
else return;
String selectedFileToReplace = "";
selectedFileToReplace = data.getData().getPath();
//Создание файла куда будет складывться замена
File replacement = generateReplacementFile();
//Копирование выбранного оригинального файла в хранилище замен
//Иначе говоря, создание резервной копии
String path = chosenFile.getAbsolutePath();
copy(path, replacement.getPath());
//Непосредственная замена
copy(selectedFileToReplace, path);
values.put(NAME_OF_BACKUPED_ELEMENT, replacement.getName());
values.put(ReplacementDataBaseHelper.PATH_TO_REPLACED_ELEMENT, path);
//Запись в бд
writableDatabase.insert(MAIN_TABLE_NAME, null, values);
writableDatabase.close();
activity.updateListView();
show.cancel();
//TODO Язык!!!!
Toast.makeText(activity, "Заменено!", Toast.LENGTH_LONG).show();
}
});
activity.startActivityForResult(
Intent.createChooser(chooseFile, "Choose a file"),
OPEN_FILE_ON_REPLACE_REQUEST
);
}
@Override
public void actionRecoverFile() {
String path = chosenFile.getAbsolutePath();
UtilitiesAndData.recoverFile(path);
activity.updateListView();
show.cancel();
//дщд
}
@Override
public void actionRemoveFile() {
AlertDialog.Builder dialog = new AlertDialog.Builder(activity);
dialog.setTitle(activity.getString(R.string.remove_file_title));
String message = String.format(activity.getString(R.string.sure_remove_title), chosenFile.getName());
dialog.setMessage(message);
dialog.setPositiveButton(R.string.ok_title, (dialog1, which) -> {
UtilitiesAndData.deleteRecursive(chosenFile);
activity.updateListView();
});
dialog.setNegativeButton(R.string.cancel_title, null);
dialog.show();
}
@Override
public void actionTrackTheFile() {}
@Override
public void actionGetPropsOfFile() {
AlertDialog.Builder dialog = new AlertDialog.Builder(activity);
dialog.setTitle(chosenFile.getName()
+ " - " +
((chosenFile.isDirectory()) ?
activity.getString(R.string.folder_title) :
activity.getString(R.string.file_title)));
long lastModified = chosenFile.lastModified();
Date date = new Date(lastModified);
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss:SS");
String formattedDate = sdf.format(date);
long size = getFileSize(chosenFile);
dialog.setMessage(
activity.getString(R.string.file_lastmod_title) + "\n" +
formattedDate + "\n\n" +
activity.getString(R.string.file_size_title) + "\n" +
humanReadableByteCountSI(size) + " (" + size + " B)"
);
dialog.show();
}
@Override
public void actionHideTheFile() {
}
}
@@ -1,5 +0,0 @@
package com.ea.ironmonkey.devmenu.components;
public interface OptionAction {
void action();
}
@@ -1,246 +0,0 @@
package com.ea.ironmonkey.devmenu.dialog;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.ea.games.nfs13_na.R;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class OpenFileDialog extends AlertDialog.Builder {
private String currentPath = Environment.getExternalStorageDirectory().getPath();
private FilenameFilter filenameFilter;
private List<File> files = new ArrayList<File>();
private TextView title;
private ListView listView;
private int selectedIndex = -1;
public OpenFileDialog(Context context) {
super(context);
title = createTitle(context);
changeTitle();
LinearLayout linearLayout = createMainLayout(context);
linearLayout.addView(createBackItem(context));
files.addAll(getFiles(currentPath));
listView = createListView(context);
listView.setAdapter(new FileAdapter(context, files));
linearLayout.addView(listView);
setCustomTitle(title)
.setView(linearLayout)
.setPositiveButton(R.string.ok_title, (dialog, which) -> {
if (selectedIndex > -1 && listener != null) {
listener.OnSelectedFile(listView.getItemAtPosition(selectedIndex).toString());
}
})
.setNegativeButton(R.string.cancel_title, null);
}
@Override
public AlertDialog show() {
files.addAll(getFiles(currentPath));
listView.setAdapter(new FileAdapter(getContext(), files));
return super.show();
}
private <T> List<T> asList(T[] a){
return Arrays.asList(a);
}
private List<File> getFiles(String directoryPath){
File directory = new File(directoryPath);
List<File> fileList = asList(directory.listFiles(filenameFilter));
Collections.sort(fileList, (file, file2) -> {
if (file.isDirectory() && file2.isFile())
return -1;
else if (file.isFile() && file2.isDirectory())
return 1;
else
return file.getPath().compareTo(file2.getPath());
});
return fileList;
}
private TextView createTextView(Context context, int style) {
TextView textView = new TextView(context);
textView.setTextAppearance(context, style);
int itemHeight = getItemHeight(context);
textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, itemHeight));
textView.setMinHeight(itemHeight);
textView.setGravity(Gravity.CENTER_VERTICAL);
textView.setPadding(15, 0, 0, 0);
return textView;
}
private int getItemHeight(Context context) {
TypedValue value = new TypedValue();
DisplayMetrics metrics = new DisplayMetrics();
context.getTheme().resolveAttribute(android.R.attr.rowHeight, value, true);
getDefaultDisplay(context).getMetrics(metrics);
return (int)TypedValue.complexToDimension(value.data, metrics);
}
public int getTextWidth(String text, Paint paint) {
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return bounds.left + bounds.width() + 80;
}
private void changeTitle() {
String titleText = currentPath;
int screenWidth = getScreenSize(getContext()).x;
int maxWidth = (int) (screenWidth * 0.99);
if (getTextWidth(titleText, title.getPaint()) > maxWidth) {
while (getTextWidth("..." + titleText, title.getPaint()) > maxWidth)
{
int start = titleText.indexOf("/", 2);
if (start > 0)
titleText = titleText.substring(start);
else
titleText = titleText.substring(2);
}
title.setText("..." + titleText);
} else {
title.setText(titleText);
}
}
private TextView createTitle(Context context) {
TextView textView = new TextView(context);
textView.setTextAppearance(context, android.R.style.TextAppearance_DeviceDefault_DialogWindowTitle);
int itemHeight = getItemHeight(context);
textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, itemHeight));
textView.setMinHeight(itemHeight);
textView.setGravity(Gravity.CENTER_VERTICAL);
textView.setPadding(15, 0, 0, 0);
textView.setText(currentPath);
return textView;
}
private void RebuildFiles(ArrayAdapter<File> adapter) {
try{
List<File> fileList = getFiles(currentPath);
files.clear();
selectedIndex = -1;
files.addAll(fileList);
adapter.notifyDataSetChanged();
changeTitle();
} catch (NullPointerException e){
Toast.makeText(getContext(), android.R.string.unknownName, Toast.LENGTH_SHORT).show();
}
}
public OpenFileDialog setFilter(final String filter) {
filenameFilter = (file, fileName) -> {
File tempFile = new File(String.format("%s/%s", file.getPath(), fileName));
if (tempFile.isFile())
return tempFile.getName().matches(filter);
return true;
};
return this;
}
private ListView createListView(Context context) {
ListView listView = new ListView(context);
listView.setOnItemClickListener((adapterView, view, index, l) -> {
FileAdapter adapter = (FileAdapter) adapterView.getAdapter();
File file = adapter.getItem(index);
if (file.isDirectory()) {
currentPath = file.getPath();
RebuildFiles(adapter);
} else {
if (index != selectedIndex)
selectedIndex = index;
else
selectedIndex = -1;
adapter.notifyDataSetChanged();
}
});
return listView;
}
private static Display getDefaultDisplay(Context context) {
return ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
}
private static Point getScreenSize(Context context) {
Point screeSize = new Point();
getDefaultDisplay(context).getSize(screeSize);
return screeSize;
}
private LinearLayout createMainLayout(Context context) {
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setMinimumHeight(750);
return linearLayout;
}
private TextView createBackItem(Context context) {
TextView textView = createTextView(context, android.R.style.TextAppearance_DeviceDefault_Small);
Drawable drawable = getContext().getResources().getDrawable(android.R.drawable.ic_menu_directions);
drawable.setBounds(0, 0, 60, 60);
textView.setCompoundDrawables(drawable, null, null, null);
textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
textView.setOnClickListener(view -> {
File file = new File(currentPath);
File parentDirectory = file.getParentFile();
if (parentDirectory != null) {
currentPath = parentDirectory.getPath();
RebuildFiles(((FileAdapter) listView.getAdapter()));
}
});
return textView;
}
class FileAdapter extends ArrayAdapter<File> {
public FileAdapter(Context context, List files) {
super(context, android.R.layout.simple_list_item_1, files);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getView(position, convertView, parent);
File file = getItem(position);
view.setText(file.getName());
if (selectedIndex == position)
view.setBackgroundColor(getContext().getResources().getColor(android.R.color.holo_blue_light));
else
view.setBackgroundColor(getContext().getResources().getColor(android.R.color.background_dark));
return view;
}
}
public interface OpenDialogListener{
void OnSelectedFile(String fileName);
}
private OpenDialogListener listener;
public OpenFileDialog setOpenDialogListener(OpenDialogListener listener) {
this.listener = listener;
return this;
}
}
@@ -1,95 +0,0 @@
package com.ea.ironmonkey.devmenu.dialog;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import com.ea.games.nfs13_na.R;
import com.ea.ironmonkey.devmenu.util.SaveManager;
import com.ea.ironmonkey.devmenu.util.UtilitiesAndData;
import java.io.File;
import java.io.IOException;
/**
* Диалог для содания бандлов
* Сам умеет их создавать
*/
public class SvmwCreatorDialog extends AlertDialog {
private EditText nameEdit;
private EditText desEdit;
private CheckBox isUseCurSaveBox;
private View mainView;
private boolean useCurrentSave;
private SaveManager manager;
private Context context;
private File svmwPath;
public SvmwCreatorDialog(Activity activity) {
super(activity);
context = activity.getApplicationContext();
svmwPath = new File(UtilitiesAndData.getExternalStorage() + File.separator + "svmw");
svmwPath.mkdir();
setTitle("Создание SVMW");
ImageButton a;
Button s;
mainView = LayoutInflater
.from(context)
.inflate(R.layout.saves, null, false);
nameEdit = (EditText) mainView.findViewById(R.id.name_svmw);
desEdit = (EditText) mainView.findViewById(R.id.des_svmw);
isUseCurSaveBox = (CheckBox) mainView.findViewById(R.id.isUseCurrentSave);
manager = new SaveManager(context);
//Конпка создания
setButton(context.getText(R.string.create_svmw_file_title), (dialog, witch) -> {
String name = getTextFrom(nameEdit);
String des = getTextFrom(desEdit);
if(name.isEmpty() | des.isEmpty()){
Toast.makeText(context, context.getText(R.string.toast_strings_must_be_entered), Toast.LENGTH_LONG).show();
return;
}
File to = new File(svmwPath.getAbsolutePath() + File.separator + name + ".svmw");
try {
to.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
manager.createBundleFile(des, to, UtilitiesAndData.getSaveFile());
});
//Кнопка отмены
setButton2(context.getText(R.string.cancel_title), (OnClickListener) null);
//Кнопка выбора отдельного файла
setButton3(context.getString(R.string.choose_svmw_file_title), (dialog, witch) -> {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
getOwnerActivity().startActivityForResult(intent, 228);
});
isUseCurSaveBox.setOnCheckedChangeListener((buttonView, isChecked) -> getButton(AlertDialog.BUTTON3).setEnabled(!isChecked));
// Если включена опция "Использовать текущее сохранение" то заюлокировтаь кнопку выбора файла сохранения
setView(mainView);
}
private String getTextFrom(EditText editText){
return editText.getText().toString();
}
}
@@ -1,66 +0,0 @@
package com.ea.ironmonkey.devmenu.dialog;
import android.app.AlertDialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.ea.games.nfs13_na.R;
import com.ea.ironmonkey.devmenu.util.SaveManager;
import java.io.File;
import java.util.Date;
/**
* Диалог выбора и просмотра информации об svmw файле
*/
public class SvmwInspectorDialog extends AlertDialog {
private SaveManager manager;
private View mainView;
private boolean isWork;
private TextView description;
private TextView time;
public SvmwInspectorDialog(Context context, File svmw) {
super(context);
manager = new SaveManager(context);
//Если пришедший файл - svmw иницализируем работу с ним если нет
// то выходим
// и ничего интересного не показываем((
isWork = manager.isSvmwFile(svmw);
if(isWork){
setTitle("Файл - " + svmw.getName());
mainView = LayoutInflater
.from(context)
.inflate(R.layout.inspector, null, false);
description = (TextView) mainView.findViewById(R.id.description);
description.setText(manager.getDescriptionOf(svmw));
time = (TextView) mainView.findViewById(R.id.date);
Date dateOfCreate = manager.getDateOfCreateOf(svmw);
String format = SaveManager.dateFormat.format(dateOfCreate);
time.setText(time.getText() + ": " + format);
setButton(context.getString(R.string.title_load_svmw), (dialog, which) -> {
manager.loadBundleFile(svmw);
});
setButton2(context.getString(R.string.cancel_title), (OnClickListener) null);
setView(mainView);
}else Toast.makeText(context, "Это не svmw!", Toast.LENGTH_LONG).show();
}
@Override
public void show() {
if(isWork) super.show();
}
}
@@ -1,110 +0,0 @@
package com.ea.ironmonkey.devmenu.util;
import android.util.Log;
public class Observer {
private static final String LOG_TAG = "Observer";
public static void onCallingMethod(Method... states){
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
Log.i(LOG_TAG, "info{");
if(states.length != 0){
Log.i(LOG_TAG, "States of method:");
for(Method mthd : states){
Log.i(LOG_TAG, "\t" + mthd.title);
}
Log.i(LOG_TAG, "\n");
}
for(int i = 1; i < stackTrace.length; i++) {
Log.i(LOG_TAG, "\t" + stackTrace[i]);
}
Log.i(LOG_TAG, "}");
}
private interface MethodCallingCounter{
void call();
}
/** Перечисление состояний методов при из анализе и изменении, доработке */
public enum Method implements MethodCallingCounter{
/** Состояние невозможгости декомпиляции */
IMPOSSIBLE_TO_DECOMPILE("Impossible to decompile"){
@Override
public void call() {
}
},
/** Уровни подозртельности работы методов при их воостановлении после
декомпиляции, или их доработке и изменеии.
/** Зеленая зона. Небольшие подозрения */
SUSPICIOUS_METHOD("Suspicious method"){
@Override
public void call() {
}
},
/** Желтая зона. уже более подозрительны метод, что ставит под вопрос корректоность отрработки некторого функционала */
VERY_SUSPICIOUS_METHOD("Very suspicious Method") {
@Override
public void call() {
}
},
/** Красная зона. Опасный метод который может привести к фатальным ошибкам */
HAZARD_METHOD("Hazard method") {
@Override
public void call() {
}
},
/** Уровни воостонавливаемости кода */
HARD_TO_RECOVER_LOGIC("Hard to recover logic of method") {
@Override
public void call() {
}
},
ON_CATCHING_EXCEPTION("on catching exception") {
@Override
public void call() {
}
},
RETURN_NULL("Method returns null") {
@Override
public void call() {
}
},
SOME_PACKAGE_IS_DELETED("Some package is deleted"){
@Override
public void call() {
}
};
private String title;
Method(String title) {
this.title = title;
//this.call();
}
}
}
@@ -1,34 +0,0 @@
package com.ea.ironmonkey.devmenu.util;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class ReplacementDataBaseHelper extends SQLiteOpenHelper {
public static final String MAIN_TABLE_NAME = "Replacements";
public static final String PATH_TO_REPLACED_ELEMENT = "Path";
public static final String NAME_OF_BACKUPED_ELEMENT = "Original_element";
private static final int DATABASE_VERSION = 1;
public SQLiteDatabase getDatabase() {
return database;
}
private SQLiteDatabase database;
public ReplacementDataBaseHelper(Context context) {
super(context, MAIN_TABLE_NAME + ".db", (SQLiteDatabase.CursorFactory) (db, masterQuery, editTable, query) -> null, DATABASE_VERSION);
database = context.openOrCreateDatabase(MAIN_TABLE_NAME + ".db", Context.MODE_PRIVATE, null);
database.execSQL("CREATE TABLE IF NOT EXISTS " + MAIN_TABLE_NAME + " (_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ PATH_TO_REPLACED_ELEMENT + " TEXT,"
+ NAME_OF_BACKUPED_ELEMENT + " TEXT);");
}
@Override
public void onCreate(SQLiteDatabase db) {}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}
@@ -1,7 +0,0 @@
package com.ea.ironmonkey.devmenu.util;
public interface ResultListener {
default void onResult(Object data){}
}
@@ -1,186 +0,0 @@
package com.ea.ironmonkey.devmenu.util;
import android.content.Context;
import android.util.Log;
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.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Менедженер создания и загрузки сохранений в игру<br/>
* Создает bundle-файлы .svmw и загружает их<br/>
* Умеет загружать обчные .sb сохранения в игру
*/
public class SaveManager {
private Context context;
private static final String LOG_TAG = "SaveManager";
private static final byte[] svmw_header = "SVMW".getBytes(StandardCharsets.UTF_8);
private static final byte[] save_header = "SBIN".getBytes(StandardCharsets.UTF_8);
public static final String dateFormatStr = "dd.MM.yy:hh:mm:ss";
public static final SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
public SaveManager(Context context) {
this.context = context;
}
public File createBundleFile(String description, File fileToSave, File save) {
if (fileToSave.exists()) fileToSave.delete();
try {
fileToSave.createNewFile();
FileOutputStream fos = new FileOutputStream(fileToSave);
Date date = new Date();
Long time = date.getTime();
ByteBuffer bb = ByteBuffer.allocate(Long.SIZE);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.putLong(time);
bb.flip();
//bb.
String curDate = dateFormat.format(new Date());
fos.write(svmw_header);
fos.write(curDate.getBytes(StandardCharsets.UTF_8));
fos.write(description.getBytes(StandardCharsets.UTF_8));
fos.write(UtilitiesAndData.fileAsByteArray(save));
} catch (IOException e) {
Log.i("lol", fileToSave.getAbsolutePath());
//fileToSave.getAbsolutePath()
e.printStackTrace();
}
return fileToSave;
}
public void loadBundleFile(File svmw) {
if(isSvmwFile(svmw)){
byte[] byteFile = UtilitiesAndData.fileAsByteArray(svmw);
int headerInByteFile = UtilitiesAndData.findHeaderInByteFile(byteFile, save_header);
byte[] result = new byte[byteFile.length - headerInByteFile];
System.arraycopy(byteFile, headerInByteFile, result, 0, result.length);
File dest = new File("/data/data/" + context.getPackageName() + "/files/var/nfstr_save.sb");
if(!dest.exists()) {
try {
dest.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
FileOutputStream fos = new FileOutputStream(dest);
fos.write(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public String getDescriptionOf(File svmw){
if(isSvmwFile(svmw)){
int offset = svmw_header.length + dateFormatStr.length();
byte[] byteFile = UtilitiesAndData.fileAsByteArray(svmw);
int headerInByteFile = UtilitiesAndData.findHeaderInByteFile(byteFile, save_header);
return new String(byteFile, offset, headerInByteFile - offset, StandardCharsets.UTF_8);
}
Log.i(LOG_TAG, "getDescription(), this is not a svmw file((( Return empty description(((");
return "";
}
public Date getDateOfCreateOf(File svmw){
if(isSvmwFile(svmw)){
int offset = svmw_header.length;
byte[] byteFile = UtilitiesAndData.fileAsByteArray(svmw);
String s = new String(byteFile, offset, dateFormatStr.length(), StandardCharsets.UTF_8);
try {
return dateFormat.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
}
Log.i(LOG_TAG, "getDateOfCreateOf, this is not a svmw file((( Return null date(((");
return null;
}
public void loadSaveFile(File save) {
if(isSaveFile(save)){
copySave(save);
}
}
public boolean isSaveFile(File save) {
if(!save.exists() | isEmptyFile(save)) return false;
byte[] arr = UtilitiesAndData.fileAsByteArray(save);
for (int i = 0; i < save_header.length; i++)
if (save_header[i] != arr[i]) return false;
return true;
}
public boolean isSvmwFile(File svmw) {
if(!svmw.exists() | isEmptyFile(svmw)) return false;
byte[] arr = UtilitiesAndData.fileAsByteArray(svmw);
for (int i = 0; i < svmw_header.length; i++)
if (svmw_header[i] != arr[i]) return false;
return true;
}
public boolean isEmptyFile(File file){
return UtilitiesAndData.fileAsByteArray(file).length == 0;
}
public void copySave(File save){
File source = save;
File dest = new File("/data/data/" + context.getPackageName() + "/files/var/nfstr_save.sb");
if(!dest.exists()) {
try {
dest.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
is.close();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@@ -1,290 +0,0 @@
package com.ea.ironmonkey.devmenu.util;
import static com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper.MAIN_TABLE_NAME;
import static com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper.NAME_OF_BACKUPED_ELEMENT;
import static com.ea.ironmonkey.devmenu.util.ReplacementDataBaseHelper.PATH_TO_REPLACED_ELEMENT;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.util.Log;
import org.apache.commons.codec.digest.DigestUtils;
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.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class UtilitiesAndData {
private static Context context;
private static FileOutputStream stream;
public static final int OPEN_FILE_ON_REPLACE_REQUEST = 100;
public static final int READ_FILE_REQUEST_CODE = 101;
private static final String LOG_TAG = "UtilitiesAndData";
public static void init(Context context){
UtilitiesAndData.context = context;
}
public static void setLogger(File file){
if(file.exists()){
try {
stream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
Log.wtf(LOG_TAG, "cant create out stream(((");
e.printStackTrace();
}
}
}
public static void deleteRecursive(File fileOrDirectory) {
if (fileOrDirectory.isDirectory())
for (File child : fileOrDirectory.listFiles())
deleteRecursive(child);
fileOrDirectory.delete();
}
public static boolean isLoggerEnabled(){
return stream != null;
}
public static void printLog(String msg){
try{
if(isLoggerEnabled())
stream.write(msg.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
Log.wtf(LOG_TAG, "cant write to stream(((");
e.printStackTrace();
}
}
public static String getInternalStorage(){
return "/data/data/" + context.getPackageName();
}
public static String getExternalStorage(){
return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + context.getPackageName() + "/files";
}
public static File getDevMenuSwitcher(){
return new File(UtilitiesAndData.getExternalStorage() + File.separator + "DevMenu");
}
public static File getSaveFile(){
File save = new File(getInternalStorage() + File.separator + "files" + File.separator + "var" + File.separator + "nfstr_save.sb");
if(!save.exists()) {
try {
save.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return save;
}
public static String getReplacementsStorage(){
return getInternalStorage() + File.separator + "replace";
}
public static boolean isFirstRun(){
File temp = new File(getInternalStorage() + File.separator + "load");
try {
if(!temp.exists()){
temp.createNewFile();
return true;
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private static final String[] exclusionNamesArr = {
"replace",
"lib",
"databases"
};
public static void copy(File from, File to){
copy(from.getAbsolutePath(), to.getAbsolutePath());
}
public static void copy(String from, String to) {
File source = new File(from);
File dest = new File(to);
if (!dest.exists()) {
try {
dest.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
Math.max(getFileSize(source), getFileSize(dest));
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
is.close();
os.close();
} catch (FileNotFoundException e) {
Log.e("lol", e.toString());
e.printStackTrace();
} catch (IOException e) {
Log.e("lol1", e.toString());
e.printStackTrace();
}
}
public static long getFileSize(final File file) {
if (file == null || !file.exists())
return 0;
if (!file.isDirectory())
return file.length();
final List<File> dirs = new LinkedList<>();
dirs.add(file);
long result = 0;
while (!dirs.isEmpty()) {
final File dir = dirs.remove(0);
if (!dir.exists())
continue;
final File[] listFiles = dir.listFiles();
if (listFiles == null || listFiles.length == 0)
continue;
for (final File child : listFiles) {
result += child.length();
if (child.isDirectory())
dirs.add(child);
}
}
return result;
}
private static final Set<String> exclusionNames = new HashSet<>(Arrays.asList(exclusionNamesArr));
public static boolean isExclusionName(String name){
return exclusionNames.contains(name);
}
public static void recoverFile(String path){
ReplacementDataBaseHelper dataBaseHelper = new ReplacementDataBaseHelper(context);
SQLiteDatabase writableDatabase = dataBaseHelper.getDatabase();
Cursor query = writableDatabase.rawQuery("SELECT " + PATH_TO_REPLACED_ELEMENT + " , " + NAME_OF_BACKUPED_ELEMENT + " FROM " + MAIN_TABLE_NAME + " WHERE " + PATH_TO_REPLACED_ELEMENT + " = \"" + path + "\"", null);
if(query.getCount() == 1) {
query.moveToFirst();
//Путь к заменяемому файлу
String pathToReplace = query.getString(query.getColumnIndex(PATH_TO_REPLACED_ELEMENT));
//Имя бэкапа
String nameFile = query.getString(query.getColumnIndex(NAME_OF_BACKUPED_ELEMENT));
//Файл замены
File toReplace = new File(pathToReplace);
//Файл бэкапа
File backup = new File(UtilitiesAndData.getReplacementsStorage() + File.separator + nameFile);
copy(backup, toReplace);
writableDatabase.delete(MAIN_TABLE_NAME, PATH_TO_REPLACED_ELEMENT + " = ?", new String[]{path});
backup.delete();
}
query.close();
}
public static byte[] generateMD5(File file){
try {
return DigestUtils.md5(new FileInputStream(file));
} catch (IOException e) {
e.printStackTrace();
}
return new byte[1];
}
public static void getInfoAboutFile(File file){
Log.i(LOG_TAG, "Info about File -> " + file.getAbsolutePath());
if(file.exists()){
if(file.isFile()) {
Log.i(LOG_TAG, "isCanRead = " + file.canRead());
Log.i(LOG_TAG, "isCanWrite = " + file.canWrite());
Log.i(LOG_TAG, "isCanExecute = " + file.canExecute());
}else
Log.i(LOG_TAG, "its dir!");
}else
Log.wtf(LOG_TAG, "it does not exists!");
}
public static byte[] fileAsByteArray(File file){
byte[] b = new byte[(int) file.length()];
try {
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(b);
} catch (Exception e) {
return null;
}
return b;
}
public static void saveBytesToFile(byte[] bytes, File saveTo){
try{
saveTo.createNewFile();
FileOutputStream outputStream = new FileOutputStream(saveTo);
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
public static int findHeaderInByteFile(byte[] byteFile, byte[] header){
int[] pf = prefix(header);
int index = 0;
for (int i = 0; i < byteFile.length; i++){
while (index > 0 && header[index] != byteFile[i]) index = pf[index - 1];
if (header[index] == byteFile[i]) index++;
if (index == header.length) return i - index + 1;
}
return -1;
}
/**
* Префикс функция для алгоритма КМП
*/
private static int[] prefix(byte[] s) {
int[] result = new int[s.length];
result[0] = 0;
int index = 0;
for (int i = 1; i < s.length; i++) {
while (index >= 0 && s[index] != s[i]) { index--; }
index++;
result[i] = index;
}
return result;
}
}