├── .gitignore
├── .gitmodules
├── .idea
├── gradle.xml
└── runConfigurations.xml
├── COPYING
├── README.txt
├── app
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ └── fonts
│ │ └── default-1.1.7.ttf
│ ├── java
│ ├── com
│ │ └── onscripter
│ │ │ └── plus
│ │ │ ├── ActivityPlus.java
│ │ │ ├── App.java
│ │ │ ├── ChangeLog.java
│ │ │ ├── CopyFilesDialogTask.java
│ │ │ ├── DataDownloader.java
│ │ │ ├── Environment2.java
│ │ │ ├── ExtSDCardFix.java
│ │ │ ├── FileSystemAdapter.java
│ │ │ ├── FolderBrowserDialogPreference.java
│ │ │ ├── FolderBrowserDialogWrapper.java
│ │ │ ├── GameUtils.java
│ │ │ ├── ImageButton2.java
│ │ │ ├── LauncherActivity.java
│ │ │ ├── ListPreferencePlus.java
│ │ │ ├── ONScripter.java
│ │ │ ├── ONScripterGame.java
│ │ │ ├── ProgressDialogAsyncTask.java
│ │ │ ├── Settings.java
│ │ │ ├── TwoStateLayout.java
│ │ │ ├── UnicodeUtil.java
│ │ │ ├── VNPreferences.java
│ │ │ ├── VNSettingsDialog.java
│ │ │ ├── ViewAdapterBase.java
│ │ │ ├── bugtracking
│ │ │ ├── BugTrackingService.java
│ │ │ ├── ModifyServerRequest.java
│ │ │ ├── ONScripterTracer.java
│ │ │ └── TracedONScripterView.java
│ │ │ └── settings
│ │ │ ├── AboutSettingsFragment.java
│ │ │ ├── GeneralSettingsFragment.java
│ │ │ └── LayoutPreference.java
│ └── jrummy
│ │ └── sdfix
│ │ ├── Remounter.java
│ │ ├── SDFix.java
│ │ └── Shell.java
│ ├── libs
│ └── android-support-v4.jar
│ └── res
│ ├── drawable-hdpi
│ ├── ic_action_new.png
│ ├── ic_action_new_dark.png
│ ├── ic_action_phone.png
│ ├── ic_action_phone_dark.png
│ ├── ic_action_sd_storage.png
│ ├── ic_action_sd_storage_dark.png
│ └── icon.png
│ ├── drawable-ldpi
│ └── icon.png
│ ├── drawable-mdpi
│ ├── ic_action_new.png
│ ├── ic_action_new_dark.png
│ ├── ic_action_phone.png
│ ├── ic_action_phone_dark.png
│ ├── ic_action_sd_storage.png
│ ├── ic_action_sd_storage_dark.png
│ └── icon.png
│ ├── drawable-xhdpi
│ ├── ic_action_new.png
│ ├── ic_action_new_dark.png
│ ├── ic_action_phone.png
│ ├── ic_action_phone_dark.png
│ ├── ic_action_sd_storage.png
│ ├── ic_action_sd_storage_dark.png
│ └── icon.png
│ ├── drawable-xxhdpi
│ ├── ic_action_new.png
│ ├── ic_action_new_dark.png
│ ├── ic_action_phone.png
│ ├── ic_action_phone_dark.png
│ ├── ic_action_sd_storage.png
│ ├── ic_action_sd_storage_dark.png
│ └── icon.png
│ ├── drawable-xxxhdpi
│ └── icon.png
│ ├── drawable
│ ├── dark_divider.xml
│ ├── ic_action_save.png
│ ├── ic_file_dark.png
│ ├── ic_file_light.png
│ ├── ic_folder_dark.png
│ ├── ic_folder_light.png
│ ├── ic_folder_up_dark.png
│ ├── ic_folder_up_light.png
│ ├── ic_menu_change_folder.png
│ ├── light_divider.xml
│ ├── menu_auto.png
│ ├── menu_auto_selected.png
│ ├── menu_back.png
│ ├── menu_change_speed.png
│ ├── menu_change_speed_selected.png
│ ├── menu_mouse_right_click.png
│ ├── menu_mouse_scroll_down.png
│ ├── menu_mouse_scroll_up.png
│ ├── menu_settings.png
│ ├── menu_skip.png
│ └── menu_skip_selected.png
│ ├── layout
│ ├── about_preference_layout.xml
│ ├── change_log_entry.xml
│ ├── copy_file_dialog.xml
│ ├── dialog_preference.xml
│ ├── file_system_layout.xml
│ ├── fix_dialog.xml
│ ├── folder_browser_dialog.xml
│ ├── main.xml
│ ├── onscripter.xml
│ ├── radiobutton_choice_item.xml
│ ├── sdcard_fix_su_dialog.xml
│ ├── selective_file_dialog.xml
│ ├── selective_file_item.xml
│ ├── vnsettings_dialog.xml
│ ├── vnsettings_dialog_controls.xml
│ └── vnsettings_dialog_text.xml
│ ├── menu
│ └── menu_launcher.xml
│ ├── values-ja
│ ├── change_log.xml
│ └── strings.xml
│ ├── values-ko
│ ├── change_log.xml
│ └── strings.xml
│ ├── values-ru
│ ├── change_log.xml
│ └── strings.xml
│ ├── values-xlarge
│ └── dimens.xml
│ ├── values-zh
│ ├── change_log.xml
│ └── strings.xml
│ ├── values
│ ├── attrs.xml
│ ├── change_log.xml
│ ├── dimens.xml
│ ├── hidden_strings.xml
│ ├── strings.xml
│ ├── style.xml
│ └── themes.xml
│ └── xml
│ ├── about_settings.xml
│ ├── general_settings.xml
│ └── settings_header.xml
├── build.gradle
├── design
├── buttons.psd
├── feature-image.psd
├── folder.psd
├── icon.psd
└── screenshots
│ ├── ja
│ ├── screenshot1.png
│ ├── screenshot2.png
│ ├── screenshot3.png
│ ├── screenshot4.png
│ ├── screenshot5.png
│ └── screenshot6.png
│ ├── ko
│ ├── screenshot1.png
│ ├── screenshot2.png
│ ├── screenshot3.png
│ ├── screenshot4.png
│ └── screenshot5.png
│ ├── ru
│ ├── screenshot1.png
│ ├── screenshot2.png
│ ├── screenshot3.png
│ ├── screenshot4.png
│ ├── screenshot5.png
│ └── screenshot6.png
│ ├── screenshot1.png
│ ├── screenshot2.png
│ ├── screenshot3.png
│ ├── screenshot4.png
│ ├── screenshot5.png
│ ├── screenshot6.png
│ ├── screenshot7.png
│ └── screenshot8.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | build/
3 | obj/
4 |
5 | # Crashlytics configuations
6 | com_crashlytics_export_strings.xml
7 |
8 | # Local configuration file (sdk path, etc)
9 | local.properties
10 |
11 | # Gradle generated files
12 | .gradle/
13 |
14 | # Signing files
15 | .signing/
16 |
17 | # User-specific configurations
18 | .idea/libraries/
19 | .idea/workspace.xml
20 | .idea/tasks.xml
21 | .idea/.name
22 | .idea/compiler.xml
23 | .idea/copyright/profiles_settings.xml
24 | .idea/encodings.xml
25 | .idea/misc.xml
26 | .idea/modules.xml
27 | .idea/scopes/scope_settings.xml
28 | .idea/vcs.xml
29 | *.iml
30 |
31 | # OS-specific files
32 | .DS_Store
33 | .DS_Store?
34 | ._*
35 | .Spotlight-V100
36 | .Trashes
37 | ehthumbs.db
38 | Thumbs.db
39 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "libs/VPlayer_lib"]
2 | path = VPlayer_lib
3 | url = git@github.com:matthewn4444/VPlayer_lib.git
4 | [submodule "libs/onscripter-engine-android"]
5 | path = onscripter-engine-android
6 | url = git@github.com:matthewn4444/onscripter-engine-android.git
7 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | This repository is not active anymore. (Oct 18, 2021)
2 |
3 | ===========================
4 | Onscripter Plus For Android
5 | ===========================
6 | December 27, 2013
7 |
8 | Fork of Onscripter for Android (http://onscripter.sourceforge.jp/android/android.html)
9 | that is compiled on Windows including full source (with dependencies).
10 |
11 | This Android application allows you to play visual novel games using the NScripter engine
12 | on your Android device.
13 |
14 |
15 | Steps to Compile
16 | ================
17 | 1. Install Java [https://www.java.com/en/] (match bit with Eclipse, probably get 32-bit)
18 | 2. Install Eclipse with Android SDK [https://developer.android.com/sdk/index.html] (32bit probably)
19 | 3. Run the "Android SDK Manager" and install:
20 | - Tools/ - All
21 | - Android 2.2 (API 8) - All
22 | - Extras/ -> Support Repo, Support Library, Google USB Driver, Google Web Driver
23 | - [OPTIONAL] Android 4.0 (API 14) and/or anything newer
24 | 4. [WINDOWS] Install Cywin [http://cygwin.com/install.html]
25 | - When choosing what to install, only install:
26 | DLevel -> make
27 | 5. [WINDOWS] Set up the environment variable for cygwin in PATH (to the bin folder)
28 | C:\/bin;
29 | 6. Install the NDK [http://developer.android.com/tools/sdk/ndk/index.html] (Doesn't matter the bit)
30 | 7. Setup NDK in Eclipse:
31 | - Open Eclipse
32 | - Window -> Preference -> Android -> NDK -> [Browse the location of the NDK folder]
33 | C:\\android-ndk
34 | 8. Git clone this repo a folder
35 | 9. Open Eclipse and Import the project
36 | - Open Eclipse
37 | - File -> Import... -> Android -> Existing Android Code Into Workspace -> [Then find the repo]
38 | 10. Add Native Support to project:
39 | - Right click ONScripterPlus -> Android Tools -> Add Native Support (If no option, then you already have native support)
40 | 11. [WINDOWS] Open file "/jni/application/Android.mk"
41 | - Change the part of APP_SUBDIR of "C:\Programming\cygwin64\bin\find" to cygwin "find"
42 | 11. [WINDOWS] Open file "/jni/freetype/Android.mk"
43 | - Change the part of APP_SUBDIR of "C:\Programming\cygwin64\bin\find" to cygwin "find"
44 | 11. Build the project (ONScipter takes a while to build) and run on device
45 |
46 |
47 | Change version of ONScripter
48 | ============================
49 | 1. Download new version of ONScripter source code based on your operating system from http://onscripter.sourceforge.jp/onscripter.html
50 | 2. Delete the folder "/jni/application/onscripter-*" (e.g. /onscripter-20130202)
51 | 3. Extract the folder "onscripter-*" (e.g. onscripter-20130202) source into "/jni/application"
52 | 4. Rebuild the code from Eclipse
53 |
54 |
55 | Play Visual Novel
56 | =================
57 | 1. Download a visual novel game that uses NScripter
58 | 2. Plug Android device in computer and navigate to the internal memory of the Android device
59 | 3. Make a new folder "ons"
60 | 4. Place the game folder into "ons" folder
61 | 5. [OPTIONAL] Place a font (Japanese preferably) into the game folder and name it "default.ttf"
62 | - if no font is provided, it will use a default font
63 | 6. You can delete the dll files
64 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | applicationId "com.onscripter.plus"
9 | minSdkVersion 16
10 | targetSdkVersion 22
11 | versionCode 6
12 | versionName "1.2.4"
13 | }
14 |
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | }
22 |
23 | dependencies {
24 | compile fileTree(dir: 'libs', include: ['*.jar'])
25 | compile project(':onscripter-engine-android')
26 | compile project(':VPlayer_library')
27 | compile files('src/main/libs/android-support-v4.jar')
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/default-1.1.7.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/assets/fonts/default-1.1.7.ttf
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/ActivityPlus.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import android.support.v4.app.FragmentActivity;
4 |
5 |
6 | public abstract class ActivityPlus extends FragmentActivity {
7 |
8 | private OnLifeCycleListener mListener;
9 |
10 | public static abstract class OnLifeCycleListener {
11 | public void onStart() {}
12 | public void onStop() {}
13 | public void onPause() {}
14 | public void onResume() {}
15 | public void onRestart() {}
16 | public void onBackPressed() {}
17 | public void onDestroy() {}
18 | }
19 |
20 | public void setOnLifeCycleListener(OnLifeCycleListener listener) {
21 | mListener = listener;
22 | }
23 |
24 | @Override
25 | protected void onStart() {
26 | super.onStart();
27 | if (mListener != null) {
28 | mListener.onStart();
29 | }
30 | }
31 |
32 | @Override
33 | protected void onStop() {
34 | super.onStop();
35 | if (mListener != null) {
36 | mListener.onStart();
37 | }
38 | }
39 |
40 | @Override
41 | protected void onPause() {
42 | super.onPause();
43 | if (mListener != null) {
44 | mListener.onPause();
45 | }
46 | }
47 |
48 | @Override
49 | protected void onRestart() {
50 | super.onRestart();
51 | if (mListener != null) {
52 | mListener.onRestart();
53 | }
54 | }
55 |
56 | @Override
57 | protected void onResume() {
58 | super.onResume();
59 | if (mListener != null) {
60 | mListener.onResume();
61 | }
62 | }
63 |
64 | @Override
65 | public void onBackPressed() {
66 | super.onBackPressed();
67 | if (mListener != null) {
68 | mListener.onBackPressed();
69 | }
70 | }
71 |
72 | @Override
73 | protected void onDestroy() {
74 | super.onDestroy();
75 | if (mListener != null) {
76 | mListener.onDestroy();
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/App.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | public final class App extends Application {
7 | private static Context StaticContext;
8 |
9 | @Override
10 | public void onCreate() {
11 | super.onCreate();
12 | StaticContext = this;
13 | }
14 |
15 | public static Context getContext() {
16 | return StaticContext;
17 | }
18 |
19 | public static String string(int resId) {
20 | return StaticContext.getString(resId);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/ChangeLog.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 | import java.util.Calendar;
6 | import java.util.Locale;
7 |
8 | import android.app.Activity;
9 | import android.app.AlertDialog;
10 | import android.app.AlertDialog.Builder;
11 | import android.content.DialogInterface;
12 | import android.content.Intent;
13 | import android.content.SharedPreferences;
14 | import android.content.SharedPreferences.Editor;
15 | import android.content.pm.ApplicationInfo;
16 | import android.content.pm.PackageManager.NameNotFoundException;
17 | import android.net.Uri;
18 | import android.preference.PreferenceManager;
19 | import android.text.Html;
20 | import android.text.method.LinkMovementMethod;
21 | import android.view.View;
22 | import android.widget.LinearLayout;
23 | import android.widget.LinearLayout.LayoutParams;
24 | import android.widget.ListView;
25 | import android.widget.TextView;
26 |
27 | public class ChangeLog {
28 | private AlertDialog mDialog;
29 | private final Activity mCtx;
30 | private final SharedPreferences mPref;
31 | private ListView mList;
32 | private static String PREF_KEY = null;
33 | private static String BULLET_POINT = null;
34 |
35 | public ChangeLog(Activity ctx) {
36 | mPref = PreferenceManager.getDefaultSharedPreferences(ctx);
37 | mCtx = ctx;
38 | if (PREF_KEY == null) {
39 | PREF_KEY = ctx.getString(R.string.change_log_key);
40 | BULLET_POINT = ctx.getString(R.string.bullet_point);
41 | }
42 | LauncherActivity.log(1);
43 | long lastDate = mPref.getLong(PREF_KEY, 0);
44 | try {
45 | ApplicationInfo appInfo = ctx.getPackageManager()
46 | .getApplicationInfo(ctx.getPackageName(), 0);
47 | String appFile = appInfo.sourceDir;
48 | LauncherActivity.log(1);
49 | long installed = new File(appFile).lastModified();
50 | LauncherActivity.log(lastDate < installed, lastDate, installed);
51 | if (lastDate < installed) {
52 | // Show the change log
53 | show();
54 | }
55 | } catch (NameNotFoundException e) {
56 | e.printStackTrace();
57 | }
58 | }
59 |
60 | public void show() {
61 | if (mDialog == null) {
62 | AlertDialog.Builder b = new Builder(mCtx);
63 | b.setNeutralButton(android.R.string.ok,
64 | new DialogInterface.OnClickListener() {
65 | @Override
66 | public void onClick(DialogInterface dialog, int which) {
67 | setChangeLogTimestamp();
68 | }
69 | });
70 | mList = new ListView(mCtx);
71 | b.setPositiveButton(R.string.dialog_button_rate,
72 | new DialogInterface.OnClickListener() {
73 | @Override
74 | public void onClick(DialogInterface dialog, int which) {
75 | showThisAppInMarket();
76 | setChangeLogTimestamp();
77 | }
78 | });
79 |
80 | LinearLayout layout = new LinearLayout(mCtx);
81 | layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
82 | int padding = (int)mCtx.getResources().getDimension(R.dimen.change_log_padding);
83 | layout.setPadding(padding, padding, padding, padding);
84 | layout.setOrientation(LinearLayout.VERTICAL);
85 |
86 | // If displaying English, then add the message to add translation
87 | String lang = Locale.getDefault().getLanguage();
88 | if (!lang.equals(Locale.JAPANESE.toString()) && !lang.equals(Locale.KOREAN.toString())
89 | && !lang.equals(Locale.CHINESE.toString())) {
90 | layout.setPadding(padding, padding, padding, padding);
91 | TextView emailText = new TextView(mCtx);
92 | TextView translationText = new TextView(mCtx);
93 | emailText.setMovementMethod(LinkMovementMethod.getInstance());
94 | String email = mCtx.getString(R.string.email);
95 | emailText.setText(Html.fromHtml("" + email + ""));
96 | translationText.setText(Html.fromHtml(mCtx.getString(R.string.dialog_add_translation)));
97 | layout.addView(translationText);
98 | layout.addView(emailText);
99 | } else {
100 | layout.setPadding(padding, 0, padding, 0);
101 | }
102 | layout.addView(mList);
103 | b.setView(layout);
104 | b.setTitle(R.string.change_log_dialog_title);
105 | b.setCancelable(false);
106 | buildContents();
107 | mDialog = b.create();
108 | }
109 | mDialog.show();
110 | }
111 |
112 | public void hide() {
113 | if (mDialog != null) {
114 | mDialog.hide();
115 | }
116 | }
117 |
118 | private void showAppInMarket(String packageName) {
119 | try {
120 | mCtx.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageName)));
121 | } catch (android.content.ActivityNotFoundException anfe) {
122 | mCtx.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + packageName)));
123 | }
124 | }
125 |
126 | private void showThisAppInMarket() {
127 | final String appPackageName = mCtx.getApplicationContext().getPackageName();
128 | showAppInMarket(appPackageName);
129 | }
130 |
131 | private void setChangeLogTimestamp() {
132 | Editor editor = mPref.edit();
133 | editor.putLong(PREF_KEY, Calendar.getInstance().getTimeInMillis());
134 | editor.apply();
135 | }
136 |
137 | private void buildContents() {
138 | ArrayList entries = new ArrayList();
139 | String[] info = mCtx.getResources().getStringArray(R.array.change_log);
140 |
141 | // Build the list of entries
142 | Entry currentEntry = null;
143 | for (int i = 0; i < info.length; i++) {
144 | String line = info[i];
145 | if (line.startsWith("v")) {
146 | if (currentEntry != null) {
147 | entries.add(currentEntry);
148 | }
149 |
150 | // Parse new version number
151 | currentEntry = new Entry();
152 | String[] items = line.split(",");
153 | currentEntry.versionName = items[0].substring(1, items[0].length());
154 | currentEntry.dateStr = items[1];
155 | } else if (currentEntry != null) {
156 | currentEntry.changeList.add(line);
157 | }
158 | }
159 | if (currentEntry != null) {
160 | entries.add(currentEntry);
161 | }
162 |
163 | ChangeLogAdapter adapter = new ChangeLogAdapter(mCtx, entries);
164 | mList.setAdapter(adapter);
165 | mList.setSelector(android.R.color.transparent);
166 | }
167 |
168 | private class Entry {
169 | public String dateStr;
170 | public String versionName;
171 | public ArrayList changeList = new ArrayList();
172 | }
173 |
174 | private static int[] WIDGET_IDS = { R.id.version, R.id.date, R.id.data };
175 |
176 | private class ChangeLogAdapter extends ViewAdapterBase {
177 | public ChangeLogAdapter(Activity a, ArrayList list) {
178 | super(a, R.layout.change_log_entry, WIDGET_IDS, list);
179 | }
180 |
181 | @Override
182 | protected void setWidgetValues(int position, Entry item,
183 | View[] elements, View layout) {
184 | ((TextView)elements[0]).setText(item.versionName);
185 | ((TextView)elements[1]).setText(item.dateStr);
186 |
187 | // Build the list of changes
188 | if (item.changeList.size() > 0) {
189 | StringBuilder sb = new StringBuilder();
190 | sb.append('\t').append(BULLET_POINT).append(' ').append(item.changeList.get(0));
191 | for (int i = 1; i < item.changeList.size(); i++) {
192 | sb.append('\n').append('\t').append(BULLET_POINT).append(' ')
193 | .append(item.changeList.get(i));
194 | }
195 | ((TextView)elements[2]).setText(sb);
196 | elements[2].setVisibility(View.VISIBLE);
197 | } else {
198 | elements[2].setVisibility(View.GONE);
199 | }
200 | }
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/DataDownloader.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import android.os.Bundle;
4 | import android.os.Message;
5 | import android.os.Handler;
6 |
7 | import org.apache.http.impl.client.DefaultHttpClient;
8 | import org.apache.http.client.methods.HttpGet;
9 | import org.apache.http.HttpResponse;
10 | import org.apache.http.HttpStatus;
11 | import org.apache.http.params.HttpConnectionParams;
12 |
13 | import java.io.File;
14 | import java.io.FileInputStream;
15 | import java.io.FileOutputStream;
16 | import java.io.BufferedInputStream;
17 | import java.io.BufferedOutputStream;
18 | import java.io.IOException;
19 |
20 | import java.util.List;
21 | import java.util.Iterator;
22 | import java.util.Arrays;
23 | import java.util.zip.ZipInputStream;
24 | import java.util.zip.ZipEntry;
25 | import java.util.zip.CheckedInputStream;
26 | import java.util.zip.CRC32;
27 |
28 | public class DataDownloader extends Thread
29 | {
30 | private byte[] buf = null;
31 |
32 | public DataDownloader( String zip_dir, String zip_filename, String extract_dir, String version_filename, String url, long file_size, Handler h )
33 | {
34 | this.zip_dir = zip_dir;
35 | this.zip_filename = zip_filename;
36 | this.extract_dir = extract_dir;
37 | this.version_filename = version_filename;
38 | this.url = url;
39 | this.file_size = file_size;
40 | handler = h;
41 | buf = new byte[8192*2];
42 |
43 | this.start();
44 | }
45 |
46 | @Override
47 | public void run()
48 | {
49 | File file = new File(zip_dir);
50 | try {
51 | file.mkdirs();
52 | }
53 | catch( SecurityException e ){
54 | sendMessage(-2, 0, "Failed to create root directory: " + e.toString());
55 | return;
56 | }
57 |
58 | String zip_path = zip_dir + "/" + zip_filename;
59 |
60 | file = new File(zip_path);
61 | if (file.exists() == false || file.length() != file_size)
62 | if (downloadZip(zip_path) != 0) return;
63 |
64 | if (extractZip(zip_path) != 0) return;
65 |
66 | if (file_size == -1){
67 | file = new File(zip_path);
68 | try {
69 | file.delete();
70 | }
71 | catch( SecurityException e ){
72 | sendMessage(-2, 0, "Failed to delete temporary file: " + e.toString());
73 | return;
74 | }
75 | }
76 |
77 | file = new File(extract_dir + "/" + version_filename);
78 | try {
79 | file.createNewFile();
80 | } catch( Exception e ) {
81 | sendMessage(-2, 0, "Failed to create version file: " + e.toString());
82 | return;
83 | };
84 |
85 | sendMessage(-1, 0, null);
86 | }
87 |
88 | private int downloadZip(String zip_path)
89 | {
90 | HttpResponse response = null;
91 | HttpGet request;
92 | int retry = 0;
93 |
94 | BufferedOutputStream tmp_out = null;
95 | long downloaded = 0;
96 | long totalLen = 0;
97 | while(true){
98 | DefaultHttpClient client = null;
99 | request = new HttpGet(url);
100 | request.addHeader("Accept", "*/*");
101 | if (totalLen > 0) request.addHeader("Range", "bytes="+downloaded+"-"+totalLen);
102 | try {
103 | client = new DefaultHttpClient();
104 | client.getParams().setBooleanParameter("http.protocol.handle-redirects", true);
105 | HttpConnectionParams.setConnectionTimeout(client.getParams(), 5000);
106 | HttpConnectionParams.setSoTimeout(client.getParams(), 3000);
107 | response = client.execute(request);
108 | } catch (org.apache.http.conn.ConnectTimeoutException e) {
109 | retry++;
110 | continue;
111 | } catch (java.net.SocketException e) {
112 | retry++;
113 | continue;
114 | } catch (java.net.SocketTimeoutException e) {
115 | retry++;
116 | continue;
117 | } catch (IOException e) {
118 | sendMessage(-2, 0, "Timeout or zip file is not found: " + e.toString());
119 | return -1;
120 | };
121 |
122 | if (response == null ||
123 | (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK &&
124 | response.getStatusLine().getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT)){
125 | response = null;
126 | sendMessage(-2, 0, "Timeout or zip file is not found.");
127 | return -1;
128 | }
129 |
130 | totalLen = response.getEntity().getContentLength();
131 | if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
132 | downloaded = 0;
133 | try {
134 | if (tmp_out != null){
135 | tmp_out.flush();
136 | tmp_out.close();
137 | tmp_out = null;
138 | }
139 | tmp_out = new BufferedOutputStream(new FileOutputStream(zip_path));
140 | } catch( Exception e ) {
141 | sendMessage(-2, 0, "Failed to create temporary file: " + e.toString());
142 | return -1;
143 | };
144 | }
145 | else{
146 | totalLen += downloaded;
147 | }
148 |
149 | BufferedInputStream stream = null;
150 | try {
151 | stream = new BufferedInputStream(response.getEntity().getContent());
152 | } catch( java.io.IOException e ) {
153 | client.getConnectionManager().shutdown();
154 | retry++;
155 | continue;
156 | } catch( java.lang.IllegalStateException e ) {
157 | client.getConnectionManager().shutdown();
158 | retry++;
159 | continue;
160 | }
161 |
162 | try {
163 | int len = stream.read(buf);
164 | while (len >= 0){
165 | if (len > 0) tmp_out.write(buf, 0, len);
166 | downloaded += len;
167 | sendMessage((int)downloaded, (int)totalLen, "Downloading archives from Internet: retry " + retry);
168 | len = stream.read(buf);
169 | try{
170 | Thread.sleep(1);
171 | } catch (InterruptedException e){
172 | }
173 | }
174 | } catch (java.net.SocketException e) {
175 | } catch( java.net.SocketTimeoutException e ) {
176 | } catch( java.io.IOException e ) {
177 | sendMessage(-2, 0, "Failed to write or download: " + e.toString());
178 | return -1;
179 | }
180 |
181 | try {
182 | stream.close();
183 | stream = null;
184 | } catch( java.io.IOException e ) {
185 | };
186 |
187 | client.getConnectionManager().shutdown();
188 |
189 | if (downloaded == totalLen) break;
190 | retry++;
191 | }
192 |
193 | try {
194 | tmp_out.flush();
195 | tmp_out.close();
196 | tmp_out = null;
197 | } catch( java.io.IOException e ) {
198 | };
199 |
200 | return 0;
201 | }
202 |
203 | private int extractZip(String zip_path)
204 | {
205 | ZipInputStream zip = null;
206 | try {
207 | zip = new ZipInputStream(new BufferedInputStream(new FileInputStream(zip_path)));
208 | } catch( java.io.FileNotFoundException e ) {
209 | sendMessage(-2, 0, "Failed to read from zip file: " + e.toString());
210 | return -1;
211 | };
212 |
213 | int num_file = 0;
214 | while(true){
215 | num_file++;
216 | ZipEntry entry = null;
217 | try {
218 | entry = zip.getNextEntry();
219 | } catch( java.io.IOException e ) {
220 | sendMessage(-2, 0, "Failed to get entry from zip file: " + e.toString());
221 | return -1;
222 | }
223 | if (entry == null) break;
224 |
225 | String path = extract_dir + "/" + entry.getName();
226 | if (entry.isDirectory()){
227 | try {
228 | (new File( path )).mkdirs();
229 | } catch( SecurityException e ) {
230 | sendMessage(-2, 0, "Failed to create directory: " + e.toString());
231 | return -1;
232 | }
233 | continue;
234 | }
235 |
236 | try {
237 | (new File( path.substring(0, path.lastIndexOf("/") ))).mkdirs();
238 | } catch( SecurityException e ){
239 | sendMessage(-2, 0, "Failed to create directory: " + e.toString());
240 | return -1;
241 | };
242 |
243 | if (extractZipEntry(path, zip, (int)entry.getSize(), "Extracting archives: " + num_file) != 0) return -1;
244 |
245 | try {
246 | CheckedInputStream check = new CheckedInputStream( new FileInputStream(path), new CRC32() );
247 | while( check.read(buf) > 0 ) {};
248 | check.close();
249 | if (check.getChecksum().getValue() != entry.getCrc()){
250 | File ff = new File(path);
251 | ff.delete();
252 | throw new Exception();
253 | }
254 | } catch( Exception e ){
255 | sendMessage(-2, 0, "CRC check failed");
256 | return -1;
257 | }
258 | }
259 |
260 | return 0;
261 | }
262 |
263 | private int extractZipEntry(String out_path, ZipInputStream zip, int total_size, String mes)
264 | {
265 | BufferedOutputStream out = null;
266 | try {
267 | out = new BufferedOutputStream(new FileOutputStream( out_path ));
268 | } catch( Exception e ) {
269 | sendMessage(-2, 0, "Failed to create file: " + e.toString());
270 | return -1;
271 | };
272 |
273 | int total_read = 0;
274 | try {
275 | int len = zip.read(buf);
276 | while (len >= 0){
277 | if (len > 0) out.write(buf, 0, len);
278 | total_read += len;
279 | sendMessage(total_read, total_size, mes);
280 | len = zip.read(buf);
281 | try{
282 | Thread.sleep(1);
283 | } catch (InterruptedException e){
284 | }
285 | }
286 | out.flush();
287 | out.close();
288 | } catch( java.io.IOException e ) {
289 | sendMessage(-2, 0, "Failed to write: " + e.toString());
290 | return -1;
291 | }
292 |
293 | return 0;
294 | }
295 |
296 | public void sendMessage(int current, int total, String str){
297 | Message msg = handler.obtainMessage();
298 | Bundle b = new Bundle();
299 | b.putInt("total", total);
300 | b.putInt("current", current);
301 | b.putString("message", str);
302 | msg.setData(b);
303 | handler.sendMessage(msg);
304 | }
305 |
306 | private String zip_dir = null;
307 | private String zip_filename = null;
308 | private String extract_dir = null;
309 | private String version_filename = null;
310 | private String url = null;
311 | private long file_size = -1;
312 | private Handler handler = null;
313 | }
314 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/Environment2.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import java.io.File;
4 | import java.io.FileFilter;
5 |
6 | import android.annotation.SuppressLint;
7 | import android.os.Environment;
8 |
9 | public final class Environment2 {
10 |
11 | // List of all potential external sd card paths
12 | @SuppressLint("SdCardPath")
13 | private final static String[] EXTERNAL_SD_DIR = {
14 | "/mnt/external",
15 | "/mnt/sdcard/external_sd",
16 | "/mnt/sdcard/ext_sd",
17 | "/mnt/external_sd",
18 | "/mnt/ext_sd",
19 | "/mnt/ext_sdcard",
20 | "/mnt/extSdCard",
21 | "/mnt/ext_card",
22 | "/mnt/extsd",
23 | "/mnt/sdcard-ext",
24 | "/mnt/sdcard2",
25 | "/storage/sdcard1/",
26 | "/storage/external_SD",
27 | "/storage/MicroSD",
28 | "/sdcard2",
29 | "/storage/ext_sd",
30 | "/sdcard0",
31 | "/mnt/sdcard0",
32 | "/mnt/sdcard/",
33 | };
34 | private static boolean HasScanned = false;
35 |
36 | // Private constructor so it is not used
37 | private Environment2(){}
38 |
39 | // Cached locations
40 | private static File InternalStorageFile;
41 | private static File ExternalSDCardStorageFile;
42 |
43 | static public File getInternalStorageDirectory() {
44 | verifyInternalStorage();
45 | return InternalStorageFile;
46 | }
47 |
48 | static public File getExternalSDCardDirectory() {
49 | verifyExternalSDCard();
50 | return ExternalSDCardStorageFile;
51 | }
52 |
53 | static public boolean hasInternalStorage() {
54 | verifyInternalStorage();
55 | return InternalStorageFile != null;
56 | }
57 |
58 | static public boolean hasExternalSDCard() {
59 | verifyExternalSDCard();
60 | return ExternalSDCardStorageFile != null;
61 | }
62 |
63 | // Checks to see if the file exists before returning, also rescans if anything may have gone wrong
64 | static private void verifyInternalStorage() {
65 | if (!HasScanned && InternalStorageFile == null ||
66 | InternalStorageFile != null && !InternalStorageFile.exists()) {
67 | reScan();
68 | }
69 | }
70 |
71 | // Checks to see if the file exists before returning, also rescans if anything may have gone wrong
72 | static private void verifyExternalSDCard() {
73 | if (!HasScanned && ExternalSDCardStorageFile == null ||
74 | ExternalSDCardStorageFile != null && !ExternalSDCardStorageFile.exists()) {
75 | reScan();
76 | }
77 | }
78 |
79 | // Rescans the potential locations for storage
80 | static public void reScan() {
81 | ExternalSDCardStorageFile = null;
82 | InternalStorageFile = Environment.getExternalStorageDirectory();
83 |
84 | // Scan storage for XXXX-XXXX folder pattern that should represent the sdcard
85 | File storage = new File("/storage");
86 | if (ExternalSDCardStorageFile == null && storage.exists() && storage.canRead()) {
87 | File[] files = storage.listFiles(new FileFilter() {
88 | @Override
89 | public boolean accept(File pathname) {
90 | return pathname.getName().matches("[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}");
91 | }
92 | });
93 | for (File file: files) {
94 | if (file.canRead()) {
95 | ExternalSDCardStorageFile = file;
96 | break;
97 | }
98 | }
99 | }
100 |
101 | if (ExternalSDCardStorageFile == null) {
102 | for (int i = 0; i < EXTERNAL_SD_DIR.length; i++) {
103 | File file = new File(EXTERNAL_SD_DIR[i]);
104 | if (file != null && file.exists() && !file.equals(InternalStorageFile) // Directory must exist and not be internal memory
105 | && file.length() > 0) {
106 | // Directory also must have space and files
107 | String[] fileList = file.list();
108 | if (fileList != null && fileList.length > 0) {
109 | ExternalSDCardStorageFile = file;
110 | break;
111 | }
112 | }
113 | }
114 | }
115 |
116 | HasScanned = true;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/FolderBrowserDialogPreference.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import android.content.Context;
4 | import android.content.DialogInterface;
5 | import android.content.res.TypedArray;
6 | import android.os.Bundle;
7 | import android.os.Parcel;
8 | import android.os.Parcelable;
9 | import android.preference.DialogPreference;
10 | import android.util.AttributeSet;
11 | import android.util.TypedValue;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 |
15 | public class FolderBrowserDialogPreference extends DialogPreference {
16 | private final FolderBrowserDialogWrapper mWrapper;
17 |
18 | public FolderBrowserDialogPreference(Context context, AttributeSet attrs) {
19 | this(context, attrs, 0);
20 | }
21 |
22 | public FolderBrowserDialogPreference(Context context, AttributeSet attrs, int defStyle) {
23 | super(context, attrs, defStyle);
24 | mWrapper = new FolderBrowserDialogWrapper(context);
25 |
26 | setPositiveButtonText(R.string.dialog_select_button_text);
27 | setNegativeButtonText(android.R.string.cancel);
28 | setLayoutResource(R.layout.dialog_preference);
29 | }
30 |
31 | @Override
32 | protected View onCreateView(ViewGroup parent) {
33 | View v = super.onCreateView(parent);
34 | int paddingLeft = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
35 | v.getResources().getDimension(R.dimen.preference_padding_start),
36 | v.getResources().getDisplayMetrics());
37 | v.setPadding(paddingLeft, 0, 0, 0);
38 | return v;
39 | }
40 |
41 | @Override
42 | protected View onCreateDialogView() {
43 | return mWrapper.getDialogLayout();
44 | }
45 |
46 | @Override
47 | protected void showDialog(Bundle state) {
48 | super.showDialog(state);
49 | mWrapper.setDialog(getDialog());
50 | mWrapper.show(getPersistedString(null));
51 | }
52 |
53 | @Override
54 | public void onDismiss(DialogInterface dialog) {
55 | ViewGroup layout = mWrapper.getDialogLayout();
56 | if (layout.getParent() != null) {
57 | ((ViewGroup)layout.getParent()).removeView(layout);
58 | }
59 | super.onDismiss(dialog);
60 | }
61 |
62 | @Override
63 | protected void onDialogClosed(boolean positiveResult) {
64 | super.onDialogClosed(positiveResult);
65 |
66 | if (positiveResult) {
67 | String value = mWrapper.getResultDirectory().getPath();
68 | if (callChangeListener(value)) {
69 | persistString(value);
70 | }
71 | }
72 | }
73 |
74 | @Override
75 | protected Object onGetDefaultValue(TypedArray a, int index) {
76 | return a.getString(index);
77 | }
78 |
79 | // Code below is from EditTextPreference class
80 | @Override
81 | protected Parcelable onSaveInstanceState() {
82 | final Parcelable superState = super.onSaveInstanceState();
83 | if (isPersistent()) {
84 | // No need to save instance state since it's persistent
85 | return superState;
86 | }
87 |
88 | final SavedState myState = new SavedState(superState);
89 | myState.text = mWrapper.getResultDirectory().getPath();
90 | return myState;
91 | }
92 |
93 | @Override
94 | protected void onRestoreInstanceState(Parcelable state) {
95 | if (state == null || !state.getClass().equals(SavedState.class)) {
96 | // Didn't save state for us in onSaveInstanceState
97 | super.onRestoreInstanceState(state);
98 | return;
99 | }
100 |
101 | SavedState myState = (SavedState) state;
102 | super.onRestoreInstanceState(myState.getSuperState());
103 | mWrapper.setupDirectories(myState.text);
104 | }
105 |
106 | private static class SavedState extends BaseSavedState {
107 | String text;
108 |
109 | public SavedState(Parcel source) {
110 | super(source);
111 | text = source.readString();
112 | }
113 |
114 | @Override
115 | public void writeToParcel(Parcel dest, int flags) {
116 | super.writeToParcel(dest, flags);
117 | dest.writeString(text);
118 | }
119 |
120 | public SavedState(Parcelable superState) {
121 | super(superState);
122 | }
123 |
124 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
125 | @Override
126 | public SavedState createFromParcel(Parcel in) {
127 | return new SavedState(in);
128 | }
129 |
130 | @Override
131 | public SavedState[] newArray(int size) {
132 | return new SavedState[size];
133 | }
134 | };
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/FolderBrowserDialogWrapper.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import java.io.File;
4 | import java.io.FileNotFoundException;
5 |
6 | import android.app.AlertDialog;
7 | import android.app.Dialog;
8 | import android.content.Context;
9 | import android.content.DialogInterface;
10 | import android.content.DialogInterface.OnKeyListener;
11 | import android.content.res.TypedArray;
12 | import android.graphics.drawable.Drawable;
13 | import android.os.Environment;
14 | import android.text.method.TextKeyListener;
15 | import android.view.Display;
16 | import android.view.KeyEvent;
17 | import android.view.LayoutInflater;
18 | import android.view.View;
19 | import android.view.ViewGroup;
20 | import android.view.WindowManager;
21 | import android.widget.AdapterView;
22 | import android.widget.AdapterView.OnItemClickListener;
23 | import android.widget.EditText;
24 | import android.widget.ImageButton;
25 | import android.widget.LinearLayout;
26 | import android.widget.ListView;
27 | import android.widget.TextView;
28 | import android.widget.Toast;
29 |
30 | public class FolderBrowserDialogWrapper implements OnItemClickListener, OnKeyListener {
31 | private final LinearLayout mLayout;
32 | private final ListView mListView;
33 | private FileSystemAdapter mAdapter;
34 | private final Context mCtx;
35 | private final TextView mPathText;
36 | private final ImageButton mTogglePath;
37 | private final ImageButton mNewFolderButton;
38 | private final TextView mExternalNotFoundText;
39 | private final boolean mAccessExtStorage;
40 | private Dialog mDialog;
41 | private Dialog mNewFolderDialog;
42 | private boolean isInInternalStorage;
43 |
44 | private static Drawable IconPhoneDrawable;
45 | private static Drawable IconSDcardDrawable;
46 |
47 | // Files
48 | private File mCurrentInternalPath;
49 | private File mCurrentExternalPath;
50 | private static File InternalStorage;
51 | private static File ExternalStorage;
52 |
53 | public FolderBrowserDialogWrapper(Context context) {
54 | this(context, true, false);
55 | }
56 |
57 | public FolderBrowserDialogWrapper(Context context, boolean accessExternalStorage, boolean ableToMakeFolders) {
58 | mCtx = context;
59 | mAccessExtStorage = accessExternalStorage;
60 |
61 | // Inflate the dialog
62 | LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE);
63 | mLayout = (LinearLayout) inflater.inflate(R.layout.folder_browser_dialog, null);
64 | mListView = (ListView) mLayout.findViewById(R.id.list);
65 | mPathText = (TextView) mLayout.findViewById(R.id.path);
66 | mExternalNotFoundText = (TextView) mLayout.findViewById(R.id.extNotFound);
67 | mTogglePath = (ImageButton) mLayout.findViewById(R.id.toggleLocation);
68 | mNewFolderButton = (ImageButton) mLayout.findViewById(R.id.newFolder);
69 | mListView.setOnItemClickListener(this);
70 | mTogglePath.setOnClickListener(new View.OnClickListener() {
71 | @Override
72 | public void onClick(View v) {
73 | toggleGotoButton();
74 | }
75 | });
76 | if (ableToMakeFolders) {
77 | mNewFolderButton.setOnClickListener(new View.OnClickListener() {
78 | @Override
79 | public void onClick(View arg0) {
80 | final EditText input = new EditText(mCtx);
81 | if (mNewFolderDialog == null) {
82 | mNewFolderDialog = new AlertDialog.Builder(mCtx)
83 | .setTitle(R.string.dialog_create_new_folder)
84 | .setView(input)
85 | .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
86 | @Override
87 | public void onClick(DialogInterface dialog, int whichButton) {
88 | // Folder is created
89 | String name = input.getText().toString();
90 | if (input.length() > 0) {
91 | TextKeyListener.clear(input.getText());
92 | }
93 | if (mAdapter.fileExists(name)) {
94 | Toast.makeText(mCtx, R.string.message_folder_exists, Toast.LENGTH_SHORT).show();
95 | } else {
96 | mAdapter.makeDirectory(name);
97 | }
98 | }
99 | }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
100 | @Override
101 | public void onClick(DialogInterface dialog, int whichButton) {
102 | }
103 | }).create();
104 | }
105 | mNewFolderDialog.show();
106 | }
107 | });
108 | mNewFolderButton.setVisibility(View.VISIBLE);
109 | } else {
110 | mNewFolderButton.setVisibility(View.GONE);
111 | }
112 |
113 | // Force dialog to max height
114 | WindowManager window = (WindowManager)mCtx.getSystemService(Context.WINDOW_SERVICE);
115 | Display display = window.getDefaultDisplay();
116 | mLayout.setMinimumHeight(display.getHeight());
117 |
118 | if (InternalStorage == null) {
119 | InternalStorage = Environment.getExternalStorageDirectory();
120 | ExternalStorage = Environment2.getExternalSDCardDirectory();
121 | }
122 | if (ExternalStorage != null || mCtx.getString(R.string.dialog_ext_not_found).equals("")) {
123 | mExternalNotFoundText.setVisibility(View.GONE);
124 | }
125 |
126 | // Themed icons for this dialog
127 | int[] attrs = new int[] { R.attr.phoneImage, R.attr.sdcardImage };
128 | TypedArray ta = context.obtainStyledAttributes(attrs);
129 | IconPhoneDrawable = ta.getDrawable(0);
130 | IconSDcardDrawable = ta.getDrawable(1);
131 | ta.recycle();
132 | }
133 |
134 | public ViewGroup getDialogLayout() {
135 | return mLayout;
136 | }
137 |
138 | public void setDialog(Dialog dialog) {
139 | mDialog = dialog;
140 | }
141 |
142 | public void show(String directory) {
143 | if (mDialog == null) {
144 | throw new NullPointerException("Did not run setDialog() before showing.");
145 | }
146 | mDialog.setCancelable(false);
147 | mDialog.setOnKeyListener(this);
148 | setupDirectories(directory);
149 | mDialog.show();
150 | }
151 |
152 | public void dismiss() {
153 | if (mDialog != null) {
154 | mDialog.dismiss();
155 | }
156 | }
157 |
158 | public File getResultDirectory() {
159 | return mAdapter.getCurrentDirectory();
160 | }
161 |
162 | public void setupDirectories(String path) {
163 | if (mDialog == null) {
164 | throw new NullPointerException("Did not run setDialog() before showing.");
165 | }
166 | // Detect if External sdcard is available, if not then remove the sdcard button and adjust the layout
167 | final LinearLayout.LayoutParams textLayout = (LinearLayout.LayoutParams) mPathText.getLayoutParams();
168 | if (ExternalStorage == null || !mAccessExtStorage) {
169 | ((View)mTogglePath).setVisibility(View.GONE);
170 | } else {
171 | ((View)mTogglePath).setVisibility(View.VISIBLE);
172 | }
173 | mPathText.setLayoutParams(textLayout);
174 |
175 | // Open default location from preference, if cannot find, then open storage
176 | File openDir;
177 | if (path != null) {
178 | openDir = new File(path);
179 | if (!openDir.exists()) {
180 | openDir = InternalStorage;
181 | }
182 | } else {
183 | openDir = InternalStorage;
184 | }
185 |
186 | // Detect where the current directory is either from internal or external storage
187 | if (openDir.getPath().contains(InternalStorage.getPath())) {
188 | isInInternalStorage = true;
189 | mCurrentExternalPath = ExternalStorage;
190 | } else {
191 | if (!mAccessExtStorage) {
192 | throw new IllegalStateException(
193 | "Cannot set the default location to external sd card when you have no access to it.");
194 | }
195 | isInInternalStorage = false;
196 | mCurrentInternalPath = InternalStorage;
197 | mTogglePath.setImageDrawable(IconPhoneDrawable);
198 | }
199 |
200 | try {
201 | mAdapter = new FileSystemAdapter(mCtx, openDir, true, true);
202 | mAdapter.addLowerBoundFile(InternalStorage);
203 | mAdapter.addLowerBoundFile(ExternalStorage);
204 | mAdapter.refresh();
205 | } catch (FileNotFoundException e) {
206 | e.printStackTrace();
207 | mDialog.dismiss();
208 | Toast.makeText(mCtx, R.string.message_cannot_find_internal_storage, Toast.LENGTH_SHORT).show();
209 | return;
210 | }
211 |
212 | mAdapter.bindPathToTextView(mPathText);
213 | mListView.setAdapter(mAdapter);
214 | }
215 |
216 | private void toggleGotoButton() {
217 | // Toggle between the internal and external storage
218 | if (isInInternalStorage) {
219 | mCurrentInternalPath = mAdapter.getCurrentDirectory();
220 | mTogglePath.setImageDrawable(IconPhoneDrawable);
221 | mAdapter.setCurrentDirectory(mCurrentExternalPath);
222 | } else {
223 | mCurrentExternalPath = mAdapter.getCurrentDirectory();
224 | mTogglePath.setImageDrawable(IconSDcardDrawable);
225 | mAdapter.setCurrentDirectory(mCurrentInternalPath);
226 | }
227 | isInInternalStorage = !isInInternalStorage;
228 | }
229 |
230 | @Override
231 | public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
232 | // Move up a directory if back is pressed and have not hit the folder upperlimit
233 | if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) {
234 | if (mAdapter.isDirectoryAtLowerBound()) {
235 | mDialog.dismiss();
236 | } else {
237 | mAdapter.moveUp();
238 | }
239 | }
240 | return false;
241 | }
242 |
243 | @Override
244 | public void onItemClick(AdapterView> parent, View v, int position, long id) {
245 | mAdapter.setChildAsCurrent(position);
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/ImageButton2.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.drawable.Drawable;
6 | import android.util.AttributeSet;
7 | import android.view.MotionEvent;
8 | import android.view.View;
9 | import android.view.View.OnClickListener;
10 | import android.view.View.OnTouchListener;
11 | import android.widget.FrameLayout;
12 | import android.widget.ImageView;
13 | import android.widget.ImageView.ScaleType;
14 |
15 | public class ImageButton2 extends FrameLayout implements OnTouchListener, OnClickListener {
16 |
17 | private final static int DOWN_ALPHA = 150;
18 | private final static int NORMAL_ALPHA = 255;
19 | private final static int HOVER_ALPHA = 200;
20 |
21 | private final ImageView mImageView;
22 | private Drawable mSrcImage;
23 | private Drawable mSrcImageSelected;
24 | private OnTouchListener mTouchListener;
25 | private OnClickListener mClickListener;
26 | private boolean mSelected = false;
27 |
28 | public ImageButton2(Context context) {
29 | this(context, null, 0);
30 | }
31 |
32 | public ImageButton2(Context context, AttributeSet attrs) {
33 | this(context, attrs, 0);
34 | }
35 |
36 | public ImageButton2(Context context, AttributeSet attrs, int defStyle) {
37 | super(context, attrs, defStyle);
38 | mImageView = new ImageView(context);
39 |
40 | TypedArray a = context.obtainStyledAttributes (attrs, R.styleable.ImageButton2, 0, 0);
41 | mSrcImage = a.getDrawable(R.styleable.ImageButton2_src);
42 | mSrcImageSelected = a.getDrawable(R.styleable.ImageButton2_src_selected);
43 | a.recycle();
44 |
45 | super.setOnTouchListener(this);
46 | mImageView.setImageDrawable(mSrcImage);
47 |
48 | mImageView.setScaleType(ScaleType.FIT_CENTER);
49 |
50 | addView(mImageView);
51 | }
52 |
53 | public void setNormalDrawable(Drawable drawable) {
54 | mSrcImage = drawable;
55 | if (!mSelected) {
56 | mImageView.setImageDrawable(drawable);
57 | }
58 | }
59 |
60 | public void setSelectedDrawable(Drawable drawable) {
61 | mSrcImageSelected = drawable;
62 | if (drawable == null) {
63 | mImageView.setImageDrawable(mSrcImage);
64 | }
65 | }
66 |
67 | @Override
68 | public void setSelected(boolean selected) {
69 | if (mSelected != selected) {
70 | mSelected = selected;
71 | if (mSrcImageSelected != null) {
72 | mImageView.setImageDrawable(selected ? mSrcImageSelected : mSrcImage);
73 | }
74 | super.setSelected(selected);
75 | }
76 | }
77 |
78 | public boolean getSelected() {
79 | return mSelected;
80 | }
81 |
82 | @Override
83 | public void setOnTouchListener(OnTouchListener l) {
84 | mTouchListener = l;
85 | }
86 |
87 | @Override
88 | public void setOnClickListener(OnClickListener l) {
89 | mClickListener = l;
90 | }
91 |
92 | @Override
93 | public void onClick(View v) {
94 | if (mClickListener != null) {
95 | mClickListener.onClick(v);
96 | }
97 | }
98 |
99 | @Override
100 | public boolean onTouch(View v, MotionEvent event) {
101 | boolean flag = false;
102 | if (mTouchListener != null) {
103 | flag = mTouchListener.onTouch(v, event);
104 | }
105 | switch (event.getAction()) {
106 | case MotionEvent.ACTION_DOWN:
107 | mImageView.setAlpha(DOWN_ALPHA);
108 | return true;
109 | case MotionEvent.ACTION_HOVER_EXIT:
110 | case MotionEvent.ACTION_UP:
111 | mImageView.setAlpha(NORMAL_ALPHA);
112 | setSelected(!mSelected);
113 | onClick(v);
114 | return true;
115 | case MotionEvent.ACTION_HOVER_ENTER:
116 | mImageView.setAlpha(HOVER_ALPHA);
117 | return true;
118 | default:
119 | break;
120 | }
121 | return flag;
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/ListPreferencePlus.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import android.content.Context;
4 | import android.preference.ListPreference;
5 | import android.util.AttributeSet;
6 |
7 | public class ListPreferencePlus extends ListPreference {
8 | public ListPreferencePlus(Context context) {
9 | super(context);
10 | }
11 | public ListPreferencePlus(Context context, AttributeSet attrs) {
12 | super(context, attrs);
13 | }
14 |
15 | @Override
16 | public void setValue(String value) {
17 | super.setValue(value);
18 | setSummary(getEntry());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/ProgressDialogAsyncTask.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.DialogInterface.OnCancelListener;
7 | import android.os.AsyncTask;
8 |
9 | public abstract class ProgressDialogAsyncTask extends
10 | AsyncTask implements OnCancelListener {
11 | private static final String DEFAULT_MESSAGE = "Working...";
12 |
13 | private ProgressDialog mProgressDial;
14 | private String mMessage;
15 | private final Context mCtx;
16 | private boolean mCancelable;
17 | private boolean mShowDialog;
18 |
19 | public ProgressDialogAsyncTask(Context ctx) {
20 | this(ctx, DEFAULT_MESSAGE, true);
21 | }
22 |
23 | public ProgressDialogAsyncTask(Context ctx, String message) {
24 | this(ctx, message, true);
25 | }
26 |
27 | public ProgressDialogAsyncTask(Context ctx, String message, boolean showDialog) {
28 | mCtx = ctx;
29 | mCancelable = true;
30 | setMessage(message);
31 | mShowDialog = showDialog;
32 | }
33 |
34 | public void setMessage(String message) {
35 | mMessage = message;
36 | if (mProgressDial != null) {
37 | mProgressDial.setMessage(mMessage);
38 | }
39 | }
40 |
41 | public String getMessage() {
42 | return mMessage;
43 | }
44 |
45 | public void show() {
46 | mShowDialog = true;
47 | mProgressDial = ProgressDialog.show(mCtx, "", mMessage, true, mCancelable, this);
48 | }
49 |
50 | public void setCancelable(boolean cancelable) {
51 | mCancelable = cancelable;
52 | }
53 |
54 | @Override
55 | protected void onPreExecute() {
56 | super.onPreExecute();
57 | if (mShowDialog) {
58 | show();
59 | }
60 | }
61 |
62 | @Override
63 | public void onCancel(DialogInterface dialog) {
64 | this.cancel(mCancelable);
65 | }
66 |
67 | public void dismiss() {
68 | if (mProgressDial != null && mProgressDial.isShowing()) {
69 | mProgressDial.dismiss();
70 | mProgressDial = null;
71 | }
72 | }
73 |
74 | @Override
75 | protected void onPostExecute(Result result) {
76 | super.onPostExecute(result);
77 | dismiss();
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/Settings.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import java.util.List;
4 |
5 | import android.content.Context;
6 | import android.content.pm.PackageInfo;
7 | import android.content.pm.PackageManager.NameNotFoundException;
8 | import android.content.res.Configuration;
9 | import android.content.res.Resources.Theme;
10 | import android.os.Bundle;
11 | import android.preference.Preference;
12 | import android.preference.Preference.OnPreferenceClickListener;
13 | import android.preference.PreferenceActivity;
14 | import android.preference.PreferenceManager;
15 | import android.view.MenuItem;
16 | import android.view.View;
17 | import android.widget.TextView;
18 |
19 | import com.onscripter.plus.settings.AboutSettingsFragment;
20 | import com.onscripter.plus.settings.GeneralSettingsFragment;
21 | import com.onscripter.plus.settings.LayoutPreference;
22 | import com.onscripter.plus.settings.LayoutPreference.OnLayoutViewCreatedListener;
23 |
24 | public final class Settings extends PreferenceActivity implements OnPreferenceClickListener {
25 | private ChangeLog mChangeLog;
26 |
27 | // TODO when removing 2.X dependency, put the fragment classes back
28 | private static String[] ValidFragments;
29 |
30 | public static void setVersionString(View layoutView, Context ctx) {
31 | PackageInfo pInfo;
32 | try {
33 | pInfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0);
34 | String version = pInfo.versionName;
35 | ((TextView)layoutView.findViewById(R.id.version_text)).setText(version);
36 | } catch (NameNotFoundException e) {
37 | e.printStackTrace();
38 | }
39 | }
40 |
41 | @Override
42 | protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
43 | // Set the theme
44 | String defaultThemeName = getString(R.string.settings_theme_default_value);
45 | String themeName = PreferenceManager.getDefaultSharedPreferences(this).getString(
46 | getString(R.string.settings_theme_key), defaultThemeName);
47 | int id = themeName.equals(defaultThemeName) ? R.style.Theme_Light : R.style.Theme_Dark;
48 | super.onApplyThemeResource(theme, id, first);
49 | }
50 |
51 | @SuppressWarnings("deprecation")
52 | @Override
53 | protected void onCreate(Bundle savedInstanceState) {
54 | if (ValidFragments == null) {
55 | ValidFragments = new String[]{
56 | GeneralSettingsFragment.class.getName(),
57 | AboutSettingsFragment.class.getName()
58 | };
59 | }
60 | super.onCreate(savedInstanceState);
61 | getActionBar().setDisplayHomeAsUpEnabled(true);
62 | getActionBar().setTitle(R.string.menu_action_settings);
63 |
64 | if (!isLargeTablet()) {
65 | // Old way of setting preferences for smaller devices
66 | addPreferencesFromResource(R.xml.general_settings);
67 | addPreferencesFromResource(R.xml.about_settings);
68 |
69 | Preference preference = getPreferenceScreen().findPreference(getString(R.string.settings_about_change_log_key));
70 | preference.setOnPreferenceClickListener(this);
71 |
72 | // Put the version number inside the app about preference screen
73 | LayoutPreference appAboutPref = (LayoutPreference)findPreference(getString(R.string.settings_about_app_key));
74 | appAboutPref.setOnLayoutViewCreatedListener(new OnLayoutViewCreatedListener() {
75 | @Override
76 | public void onLayoutViewCreated(View layoutView) {
77 | setVersionString(layoutView, Settings.this);
78 | }
79 | });
80 | }
81 | }
82 |
83 | @Override
84 | public void onBuildHeaders(List target) {
85 | if (isLargeTablet()) {
86 | loadHeadersFromResource(R.xml.settings_header, target);
87 | }
88 | }
89 |
90 | @Override
91 | protected boolean isValidFragment(String fragmentName) {
92 | for (String name: ValidFragments) {
93 | if (fragmentName.equals(name)) {
94 | return true;
95 | }
96 | }
97 | return false;
98 | }
99 |
100 | @Override
101 | public boolean onPreferenceClick(Preference preference) {
102 | if (mChangeLog == null) {
103 | mChangeLog = new ChangeLog(this);
104 | }
105 | mChangeLog.show();
106 | return false;
107 | }
108 |
109 | @Override
110 | public boolean onOptionsItemSelected(MenuItem item) {
111 | switch (item.getItemId()) {
112 | case android.R.id.home:
113 | finish();
114 | break;
115 | }
116 | return true;
117 | }
118 |
119 | private boolean isLargeTablet() {
120 | return (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK)
121 | >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/UnicodeUtil.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.ByteArrayInputStream;
6 | import java.io.ByteArrayOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.InputStreamReader;
10 | import java.io.OutputStreamWriter;
11 | import java.io.PushbackInputStream;
12 | import java.io.UnsupportedEncodingException;
13 | import java.io.Writer;
14 |
15 | public class UnicodeUtil {
16 |
17 | public static byte[] convert(byte[] bytes, String encout) throws Exception {
18 | // Workaround for bug that will not be fixed by SUN
19 | // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
20 | UnicodeInputStream uis = new UnicodeInputStream(
21 | new ByteArrayInputStream(bytes), "ASCII");
22 | boolean unicodeOutputReqd = (getBOM(encout) != null) ? true : false;
23 | String enc = uis.getEncoding();
24 | String BOM = getBOM(enc); // get the BOM of the inputstream
25 |
26 | if (BOM == null) {
27 | // inputstream looks like ascii...
28 | // create a BOM based on the outputstream
29 | BOM = getBOM(encout);
30 | }
31 | uis.close();
32 |
33 | ByteArrayOutputStream out = new ByteArrayOutputStream();
34 | BufferedReader br = new BufferedReader(new InputStreamReader(
35 | new ByteArrayInputStream(bytes, uis.getBOMOffset(),
36 | bytes.length), enc));
37 | Writer w = new BufferedWriter(new OutputStreamWriter(out, encout));
38 |
39 | // dont write a BOM for ascii(out) as the OutputStreamWriter
40 | // will not process it correctly.
41 | if (BOM != null && unicodeOutputReqd) {
42 | w.write(BOM);
43 | }
44 |
45 | char[] buffer = new char[4096];
46 | int len;
47 | while ((len = br.read(buffer)) != -1) {
48 | w.write(buffer, 0, len);
49 | }
50 |
51 | br.close(); // Close the input.
52 | w.close(); // Flush and close output.
53 | return out.toByteArray();
54 | }
55 |
56 | public static String getBOM(String enc) throws UnsupportedEncodingException {
57 | if ("UTF-8".equals(enc)) {
58 | byte[] bom = new byte[3];
59 | bom[0] = (byte) 0xEF;
60 | bom[1] = (byte) 0xBB;
61 | bom[2] = (byte) 0xBF;
62 | return new String(bom, enc);
63 | } else if ("UTF-16BE".equals(enc)) {
64 | byte[] bom = new byte[2];
65 | bom[0] = (byte) 0xFE;
66 | bom[1] = (byte) 0xFF;
67 | return new String(bom, enc);
68 | } else if ("UTF-16LE".equals(enc)) {
69 | byte[] bom = new byte[2];
70 | bom[0] = (byte) 0xFF;
71 | bom[1] = (byte) 0xFE;
72 | return new String(bom, enc);
73 | } else if ("UTF-32BE".equals(enc)) {
74 | byte[] bom = new byte[4];
75 | bom[0] = (byte) 0x00;
76 | bom[1] = (byte) 0x00;
77 | bom[2] = (byte) 0xFE;
78 | bom[3] = (byte) 0xFF;
79 | return new String(bom, enc);
80 | } else if ("UTF-32LE".equals(enc)) {
81 | byte[] bom = new byte[4];
82 | bom[0] = (byte) 0x00;
83 | bom[1] = (byte) 0x00;
84 | bom[2] = (byte) 0xFF;
85 | bom[3] = (byte) 0xFE;
86 | return new String(bom, enc);
87 | } else {
88 | return null;
89 | }
90 |
91 | }
92 |
93 | public static class UnicodeInputStream extends InputStream {
94 | private final PushbackInputStream internalIn;
95 |
96 | private boolean isInited = false;
97 |
98 | private int BOMOffset = -1;
99 |
100 | private final String defaultEnc;
101 |
102 | private String encoding;
103 |
104 | public static final int BOM_SIZE = 4;
105 |
106 | public UnicodeInputStream(InputStream in, String defaultEnc) {
107 | internalIn = new PushbackInputStream(in, BOM_SIZE);
108 | this.defaultEnc = defaultEnc;
109 | }
110 |
111 | public String getDefaultEncoding() {
112 | return defaultEnc;
113 | }
114 |
115 | public String getEncoding() {
116 | if (!isInited) {
117 | try {
118 | init();
119 | } catch (IOException ex) {
120 | IllegalStateException ise = new IllegalStateException(
121 | "Init method failed.");
122 | ise.initCause(ise);
123 | throw ise;
124 | }
125 | }
126 | return encoding;
127 | }
128 |
129 | /**
130 | * Read-ahead four bytes and check for BOM marks. Extra bytes are unread
131 | * back to the stream, only BOM bytes are skipped.
132 | */
133 | protected void init() throws IOException {
134 | if (isInited)
135 | return;
136 |
137 | byte bom[] = new byte[BOM_SIZE];
138 | int n, unread;
139 | n = internalIn.read(bom, 0, bom.length);
140 |
141 | if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00)
142 | && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) {
143 | encoding = "UTF-32BE";
144 | unread = n - 4;
145 | } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)
146 | && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) {
147 | encoding = "UTF-32LE";
148 | unread = n - 4;
149 | } else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB)
150 | && (bom[2] == (byte) 0xBF)) {
151 | encoding = "UTF-8";
152 | unread = n - 3;
153 | } else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
154 | encoding = "UTF-16BE";
155 | unread = n - 2;
156 | } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
157 | encoding = "UTF-16LE";
158 | unread = n - 2;
159 | } else {
160 | // Unicode BOM mark not found, unread all bytes
161 | encoding = defaultEnc;
162 | unread = n;
163 | }
164 | BOMOffset = BOM_SIZE - unread;
165 | if (unread > 0)
166 | internalIn.unread(bom, (n - unread), unread);
167 |
168 | isInited = true;
169 | }
170 |
171 | @Override
172 | public void close() throws IOException {
173 | // init();
174 | isInited = true;
175 | internalIn.close();
176 | }
177 |
178 | @Override
179 | public int read() throws IOException {
180 | // init();
181 | isInited = true;
182 | return internalIn.read();
183 | }
184 |
185 | public int getBOMOffset() {
186 | return BOMOffset;
187 | }
188 | }
189 |
190 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/ViewAdapterBase.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus;
2 |
3 | import java.util.ArrayList;
4 |
5 | import android.content.Context;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.ArrayAdapter;
10 |
11 |
12 | public abstract class ViewAdapterBase extends ArrayAdapter{
13 | protected ArrayList entries;
14 | private final Context context;
15 | private final int widgetLayout;
16 | private final int[] resources;
17 |
18 | public ViewAdapterBase(Context ctx, int widgetResourceLayout, int[] viewResourceIdListInWidget, ArrayList list) {
19 | super(ctx, 0, list);
20 | entries = list;
21 | context = ctx;
22 | resources = viewResourceIdListInWidget;
23 | widgetLayout = widgetResourceLayout;
24 | }
25 |
26 | protected abstract void setWidgetValues(int position, TItem item, View[] elements, View layout);
27 |
28 | public ArrayList getList() {
29 | return entries;
30 | }
31 |
32 | protected void onCreateListItem(int position, View item, ViewGroup parent) {
33 | }
34 |
35 | @Override
36 | public View getView(int position, View convertView, ViewGroup parent) {
37 | View viewObj = convertView;
38 | View[] elements = null;
39 | if (viewObj == null) {
40 | LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
41 | viewObj = inflator.inflate(widgetLayout, null);
42 | int size = resources.length;
43 | elements = new View[size];
44 | for (int i = 0; i < size; i++) {
45 | elements[i] = viewObj.findViewById(resources[i]);
46 | }
47 | viewObj.setTag(elements);
48 | onCreateListItem(position, viewObj, parent);
49 | } else {
50 | elements = (View[]) viewObj.getTag();
51 | }
52 | final TItem item = entries.get(position);
53 | for (View v: elements) {
54 | v.setVisibility(View.VISIBLE);
55 | }
56 | setWidgetValues(position, item, elements, viewObj);
57 | return viewObj;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/bugtracking/ModifyServerRequest.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus.bugtracking;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.DataOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStreamReader;
7 | import java.net.HttpURLConnection;
8 | import java.net.URL;
9 | import java.util.ArrayList;
10 |
11 | import org.json.JSONException;
12 | import org.json.JSONObject;
13 |
14 | import android.util.Pair;
15 |
16 | public class ModifyServerRequest {
17 | static enum METHOD { PUT, POST };
18 |
19 | private HttpURLConnection mConnection;
20 | private ArrayList mFieldData;
21 | private ArrayList> mFileData;
22 |
23 | private final METHOD mMethod;
24 |
25 | /**
26 | * Default constructor that sets method to be POST
27 | */
28 | public ModifyServerRequest() {
29 | mMethod = METHOD.POST;
30 | }
31 |
32 | /**
33 | * Constructor to specify the method to use, either
34 | * POST or PUT
35 | * @param method
36 | */
37 | public ModifyServerRequest(METHOD method) {
38 | mMethod = method;
39 | }
40 |
41 | /**
42 | * Open the connection specifying the url
43 | * @param url
44 | * @throws IOException
45 | */
46 | public void openConnection(String url) throws IOException {
47 | if (mConnection == null) {
48 | try {
49 | URL _url = new URL(url);
50 | System.setProperty("http.keepAlive", "false");
51 | mConnection = (HttpURLConnection) _url.openConnection();
52 | mConnection.setDoOutput(true);
53 | mConnection.setDoInput(true);
54 | mConnection.setUseCaches(false);
55 | mConnection.setRequestMethod(mMethod == METHOD.PUT ? "PUT" : "POST");
56 | mConnection.setReadTimeout(10000);
57 | mFieldData = new ArrayList();
58 | mFileData = new ArrayList>();
59 | } catch (IOException e) {
60 | mConnection = null;
61 | throw e;
62 | }
63 | }
64 | }
65 |
66 | /**
67 | * Add a field to the POST/PUT as data to send to the server
68 | * @param field
69 | * @param value
70 | */
71 | public void putField(String field, String value) {
72 | if (mFieldData != null) {
73 | mFieldData.add(field + "=" + value);
74 | }
75 | }
76 |
77 | /**
78 | * Add a file with its contents handled as binary to send to the server
79 | * @param field
80 | * @param data
81 | */
82 | public void putFile(String field, byte[] data) {
83 | if (mFieldData != null) {
84 | mFileData.add(Pair.create(field + "|" + data.length + "=", data));
85 | }
86 | }
87 |
88 | /**
89 | * Send the request to the server after specifying the fields and files
90 | * @throws IOException
91 | */
92 | public void send() throws IOException {
93 | if (mConnection != null) {
94 | DataOutputStream writer = new DataOutputStream(mConnection.getOutputStream());
95 | for (int i = 0; i < mFieldData.size(); i++) {
96 | writer.write(mFieldData.get(i).getBytes("UTF-8"));
97 | if (i + 1 < mFieldData.size()) {
98 | writer.writeBytes("&");
99 | }
100 | }
101 | if (mFileData.size() > 0) {
102 | writer.writeBytes("&");
103 | for (int i = 0; i < mFileData.size(); i++) {
104 | Pair data = mFileData.get(i);
105 | writer.writeBytes(data.first);
106 | writer.write(data.second);
107 | if (i + 1 < mFileData.size()) {
108 | writer.writeBytes("&");
109 | }
110 | }
111 | }
112 | writer.flush();
113 | writer.close();
114 | mFileData.clear();
115 | mFieldData.clear();
116 | }
117 | }
118 |
119 | /**
120 | * Disconnects communication to the server.
121 | * You should run this whenever you use openConnection (place this
122 | * in the finally clause of a try-catch)
123 | */
124 | public void disconnect() {
125 | if (mConnection != null) {
126 | mConnection.disconnect();
127 | mConnection = null;
128 | }
129 | }
130 |
131 | /**
132 | * Retrieves the response code from the server.
133 | * e.g. Good = 200
134 | * @return
135 | * @throws IOException
136 | */
137 | public int getResponseCode() throws IOException {
138 | return mConnection != null ? mConnection.getResponseCode() : 0;
139 | }
140 |
141 | /**
142 | * Retrieves the data that the server returns. If the response
143 | * code is 500 then this most likely will return null
144 | * @return
145 | * @throws IOException
146 | */
147 | public String getResponse() throws IOException {
148 | StringBuilder sb = new StringBuilder();
149 | BufferedReader br = null;
150 | try {
151 | br = new BufferedReader(new InputStreamReader(mConnection.getInputStream()));
152 | String line;
153 | while ((line = br.readLine()) != null) {
154 | sb.append(line + "\n");
155 | }
156 | } finally {
157 | if (br != null) {
158 | br.close();
159 | }
160 | }
161 | return sb.toString();
162 | }
163 |
164 | /**
165 | * Returns the response data as a JSON. You must know if the server can
166 | * return JSON files otherwise, this will throw an exception.
167 | * @return
168 | * @throws IOException
169 | * @throws JSONException
170 | */
171 | public JSONObject getResponseJSON() throws IOException, JSONException {
172 | return new JSONObject(getResponse());
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/bugtracking/TracedONScripterView.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus.bugtracking;
2 |
3 | import java.io.File;
4 |
5 | import android.app.Activity;
6 | import android.content.pm.ApplicationInfo;
7 | import android.os.Environment;
8 |
9 | import com.onscripter.ONScripterView;
10 |
11 | public class TracedONScripterView extends ONScripterView {
12 |
13 | private ONScripterTracer.Playback mPlayback;
14 | final String rootFolder;
15 | final String mCurrentDirectory;
16 |
17 | public TracedONScripterView(Activity context, String currentDirectory,
18 | String fontPath, String savePath, boolean useHQAudio,
19 | boolean shouldRenderOutline) {
20 | super(context, currentDirectory, fontPath, savePath, useHQAudio, shouldRenderOutline);
21 |
22 | mCurrentDirectory = currentDirectory;
23 | rootFolder = savePath != null ? savePath : currentDirectory;
24 |
25 | // String traceFile = getContext().getApplicationContext().getFilesDir() + "/" + ONScripterTracer.TRACE_FILE_NAME;
26 | String traceFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
27 | + "/" + ONScripterTracer.TRACE_FILE_NAME;
28 | if (isDebug() && ONScripterTracer.playbackEnabled() && new File(traceFile).exists()) {
29 | mPlayback = new ONScripterTracer.Playback(this, traceFile);
30 | mPlayback.start();
31 | } else {
32 | ONScripterTracer.init(context);
33 | ONScripterTracer.open(false);
34 | }
35 | }
36 |
37 | @Override
38 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
39 | int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
40 | int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
41 | ONScripterTracer.traceViewDimensions(parentWidth, parentHeight);
42 | this.setMeasuredDimension(parentWidth, parentHeight);
43 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
44 | }
45 |
46 | @Override
47 | public void receiveException(String message, String currentLineBuffer, String backtrace) {
48 | super.receiveException(message, currentLineBuffer, backtrace);
49 | if (mPlayback != null) {
50 | mPlayback.stop();
51 | mPlayback = null;
52 | } else {
53 | ONScripterTracer.traceCrash();
54 | ONScripterTracer.close();
55 | ONScripterTracer.open();
56 | }
57 | }
58 |
59 | @Override
60 | public void exitApp() {
61 | if (mPlayback != null) {
62 | mPlayback.stop();
63 | mPlayback = null;
64 | } else {
65 | ONScripterTracer.close();
66 | }
67 | super.exitApp();
68 | }
69 |
70 | @Override
71 | public void onPause() {
72 | super.onPause();
73 | if (mPlayback != null) {
74 | mPlayback.stop();
75 | mPlayback = null;
76 | } else {
77 | ONScripterTracer.close();
78 | }
79 | }
80 |
81 | @Override
82 | public void onResume() {
83 | if (mPlayback == null) {
84 | ONScripterTracer.open();
85 | }
86 | super.onResume();
87 | }
88 |
89 | @Override
90 | protected void nativeKey(int keyCode, int down) {
91 | if (mPlayback == null) {
92 | ONScripterTracer.traceKeyEvent(keyCode, down);
93 | }
94 | super.nativeKey(keyCode, down);
95 | }
96 |
97 | @Override
98 | protected void nativeMouse(int x, int y, int action) {
99 | if (mPlayback == null) {
100 | ONScripterTracer.traceMouseEvent(x, y, action);
101 | }
102 | super.nativeMouse(x, y, action);
103 | }
104 |
105 | @Override
106 | public void playVideo(char[] filename, boolean clickToSkip, boolean shouldLoop) {
107 | if (allowVideo()) {
108 | File video = new File(mCurrentDirectory + "/" + new String(filename).replace("\\", "/"));
109 | if (video.exists() && video.canRead()) {
110 | ONScripterTracer.traceVideoStartEvent();
111 | }
112 | super.playVideo(filename, clickToSkip, shouldLoop);
113 | }
114 | }
115 |
116 | /**
117 | * Always skip videos when playing back traces
118 | * @return
119 | */
120 | protected boolean allowVideo() {
121 | return mPlayback == null;
122 | }
123 |
124 | void triggerMouseEvent(int x, int y, int action) {
125 | nativeMouse( x, y, action );
126 | }
127 |
128 | void triggerKeyEvent(int keyCode, int down) {
129 | nativeKey( keyCode, down );
130 | }
131 |
132 | protected boolean isDebug() {
133 | return (getContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
134 | }
135 |
136 | protected void onLoadFile(String filename, String savePath) {
137 | if (mPlayback == null) {
138 | String path = rootFolder + "/" + (savePath == null ? "" : (savePath + "/")) + filename;
139 | ONScripterTracer.traceLoadEvent(getContext(), path, savePath);
140 | }
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/settings/AboutSettingsFragment.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus.settings;
2 |
3 | import android.os.Bundle;
4 | import android.preference.Preference;
5 | import android.preference.Preference.OnPreferenceClickListener;
6 | import android.preference.PreferenceFragment;
7 | import android.util.TypedValue;
8 | import android.view.View;
9 |
10 | import com.onscripter.plus.ChangeLog;
11 | import com.onscripter.plus.R;
12 | import com.onscripter.plus.Settings;
13 | import com.onscripter.plus.settings.LayoutPreference.OnLayoutViewCreatedListener;
14 |
15 | public class AboutSettingsFragment extends PreferenceFragment implements OnPreferenceClickListener {
16 | private ChangeLog mChangeLog;
17 |
18 | @Override
19 | public void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | addPreferencesFromResource(R.xml.about_settings);
22 | findPreference(getString(R.string.settings_about_change_log_key))
23 | .setOnPreferenceClickListener(this);
24 |
25 | // Set the corrected padding on the left to follow the same indent as the rest and set version number
26 | LayoutPreference p = (LayoutPreference) findPreference(getString(R.string.settings_about_app_key));
27 | p.setOnLayoutViewCreatedListener(new OnLayoutViewCreatedListener() {
28 | @Override
29 | public void onLayoutViewCreated(View layoutView) {
30 | int paddingLeft = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
31 | getResources().getDimension(R.dimen.preference_padding_start),
32 | getResources().getDisplayMetrics());
33 | layoutView.setPadding(paddingLeft, 0, 0, 0);
34 | Settings.setVersionString(layoutView, getActivity());
35 | }
36 | });
37 | }
38 |
39 | @Override
40 | public boolean onPreferenceClick(Preference preference) {
41 | if (mChangeLog == null) {
42 | mChangeLog = new ChangeLog(getActivity());
43 | }
44 | mChangeLog.show();
45 | return false;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/settings/GeneralSettingsFragment.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus.settings;
2 |
3 | import android.os.Bundle;
4 | import android.preference.PreferenceFragment;
5 |
6 | import com.onscripter.plus.R;
7 |
8 | public class GeneralSettingsFragment extends PreferenceFragment {
9 | @Override
10 | public void onCreate(Bundle savedInstanceState) {
11 | super.onCreate(savedInstanceState);
12 | addPreferencesFromResource(R.xml.general_settings);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/onscripter/plus/settings/LayoutPreference.java:
--------------------------------------------------------------------------------
1 | package com.onscripter.plus.settings;
2 |
3 | import android.content.Context;
4 | import android.preference.Preference;
5 | import android.util.AttributeSet;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | public class LayoutPreference extends Preference {
11 | private View mLayoutView;
12 | private OnLayoutViewCreatedListener mListener;
13 |
14 | public interface OnLayoutViewCreatedListener {
15 | public void onLayoutViewCreated(View layoutView);
16 | }
17 |
18 | public LayoutPreference(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | }
21 |
22 | @Override
23 | protected View onCreateView(ViewGroup parent) {
24 | final LayoutInflater layoutInflater =
25 | (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
26 | mLayoutView = layoutInflater.inflate(getLayoutResource(), parent, false);
27 | if (mListener != null) {
28 | mListener.onLayoutViewCreated(mLayoutView);
29 | }
30 | return mLayoutView;
31 | }
32 |
33 | public void setOnLayoutViewCreatedListener(OnLayoutViewCreatedListener listener) {
34 | mListener = listener;
35 | }
36 |
37 | public View getLayoutView() {
38 | return mLayoutView;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/jrummy/sdfix/Remounter.java:
--------------------------------------------------------------------------------
1 | package jrummy.sdfix;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | import android.text.TextUtils;
11 | import android.util.Log;
12 |
13 | /**
14 | *
15 | * @author Jared Rummler
16 | *
17 | */
18 | public class Remounter {
19 |
20 | private static final String TAG = Remounter.class.getName();
21 | /** /proc/mounts File */
22 | public static final File PROC_MOUNTS = new File("/proc/mounts");
23 | /** Value of ANDROID_ROOT environmental variable or /system if empty */
24 | public static final String ANDROID_ROOT = System.getenv("ANDROID_ROOT");
25 | /** Read/Write "rw" */
26 | public static final String RW = "rw";
27 | /** Read-only "ro" */
28 | public static final String RO = "ro";
29 |
30 | /**
31 | * Contains info extracted from a line in /proc/mounts
32 | */
33 | public static class Mount {
34 | /** The line in /proc/mounts */
35 | public String line;
36 | public String device;
37 | public String mountpoint;
38 | public String type;
39 | public String options;
40 | public String mountOption;
41 |
42 | /**
43 | *
44 | * @param line A line in /proc/mounts
45 | * @throws IndexOutOfBoundsException
46 | * @throws NullPointerException
47 | */
48 | public Mount(String line) throws IndexOutOfBoundsException, NullPointerException {
49 | final String[] arr = line.split("\\s+");
50 | this.line = line;
51 | this.device = arr[0];
52 | this.mountpoint = arr[1];
53 | this.type = arr[2];
54 | this.options = arr[3];
55 | this.mountOption = this.options.split(",")[0];
56 | }
57 |
58 | /**
59 | * @return true
if the filesystem is mounted read-only.
60 | */
61 | public boolean isMountedReadOnly() {
62 | if (this.mountOption != null) {
63 | return this.mountOption.equals(RO);
64 | }
65 | return false;
66 | }
67 |
68 | /**
69 | * @return true
if the filesystem is mounted read/write.
70 | */
71 | public boolean isMountedReadWrite() {
72 | if (this.mountOption != null) {
73 | return this.mountOption.equals(RW);
74 | }
75 | return false;
76 | }
77 |
78 | /**
79 | * @return The command used to remount the filesystem read/write.
80 | */
81 | public String getMountCommand() {
82 | return getMountCommand(RW);
83 | }
84 |
85 | /**
86 | *
87 | * @param mountType "ro" or "rw"
88 | * @return The command used to remount the filesystem read/write or read-only
89 | */
90 | public String getMountCommand(String mountType) {
91 | return String.format("mount -o remount,%s %s %s",
92 | mountType, this.device, this.mountpoint);
93 | }
94 |
95 | private void setMountOption(String type) {
96 | this.line.replaceAll(this.mountOption + ",", type + ",");
97 | this.options.replaceAll(this.mountOption + ",", type + ",");
98 | this.mountOption = type;
99 | }
100 |
101 | /**
102 | * Mounts a filesystem read-only or read/write
103 | * @param mountType "ro" or "rw"
104 | * @return true
if successful
105 | */
106 | public boolean remount(String mountType) {
107 | String command = getMountCommand(mountType);
108 | if (Shell.SU.run(command).success()) {
109 | setMountOption(mountType);
110 | return true;
111 | }
112 |
113 | command = "busybox " + command;
114 | if (Shell.SU.run(command).success()) {
115 | setMountOption(mountType);
116 | return true;
117 | }
118 |
119 | return false;
120 | }
121 |
122 | /**
123 | * Mounts a filesystem read/write
124 | * @return true
if successful
125 | */
126 | public boolean remountReadWrite() {
127 | return remount(RW);
128 | }
129 |
130 | /**
131 | * Mounts a filesystem read-only
132 | * @return true
if successful
133 | */
134 | public boolean remountReadOnly() {
135 | return remount(RO);
136 | }
137 | }
138 |
139 | /**
140 | * Parses /proc/mounts and returns a List of {@link Remounter.Mount}
141 | * @return
142 | */
143 | public static List getMounts() {
144 | final List mounts = new ArrayList();
145 | if (PROC_MOUNTS.canRead()) {
146 | try {
147 | final BufferedReader br = new BufferedReader(new FileReader(PROC_MOUNTS));
148 | try {
149 | String line = null;
150 | while ((line = br.readLine()) != null) {
151 | try {
152 | mounts.add(new Mount(line));
153 | } catch (Exception ignore) { }
154 | }
155 | } finally {
156 | br.close();
157 | }
158 | if (!mounts.isEmpty()) {
159 | return mounts;
160 | }
161 | } catch (IOException e) {
162 | Log.e(TAG, "Failed reading " + PROC_MOUNTS, e);
163 | mounts.clear();
164 | }
165 | }
166 |
167 | final String command = "cat \"" + PROC_MOUNTS + "\"";
168 | final Shell.CommandResult r = Shell.SU.run(command);
169 | if (r.success() && !TextUtils.isEmpty(r.stdout)) {
170 | final String[] lines = r.stdout.split("\n");
171 | for (final String line : lines) {
172 | try {
173 | mounts.add(new Mount(line));
174 | } catch (Exception ignore) { }
175 | }
176 | }
177 |
178 | return mounts;
179 | }
180 |
181 | /**
182 | *
183 | * @param file
184 | * @return The filesystem in /proc/mounts for this file or null
.
185 | */
186 | public static Mount getMount(File file) {
187 | return getMount(file.getAbsolutePath());
188 | }
189 |
190 | /**
191 | *
192 | * @param path
193 | * @return The filesystem in /proc/mounts for this file or null
.
194 | */
195 | public static Mount getMount(String path) {
196 | final List mounts = getMounts();
197 | if (mounts.isEmpty()) {
198 | return null;
199 | }
200 |
201 | while (path != null) {
202 | for (final Mount mount : mounts) {
203 | if (mount.mountpoint.equals(path)) {
204 | return mount;
205 | }
206 | }
207 |
208 | if (path.equals(File.separator)) {
209 | return null;
210 | }
211 |
212 | path = new File(path).getParent();
213 | if (path == null) {
214 | path = File.separator;
215 | }
216 | }
217 |
218 | return null;
219 | }
220 |
221 | /**
222 | * Remounts a filesystem read/write or read-only
223 | * @param path Path to the file
224 | * @param type "rw" or "ro"
225 | * @return true
if successful
226 | */
227 | public static boolean remount(String path, String type) {
228 | final Mount mount = getMount(path);
229 | if (mount == null) {
230 | Log.i(TAG, "Failed finding mountpoint for " + path);
231 | return false;
232 | }
233 |
234 | if (mount.mountOption.equals(type)) {
235 | // Already mounted
236 | return true;
237 | }
238 |
239 | return mount.remount(type);
240 | }
241 |
242 | /** @see #remount(String, String) */
243 | public static boolean remount(File file, String type) {
244 | return remount(file.getAbsolutePath(), type);
245 | }
246 |
247 | /** @see #remount(String, String) */
248 | public static boolean rw(String path) {
249 | return remount(path, RW);
250 | }
251 |
252 | /** @see #remount(String, String) */
253 | public static boolean ro(String path) {
254 | return remount(path, RO);
255 | }
256 |
257 | /** @see #remount(String, String) */
258 | public static boolean rw(File file) {
259 | return remount(file, RW);
260 | }
261 |
262 | /** @see #remount(String, String) */
263 | public static boolean ro(File file) {
264 | return remount(file, RO);
265 | }
266 |
267 | /** @see #remount(String, String) */
268 | public static boolean mountSystemRw() {
269 | return rw(ANDROID_ROOT);
270 | }
271 |
272 | /** @see #remount(String, String) */
273 | public static boolean mountSystemRo() {
274 | return ro(ANDROID_ROOT);
275 | }
276 | }
277 |
--------------------------------------------------------------------------------
/app/src/main/java/jrummy/sdfix/SDFix.java:
--------------------------------------------------------------------------------
1 | package jrummy.sdfix;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.File;
6 | import java.io.FileNotFoundException;
7 | import java.io.FileReader;
8 | import java.io.FileWriter;
9 | import java.io.IOException;
10 |
11 | import android.content.Context;
12 | import android.util.Log;
13 |
14 | public class SDFix {
15 |
16 | private static final String TAG = SDFix.class.getName();
17 |
18 | public static final String PLATFORM_XML = "/system/etc/permissions/platform.xml";
19 |
20 | /* Modified: Matthew Ng; the name is modified because it does not truly say if writable, for example
21 | * the fix is completed but user has not restarted device yet.
22 | */
23 | public static boolean isRemovableStorageWritableFixApplied() throws IOException, FileNotFoundException {
24 | boolean isRemovableStorageWritable = false;
25 | final BufferedReader reader = new BufferedReader(new FileReader(PLATFORM_XML));
26 | boolean isPermissionLine = false;
27 | String line = reader.readLine();
28 | while (line != null) {
29 | if (line.contains("android.permission.WRITE_EXTERNAL_STORAGE")) {
30 | isPermissionLine = true;
31 | }
32 | else if (isPermissionLine) {
33 | if (line.contains("")) {
34 | isPermissionLine = false;
35 | }
36 | else if (line.contains("media_rw")) {
37 | isRemovableStorageWritable = true;
38 | }
39 | }
40 | line = reader.readLine();
41 | }
42 | reader.close();
43 | return isRemovableStorageWritable;
44 | }
45 |
46 | public static String getModifiedPlatformXml() throws IOException, FileNotFoundException {
47 | final StringBuilder sb = new StringBuilder();
48 | final BufferedReader reader = new BufferedReader(new FileReader(PLATFORM_XML));
49 | boolean addLine = false;
50 | String line = reader.readLine();
51 | while (line != null) {
52 | if (line.contains("android.permission.WRITE_EXTERNAL_STORAGE")) {
53 | addLine = true;
54 | }
55 | else if (addLine) {
56 | if (line.contains("")) {
57 | sb.append(" ");
58 | sb.append('\n');
59 | addLine = false;
60 | }
61 | }
62 | sb.append(line);
63 | sb.append('\n');
64 | line = reader.readLine();
65 | }
66 | reader.close();
67 | return sb.toString();
68 | }
69 |
70 | public static boolean writeModifiedPlatformXml(File outfile) throws IOException {
71 | String text = "";
72 | try {
73 | text = getModifiedPlatformXml();
74 | } catch (Exception e) {
75 | return false;
76 | }
77 | final BufferedWriter writer = new BufferedWriter(new FileWriter(outfile));
78 | writer.append(text);
79 | writer.close();
80 | return true;
81 | }
82 |
83 | public static boolean fixPermissions(Context context) throws FileNotFoundException, IOException {
84 | if (isRemovableStorageWritableFixApplied()) {
85 | Log.i(TAG, PLATFORM_XML + " is already modified to allow apps to write to a removable SD card");
86 | return true;
87 | }
88 |
89 | final File outfile = new File(context.getFilesDir(), "platform.xml");
90 | try {
91 | if (!writeModifiedPlatformXml(outfile)) {
92 | return false;
93 | }
94 | } catch (Exception e) {
95 | Log.e(TAG, "Failed to write the modified file to " + outfile, e);
96 | return false;
97 | }
98 |
99 | if (!Remounter.mountSystemRw()) {
100 | Log.i(TAG, "Failed to mount system read/write");
101 | return false;
102 | }
103 |
104 | String[] commands = {
105 | "cp " + PLATFORM_XML + " /system/etc/permissions/platform.xml.bak",
106 | "cp \"" + outfile + "\" \"" + PLATFORM_XML + "\"",
107 | "chmod 0644 " + PLATFORM_XML,
108 | "chmod 0644 /system/etc/permissions/platform.xml.bak"
109 | };
110 |
111 | if (!Shell.SU.run(commands).success()) {
112 | Log.i(TAG, "Failed to copy over " + outfile + " to " + PLATFORM_XML);
113 | return false;
114 | }
115 |
116 | Remounter.mountSystemRo();
117 |
118 | return true;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/app/src/main/java/jrummy/sdfix/Shell.java:
--------------------------------------------------------------------------------
1 | package jrummy.sdfix;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.DataOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStreamReader;
7 | import java.util.List;
8 |
9 | import android.os.Handler;
10 | import android.text.TextUtils;
11 | import android.util.Log;
12 |
13 | /**
14 | * Shell.java runs commands as if in a native shell instance, and can
15 | * return stdout, stderr, and exit code.
16 | *
17 | * Example usage:
18 | * new Shell("sh").run("ls");
19 | *
20 | * @author Jared Rummler
21 | *
22 | */
23 | public class Shell {
24 |
25 | private static final String TAG = "Shell";
26 |
27 | /** The LD_LIBRARY_PATH environmental variable value **/
28 | private static final String LD_LIBRARY_PATH = System.getenv("LD_LIBRARY_PATH");
29 |
30 | private static Boolean canSu;
31 | private String shell;
32 |
33 | private Handler mHandler;
34 | private CommandListener mListener;
35 |
36 | public interface CommandListener {
37 | public void onExecuteCommand(String command);
38 | public void onReadOutput(String line, boolean stdout);
39 | public void onFinished(CommandResult result);
40 | }
41 |
42 | /**
43 | * Constructor to create a new shell to run linux commands in.
44 | *
45 | * @param shell The name of the shell commands will be executed in
46 | */
47 | public Shell(String shell) {
48 | this.shell = shell;
49 | }
50 |
51 | /**
52 | * Constructor to create a new root shell to run linux commands in
53 | */
54 | public Shell() {
55 | this("su");
56 | }
57 |
58 | public Shell setCommandListener(CommandListener listener) {
59 | return setCommandListener(null, listener);
60 | }
61 |
62 | public Shell setCommandListener(Handler handler, CommandListener listener) {
63 | mHandler = handler;
64 | mListener = listener;
65 | return this;
66 | }
67 |
68 | public static class SU {
69 | public static CommandResult run(String...commands) {
70 | return new Shell("su").run(commands);
71 | }
72 | public static CommandResult run(List commands) {
73 | return run(commands.toArray(new String[]{}));
74 | }
75 | }
76 |
77 | public static class SH {
78 | public static CommandResult run(String...commands) {
79 | return new Shell("sh").run(commands);
80 | }
81 | public static CommandResult run(List commands) {
82 | return run(commands.toArray(new String[]{}));
83 | }
84 | }
85 |
86 | public static Shell.CommandResult run(String shell, String[] commands) {
87 | return new Shell(shell).run(commands);
88 | }
89 |
90 | /**
91 | *
92 | * @return The current shell commands are being executed in.
93 | */
94 | public String getShell() {
95 | return shell;
96 | }
97 |
98 | /**
99 | * Sets the current shell to execute commands in.
100 | * @see #SU
101 | * @see #SH
102 | * @see #BASH
103 | * @param shell
104 | */
105 | public void setShell(String shell) {
106 | this.shell = shell;
107 | }
108 |
109 | /**
110 | * Contains information about the last run command.
111 | */
112 | public static class CommandResult {
113 | /** The exit value returned by the last run command. -1 by default. **/
114 | public int exitValue = -1;
115 | /** Standard output of all commands run **/
116 | public String stdout;
117 | /** Standard error by all commands run **/
118 | public String stderr;
119 |
120 | public CommandResult() {
121 |
122 | }
123 |
124 | public CommandResult(int exitValue, String stdout, String stderr) {
125 | this.exitValue = exitValue;
126 | this.stdout = stdout;
127 | this.stderr = stderr;
128 | }
129 |
130 | /**
131 | *
132 | * @return true
if the {@link #exitValue} is equal to 0.
133 | */
134 | public boolean success() {
135 | return exitValue == 0;
136 | }
137 |
138 | public boolean hasOutput() {
139 | return !TextUtils.isEmpty(this.stdout);
140 | }
141 |
142 | public boolean isSuccess() {
143 | return success() && hasOutput();
144 | }
145 | }
146 |
147 | private void onReadLine(final String line, final boolean stdout) {
148 | if (mListener != null) {
149 | if (mHandler != null) {
150 | mHandler.post(new Runnable() {
151 | @Override
152 | public void run() {
153 | mListener.onReadOutput(line, stdout);
154 | }
155 | });
156 | } else {
157 | mListener.onReadOutput(line, stdout);
158 | }
159 | }
160 | }
161 |
162 | private String readStream(InputStreamReader stream, boolean stdout) {
163 | BufferedReader reader = new BufferedReader(stream);
164 | StringBuffer buffer = null;
165 | try {
166 | String line = reader.readLine();
167 | if (line != null) {
168 | buffer = new StringBuffer(line);
169 | while ((line = reader.readLine()) != null) {
170 | onReadLine(line, stdout);
171 | buffer.append("\n").append(line);
172 | }
173 | }
174 | } catch (IOException e) {
175 | Log.i(TAG, "Error: " + e.getMessage());
176 | }
177 |
178 | if (buffer != null) {
179 | return buffer.toString();
180 | }
181 |
182 | return null;
183 | }
184 |
185 | /**
186 | * Runs commands in the current shell.
187 | *
188 | * @param commands A single or an array of commands the current {@link #shell} should run.
189 | * @return The result (see {@linkplain CommandResult}) of all the commands run.
190 | */
191 | public CommandResult run(String... commands) {
192 | final CommandResult result = new CommandResult();
193 | InputStreamReader osStdout = null;
194 | InputStreamReader osStderr = null;
195 | DataOutputStream os = null;
196 | Process process = null;
197 | Runtime.getRuntime().gc();
198 |
199 | try {
200 | process = Runtime.getRuntime().exec(shell);
201 | os = new DataOutputStream(process.getOutputStream());
202 | osStdout = new InputStreamReader(process.getInputStream());
203 | osStderr = new InputStreamReader(process.getErrorStream());
204 |
205 | try {
206 | for (String command : commands) {
207 |
208 | if (shell.equals("su") && LD_LIBRARY_PATH != null) {
209 | // On some versions of Android (ICS) LD_LIBRARY_PATH is unset when using su
210 | // We need to pass LD_LIBRARY_PATH over su for some commands to work correctly.
211 | command = "LD_LIBRARY_PATH=" + LD_LIBRARY_PATH + " " + command;
212 | }
213 |
214 | if (mListener != null) {
215 | if (mHandler != null) {
216 | final String cmd = command;
217 | mHandler.post(new Runnable() {
218 | @Override
219 | public void run() {
220 | mListener.onExecuteCommand(cmd);
221 | }
222 | });
223 | } else {
224 | mListener.onExecuteCommand(command);
225 | }
226 | }
227 |
228 | os.writeBytes(command + "\n");
229 | os.flush();
230 | }
231 |
232 | os.writeBytes("exit\n");
233 | os.flush();
234 |
235 | result.stdout = readStream(osStdout, true);
236 | result.stderr = readStream(osStderr, false);
237 | result.exitValue = process.waitFor();
238 | } catch (InterruptedException e) {
239 | Log.i(TAG, "Error running commands: " + e.getMessage(), e);
240 | } catch (Exception e) {
241 | Log.i(TAG, "Error running commands: " + e.getMessage(), e);
242 | }
243 | } catch (IOException e) {
244 | Log.i(TAG, "Error: " + e.getMessage());
245 | } finally {
246 | try {
247 | if (os != null) {
248 | os.close();
249 | }
250 | if (osStdout != null) {
251 | osStdout.close();
252 | }
253 | if (osStderr != null) {
254 | osStderr.close();
255 | }
256 | if (process != null) {
257 | process.destroy();
258 | }
259 | } catch (Exception ignore) { }
260 | }
261 |
262 | if (mListener != null) {
263 | if (mHandler != null) {
264 | mHandler.post(new Runnable() {
265 | @Override
266 | public void run() {
267 | mListener.onFinished(result);
268 | }
269 | });
270 | } else {
271 | mListener.onFinished(result);
272 | }
273 | }
274 |
275 | return result;
276 | }
277 |
278 | /**
279 | * Checks if the user is rooted
280 | * forceCheck defaults to false
281 | * @see #canSu(boolean)
282 | */
283 | public static boolean canSu() {
284 | return canSu(false);
285 | }
286 |
287 | /**
288 | * Checks if the user has root access.
289 | * @param forceCheck Set to true
to check for root
290 | * regardless if it has already been checked.
291 | * @return true
if the user has root access.
292 | */
293 | public static boolean canSu(boolean forceCheck) {
294 | if (canSu == null || forceCheck) {
295 | CommandResult r = SU.run("id");
296 | StringBuilder out = new StringBuilder();
297 |
298 | if (r.stdout != null) {
299 | out.append(r.stdout).append(" ; ");
300 | }
301 | if (r.stderr != null) {
302 | out.append(r.stderr);
303 | }
304 | Log.d(TAG, "canSU() su[" + r.exitValue + "]: " + out);
305 | canSu = r.success();
306 | }
307 |
308 | return canSu;
309 | }
310 |
311 | }
312 |
--------------------------------------------------------------------------------
/app/src/main/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-hdpi/ic_action_new.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_new_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-hdpi/ic_action_new_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-hdpi/ic_action_phone.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_phone_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-hdpi/ic_action_phone_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_sd_storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-hdpi/ic_action_sd_storage.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_sd_storage_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-hdpi/ic_action_sd_storage_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-mdpi/ic_action_new.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_new_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-mdpi/ic_action_new_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-mdpi/ic_action_phone.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_phone_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-mdpi/ic_action_phone_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_sd_storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-mdpi/ic_action_sd_storage.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_sd_storage_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-mdpi/ic_action_sd_storage_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xhdpi/ic_action_new.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_new_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xhdpi/ic_action_new_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xhdpi/ic_action_phone.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_phone_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xhdpi/ic_action_phone_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_sd_storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xhdpi/ic_action_sd_storage.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_sd_storage_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xhdpi/ic_action_sd_storage_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xxhdpi/ic_action_new.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_new_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xxhdpi/ic_action_new_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xxhdpi/ic_action_phone.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_phone_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xxhdpi/ic_action_phone_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_sd_storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xxhdpi/ic_action_sd_storage.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_sd_storage_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xxhdpi/ic_action_sd_storage_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dark_divider.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_action_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/ic_action_save.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_file_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/ic_file_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_file_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/ic_file_light.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_folder_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/ic_folder_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_folder_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/ic_folder_light.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_folder_up_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/ic_folder_up_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_folder_up_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/ic_folder_up_light.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_menu_change_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/ic_menu_change_folder.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/light_divider.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_auto.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_auto.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_auto_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_auto_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_back.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_change_speed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_change_speed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_change_speed_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_change_speed_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_mouse_right_click.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_mouse_right_click.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_mouse_scroll_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_mouse_scroll_down.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_mouse_scroll_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_mouse_scroll_up.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_settings.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_skip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_skip.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_skip_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/app/src/main/res/drawable/menu_skip_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/about_preference_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
18 |
26 |
29 |
32 |
35 |
36 |
40 |
43 |
45 |
46 |
51 |
55 |
58 |
61 |
64 |
65 |
68 |
71 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/change_log_entry.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
13 |
20 |
27 |
28 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/copy_file_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
17 |
20 |
21 |
25 |
31 |
35 |
36 |
37 |
38 |
43 |
50 |
51 |
52 |
57 |
64 |
65 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_preference.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
26 |
27 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/file_system_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fix_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/folder_browser_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
14 |
21 |
31 |
37 |
44 |
51 |
52 |
53 |
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/onscripter.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
17 |
21 |
26 |
31 |
36 |
37 |
43 |
47 |
51 |
55 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/radiobutton_choice_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/sdcard_fix_su_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/selective_file_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
18 |
21 |
22 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/selective_file_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/vnsettings_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
15 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/vnsettings_dialog_controls.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
16 |
18 |
21 |
24 |
25 |
27 |
30 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/vnsettings_dialog_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
17 |
23 |
27 |
28 |
34 |
40 |
41 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ja/change_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 変更
4 |
5 | - vバージョン 1.2.5,2018年9月29日
6 | - バグを直した
7 | - vバージョン 1.2.4,2015年8月7日
8 | - たくさんバグを直した
9 | - vバージョン 1.2.3,2015年7月25日
10 | - ビデオが直した
11 | - たくさんバグを直した
12 | - vバージョン 1.2.2,2015年3月20日
13 | - たくさんバグを直した
14 | - vバージョン 1.2.1,2015年3月3日
15 | - たくさんバグを直した
16 | - vバージョン 1.2.0,2015年2月17日
17 | - +中国
18 | - vバージョン 1.1.18,2015年1月30日
19 | - ビデオが直した (例:シークレットゲーム)
20 | - vバージョン 1.1.17,2014年12月24日
21 | - たくさんバグを直した
22 | - vバージョン 1.1.16,2014年12月15日
23 | - アンドロイドLのセーブスクリーンを直した
24 | - たくさんバグを直した
25 | - vバージョン 1.1.15,2014年12月1日
26 | - たくさんバグを直した
27 | - vバージョン 1.1.14,2014年11月24日
28 | - +高音質オーディオ
29 | - vバージョン 1.1.13,2014年11月20日
30 | - 外部ストレージを使用することができなかったキットカットの大きな短所を迂回するように修正しました。
31 | - ルーティングユーザのためにSDカードをアクセスできる権限を追加しました。
32 | - キットカットの全体画面機能を追加しました。
33 | - テキストプレビューが出なかったことを修正しました。
34 | - vバージョン 1.1.12,2014年9月5日
35 | - たくさんバグを直した
36 | - vバージョン 1.1.11,2014年8月1日
37 | - たくさんバグを直した
38 | - vバージョン 1.1.10,2014年7月26日
39 | - +ビデオのサポート
40 | - vバージョン 1.1.9,2014年7月2日
41 | - たくさんバグを直した
42 | - vバージョン 1.1.8,2014年6月9日
43 | - +ダークテーマ
44 | - vバージョン 1.1.7,2014年5月29日
45 | - +日本のメニュー
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ja/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | (バック)
4 | やめる
5 |
6 |
7 | 内蔵メモリを見つけることができません。何か間違っています!
8 | フォントをロードします…
9 | default.ttf が見つかりません!
10 | ディレクトリが見つかりません!
11 | 内蔵メモリにフォントを移動できません!
12 | フォントを読めません!
13 | 内蔵メモリがいっぱいになった。保存できません。
14 | 他のフォルダ名を選択してください
15 | 壊れたファイルをロードすることができません。\n別のファイルをロードしてください。
16 | ゲームを始めることができません。 現在、ゲームの必要なファイルが正しくない、又は不足します。\nゲームの必要なファイルを全てコピーしたのかしっかりチェックしてください。
17 | このゲームの中で複数のスクリプトファイルが発見されました。 そのうち最初のファイルだけが使用されます。\n\n使用されないファイル:
18 |
19 |
20 | 設定
21 | フォルダを変更する
22 |
23 |
24 | 全般
25 |
26 | レンダリング
27 | 文字を読みやすく輪郭を描きます。
28 | 文字の輪郭を描画する。
29 |
30 | コントロール
31 | スワイプするまでボタンを非表示。
32 | ボタンを表示するジェスチャー
33 | ジェスチャーに隠されたボタンを取り上げます。
34 | スワイプジェスチャー
35 |
36 | フォルダ
37 | ゲームが含まれているデフォルトのフォルダを設定します。
38 | デフォルトフォルダの設定
39 |
40 | アバウト
41 | 著者:
42 | バージョン:
43 | ウェブサイト:
44 | このアプリケーションのソースは無料です。もしこのコードを使用したい場合は、Studio OGA OgapeeとMatthew Ngとの下さるください。
45 | Studio O.G.A. Ogapee(オリジナル製作)には、アプリケーションのソースを提供したことに対して感謝の意を表します。
46 |
47 | 変更
48 |
49 | 外観
50 | テーマ
51 | 白
52 |
53 | - @string/settings_theme_default_entry
54 | - 黒
55 |
56 |
57 | 再生
58 | 外部ビデオプレーヤーを使う
59 | 高音質オーディオ使用
60 |
61 |
62 | フォルダを選ぶ
63 | 選択
64 | バック
65 | 次
66 | 終了
67 | リブート
68 |
69 | 新しいフォルダー
70 | このアプリを評価!
71 | OK、 このメッセージを再表示しない
72 |
73 |
74 | コントロール
75 | 文字
76 |
77 | この設定は、すべてのゲームでデフォルトとして設定されます。
78 |
79 | - 両側から押し
80 | - 左から押し
81 | - 右から押し
82 |
83 | ボタンを表示するジェスチャー
84 | スワイプジェスチャー
85 |
86 | 文字サイズを固定します。
87 | 文字サイズ:
88 | 日本語
89 |
90 |
91 | コピーが終了した。既存のフォルダを内部メモリに移しました。
92 | セーブファイルをコピー完了しました。
93 | コピーに失敗しました。
94 | 内部メモリがいっぱいになってゲームをコピーできません。
95 | コピーできるファイルがありません。
96 | アンドロイド4.4.Xバージョンのキットカットを使用するフォンの中には外部ストレージを使用できないように詰まっています。これがあなたがゲームをセーブしない理由です。\nの問題を修正ボタンを押してください。
97 | セーブフォルダが存在しません。
98 | あなたのSDカードはもう使用が可能です。そして内部メモリにセーブファイルがあります。このファイルを再び元のフォルダに回して欲しいですか?
99 | もうセーブファイルは元のフォルダに復帰しており、このアプリはセーブファイルをこれ以上他のフォルダに保存しません。
100 | SDカードの修正を失敗しました。なぜならplaform.xmlファイルが存在しません。
101 | システムを修正できません。携帯電話をまた始めてみますか?もしすでに再開をして見れば、matthewn4444@gmail.comメールに英語で連絡をください。
102 | システムを修正できません。matthewn4444@gmail.comメールに英語で連絡をください。.
103 | 修正が完了しました。機器を再起動させてください。
104 |
105 | セーブフォルダ変更
106 |
107 | セーブフォルダの選択
108 | 問題を修正
109 | ファイルをスキャン中
110 | ファイルをコピー中
111 | ファイルをコピーするフォルダ
112 | ファイル:
113 | サイズ:
114 | コピーするファイルを選んでください。
115 | 残容量:
116 | (どんなファイルで交代)
117 | この方法は、あなたのSDカードをアプリがアクセスが可能するようにシステムを修正します。\n\nこのアプリは問題を修正しながら起こった何事にも補償をすることはできません。\n\nシステム内部/system/etc/permissions/platform.xmlファイルにWRITE_EXTERNAL_STORAGEパーミッションを追加することで
118 | 選択によってこのアプリが貴方のシステムをアクセスすることに同意しました。
119 | 直しています…
120 |
121 |
122 | - ゲームを内部メモリに移動
123 | - ゲームのセーブファイルだけを内部メモリに移動
124 | - SDカードをアクセス可能するように修正(ルーティングユーザ)
125 |
126 |
127 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ko/change_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 변경사항
4 |
5 | - v버전 1.2.5,2018년 9월 29일
6 | - 버그를 고쳤다
7 | - v버전 1.2.4,2015년 8월 7일
8 | - 고정 된 한국어 텍스트 (쓰르라미 울적에)
9 | - v버전 1.2.3,2015년 7월 25일
10 | - 비디오 고친 (달에 다가서는 소녀의 작법2, 나츠이로레시피)
11 | - 많은 버그를 고쳤다 (리틀버스터즈)
12 | - v버전 1.2.2,2015년 3월 20일
13 | - 게임 고정: 예익의 유스티아, 점점 더
14 | - v버전 1.2.1,2015년 3월 3일
15 | - 고정된 게임을
16 | - v버전 1.2.0,2015년 2월 17일
17 | - +중국어
18 | - v버전 1.1.18,2015년 1월 30일
19 | - 비디오 고친 (Lovely Quest, Secret Game, Akatsuki no Goei)
20 | - v버전 1.1.17,2014년 12월 24일
21 | - 많은 버그를 고쳤다
22 | - v버전 1.1.16,2014년 12월 15일
23 | - 많이 게임을 고쳤다(새벽의 호위,크로스 채널,등).
24 | - 안드로이드 L의 세이브 스크린을 고쳤다.
25 | - v버전 1.1.15,2014년 12월 1일
26 | - 많은 버그를 고쳤다
27 | - v버전 1.1.14,2014년 11월 24일
28 | - +고음질 오디오
29 | - 추락하는 고정형 비디오 플레이어
30 | - v버전 1.1.13,2014년 11월 20일
31 | - 외부저장소를 사용할 수 없던 킷캣의 큰 단점을 우회하도록 수정하였습니다.
32 | - 루팅 유저를 위해 SD카드를 접근 할 수 있는 권한을 추가 하였습니다.
33 | - 킷켓의 전체화면 기능을 추가했습니다.
34 | - 텍스트 프리뷰가 안나오던 것을 수정하였습니다.
35 | - v버전 1.1.12,2014년 9월 5일
36 | - 많은 버그를 고쳤다
37 | - v버전 1.1.11,2014년 8월 1일
38 | - 많은 버그를 고쳤다
39 | - v버전 1.1.10,2014년 7월 26일
40 | - +비디오 지원
41 | - v버전 1.1.9,2014년 7월 2일
42 | - 많은 버그를 고쳤다
43 | - v버전 1.1.8,2014년 6월 9일
44 | - +어두운 테마
45 | - v버전 1.1.7,2014년 5월 29일
46 | - +일본의 메뉴
47 | - v버전 1.1.6,2014년 5월 7일
48 | - 러시아어
49 | - v버전 1.1.5,2014년 4월 16일
50 | - 일반적인 한글 인코딩(ANSI, EUC-KR)스크립트로 게임실행가능
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ko/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 온스크립터 플러스 (광고 무료)
4 |
5 | (뒤로가기)
6 | 종료
7 |
8 |
9 | 내장 메모리를 찾을 수 없습니다. 무언가 잘못 되었습니다!
10 | …폰트 로딩중
11 | default.ttf 파일을 찾을 수 없습니다!
12 | 디렉토리를 찾을 수 없습니다!
13 | 내장 메모리로 폰트를 옮길 수 없습니다!
14 | 폰트를 읽을 수 없습니다!
15 | 내장 메모리가 가득 찼습니다. 저장할 수 없습니다
16 | 다른 폴더 이름을 선택하십시오
17 | 망가진 파일을 로드할 수 없습니다.\n다른 파일을 로드하세요.
18 | 게임을 시작할 수 없습니다. 현재 게임의 필요한 파일이 올바르지 않거나 부족합니다.\n게임의 필요한 파일을 전부 복사했는지 확실히 체크해 주세요.
19 | 이 게임안에서 여러개의 스크립트 파일이 발견되었습니다. 그 중 가장 처음의 파일만 사용됩니다. \n\n사용되지 않는 파일 :
20 |
21 |
22 | 설정
23 | 폴더 바꾸기
24 |
25 |
26 | 일반
27 |
28 | 렌더
29 | 글자를 읽기 쉽게 윤곽선을 그립니다.
30 | 글자에 윤곽선 그리기.
31 |
32 | 컨트롤
33 | 스와이프 하기 전까지 버튼을 숨깁니다.
34 | 버튼을 표시하기 위한 제스처.
35 | 제스처로 숨겨진 버튼을 불러옵니다.
36 | 스와이프 제스처
37 |
38 | 폴더
39 | 게임이 들어있는 기본 폴더를 설정합니다.
40 | 기본 폴더 설정
41 |
42 | 어플에 대하여
43 | 제작자:
44 | 버전:
45 | 웹사이트:
46 | 이 어플리케이션 소스는 무료입니다. 만약 이 코드를 사용하고자 한다면, Studio O.G.A. Ogapee 와 Matthew Ng에게 연락해주시길 바랍니다.
47 | Studio O.G.A. Ogapee (오리지널 제작자)에게 이 어플과 소스를 제공한 것에 대해 감사를 표합니다.\n이 어플을 한글로 번역해주신 MadZun에게 감사를 표합니다.\n(http://madzun.blog.me)
48 |
49 | 변경사항
50 |
51 | 외관
52 | 테마
53 | 화이트
54 |
55 | - @string/settings_theme_default_entry
56 | - 검정
57 |
58 |
59 | 재생
60 | 외부 비디오 플레이어를 사용
61 | 고음질 오디오 사용
62 |
63 |
64 | 폴더 고르기
65 | 선택
66 | 뒤로
67 | 다음
68 | 어플 종료
69 | 재부팅
70 |
71 | 새로운 폴더
72 | 이 앱을 평가!
73 | 네, 그만 보여주세요
74 |
75 |
76 | @string/settings_controls_cate
77 | 본문
78 |
79 | 이 설정은 모든 게임에서 기본으로 설정됩니다.
80 |
81 | - 양쪽에서 밀기
82 | - 왼쪽에서 밀기
83 | - 오른쪽에서 밀기
84 |
85 | 버튼을 표시하기 위한 제스처.
86 | 스와이프 제스처
87 |
88 | 글자 크기를 고정시킵니다.
89 | 글자 크기:
90 | 한국어 日本語
91 |
92 |
93 | 복사 완료. 기존 폴더를 내부저장소로 옮겼습니다.
94 | 세이브 파일을 복사 완료하였습니다.
95 | 복사 실패.
96 | 내부 저장소가 가득 차서 게임을 복사 할 수 없습니다.
97 | 복사 할 수 있는 파일이 없습니다.
98 | 안드로이드 4.4.X 버전의 킷켓을 사용하는 폰들 중에는 외부 저장소를 사용 할 수 없도록 막혀있기도 합니다. 이것이 당신이 게임을 세이브 하지 못하는 이유입니다..\n문제를 수정 버튼을 눌러주세요.
99 | 세이브 폴더가 존재하지 않습니다.
100 | 당신의 SD카드는 이제 사용이 가능합니다. 그리고 내부저장소에 세이브 파일들이 있습니다. 이 파일을 다시 원래의 폴더로 돌리길 원하십니까?
101 | 이제 세이브 파일들은 원래의 폴더로 돌아갔고 온스크립터 플러스는 세이브 파일을 더 이상 다른 폴더에 저장하지 않습니다.
102 | SD카드의 수정을 실패하였습니다. 왜냐하면 plaform.xml 파일이 존재하지 않습니다.
103 | 시스템을 수정할 수 없습니다. 핸드폰을 다시 시작 해보시겠습니까? 만약 이미 다시 시작을 해 보았다면, matthewn4444@gmail.com 메일에 영어로 연락을 주세요.
104 | 시스템을 수정할 수 없습니다. matthewn4444@gmail.com 메일로 영어로 연락을 주세요.
105 | 수정이 완료 되었습니다. 기기를 재부팅 하여 주십시오.
106 |
107 | 세이브 폴더 변경
108 |
109 | 세이브 폴더 선택
110 | 문제를 수정
111 | 파일을 스캔중
112 | 파일을 복사중
113 | 파일을 복사할 폴더
114 | 파일:
115 | 크기:
116 | 복사 할 파일을 고르세요.
117 | 남은 용량:
118 | (어떤 파일로 교체)
119 | 이 방법은 당신의 SD카드를 어플이 접근이 가능하도록 시스템을 수정합니다.\n\n이 어플은 이 문제를 수정하면서 일어나는 어떠한 일에도 보상을 할 수 없습니다.\n\n시스템 내부 /system/etc/permissions/platform.xml 파일에 WRITE_EXTERNAL_STORAGE 퍼미션을 추가할 것입니다.
120 | 선택의 의해 이 온스크립터 플러스가 당신의 시스템을 접근하도록 동의했습니다.
121 | 수정중…
122 |
123 |
124 | - 게임을 내부 저장소로 이동
125 | - 게임의 세이브 파일만 내부 저장소로 이동
126 | - SD카드를 접근 가능하도록 수정(루팅유저)
127 |
128 |
129 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ru/change_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Последние изменения
4 |
5 | - vVersion 1.2.5,9/29/2018
6 | - Исправлено ошибок
7 | - vVersion 1.2.4,8/7/2015
8 | - Исправлено множество ошибок
9 | - vVersion 1.2.3,7/25/2015
10 | - фиксированная видео (Little Busters, Natsuiro Recipe)
11 | - vVersion 1.2.2,3/20/2015
12 | - исправлены некоторые игры: Kagetsu Toyha, Umineko
13 | - vVersion 1.2.1,3/3/2015
14 | - Исправлено сохранение игры
15 | - vVersion 1.2.0,2/17/2015
16 | - +китайский
17 | - Исправления Tsukihime Demo
18 | - vVersion 1.1.18,1/30/2015
19 | - фиксированная видео (Lovely Quest, Secret Game, Akatsuki no Goei)
20 | - vVersion 1.1.17,12/24/2014
21 | - Исправлено множество ошибок
22 | - vVersion 1.1.16,12/15/2014
23 | - Исправлено множество ошибок
24 | - vVersion 1.1.15,12/1/2014
25 | - Исправлено множество ошибок
26 | - vVersion 1.1.14,11/20/2014
27 | - Добавил выше Выбор качества в настройках
28 | - vVersion 1.1.13,11/20/2014
29 | - Исправлена проблема сохранения на внешнюю SD карту в Android Kitkat
30 | - Добавлен фикс возможности записи на SD карту пользователям с правами root
31 | - Добавлен режим погружения (полный экран) в Android Kitkat
32 | - Исправлены некоторые проблемы размещения текста
33 | - vVersion 1.1.12,9/5/2014
34 | - Исправлено множество ошибок
35 | - vVersion 1.1.11,8/1/2014
36 | - Исправлено множество ошибок
37 | - vVersion 1.1.10,7/26/2014
38 | - добавлена поддержка видео
39 | - vVersion 1.1.9,7/2/2014
40 | - Исправлено множество ошибок
41 | - vVersion 1.1.8,6/9/2014
42 | - +темная тема
43 | - vVersion 1.1.7,5/29/2014
44 | - добавил японское меню
45 | - vVersion 1.1.6,5/7/2014
46 | - Добавлена поддержка русского текста в приложении
47 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | (Назад)
4 | Выход
5 |
6 |
7 | Не найдена внутренняя память, что-то пошло не так!
8 | Загрузка шрифтов…
9 | Не удалось найти файл шрифта по умолчанию в папке assets!
10 | Не удалось найти папку private!
11 | Не удалось записать файл шрифта во внутреннею память!
12 | Не удалось загрузить шрифт!
13 | Внутренняя память заполнена и не может спасти.
14 | Пожалуйста, выберите другое имя
15 | Не удается загрузить поврежденный файл.\nПожалуйста, загрузите другой файл.
16 | Игра вылетает при запуске, возможно потому что отсутствуют некоторые файлы игры или они повреждены.\nПожалуйста, убедитесь, что вы скопировали все файлы игры должным образом.
17 | Найдено несколько скриптов для этой игры, перечисленных ниже. Будет использоваться только один скрипт, находящийся непосредственно в папке игры.\n\nНеиспользуемые:
18 |
19 |
20 | Настройки
21 | Сменить папку
22 |
23 |
24 | общие
25 |
26 | Видео настройки
27 | Отображает контур для каждого символа для удобства чтения.
28 | Отображение контура шрифта
29 |
30 | Управление
31 | Скрывает кнопки, пока пользователь не проведет по экрану, чтобы отобразить их.
32 | Провести по экрану, чтобы отобразить кнопки.
33 | Жест чтобы отобразить кнопки, когда они спрятаны.
34 | Провести по экрану
35 |
36 | Папка
37 | Выберите местоположение папки по умолчанию для чтения визуальных романов.
38 | Выберите папку по умолчанию
39 |
40 | О программе
41 | Автор:
42 | Version:
43 | Website:
44 | Это приложение бесплатно и с открытым исходным кодом. Если вы планируете использовать код, пожалуйста, укажите Studio Oga Ogapee и Matthew Ng.
45 | Благодаря Studio O.G.A. Ogapee (первый автор) возможно запустить это приложение.
46 |
47 | Посмотреть журнал изменений
48 |
49 | внешний вид
50 | тема
51 | белый
52 |
53 | - @string/settings_theme_default_entry
54 | - черный
55 |
56 |
57 | Воспроизведение
58 | Используйте внешний видеоплеер
59 | Использовать высокое качество звука
60 |
61 |
62 | Выберите папку
63 | Выбрать
64 | Назад
65 | Далее
66 | Закрыть приложение
67 | Перезагрузить
68 | Отправте письмо местоположением sdcard на matthewn4444@gmail.com.
69 | Что-бы добавить перевод для вашего языка напишите мне
70 | Создать новую папку
71 | Оцените приложение
72 | ОК, больше не показывать
73 |
74 |
75 | Управление
76 | Текст
77 |
78 | Глобальные настройки управления
79 |
80 | - Проведите с двух сторон
81 | - Проведите по экрану слева
82 | - Проведите по экрану справа
83 |
84 | Провести по экрану
85 |
86 |
87 | Установите масштабирование текста
88 | Масштаб текста:
89 | Русский 日本語
90 |
91 |
92 | Копирование завершено. Теперь папка по умолчанию во внутренней памяти.
93 | Копирование сохранений завершено.
94 | Не удалось выполнить копирование.
95 | Внутренняя память заполнена, нельзя скопировать файлы игры.
96 | Нет файлов для копирования.
97 | Начиная с Android Kitkat 4.4.X, некоторые телефоны заблокировали доступ записи на внешнюю SD карту. Это причина почему вы не можете сохранить. \nПожалуйста выберите, как исправить эту проблему.
98 | Папка сохранений не существует.
99 | Теперь возможна запись на SD карту, но у вас есть файлы сохранений во внутренней памяти, вы бы хотели переместить их?
100 | Теперь возможна запись. Вам нужно скопировать сохранения из папки сохранений в папку с игрой. Сейчас приложение будет читать сохранения из папки игры, а не из папки сохранений.
101 | Не удается исправить разрешение на запись на внешнюю SD карту, потому что platform.xml не существует.
102 | Нельзя применить исправления к системе, вы пробовали перезагрузить? Если вы уже пробовали перезагрузиться, просьба сообщить об этом в matthewn4444@gmail.com.
103 | Не удается изменить системные файлы. Пожалуйста сообщите об этом matthewn4444@gmail.com.
104 | Чтобы применить изменения перезагрузите устройство.
105 |
106 | Изменить папку сохранений
107 |
108 | Выбрать папку сохранений
109 | Выберите способ исправить сохранения
110 | Сканирование файлов
111 | Копирование файлов
112 | Выберите назначение копирования
113 | Файл:
114 | Размер:
115 | Выбрать файлы для копирования
116 | Осталось свободного места:
117 | (Замена некоторых файлов)
118 | Эта операция исправит запись на внешнюю SD карту. Она изменяет системные файлы.\n\n Автор приложения не несет ответственности за возникшие проблемы с телефоном. Согласившись, вы несете ответственность за любые проблемы, которые могут случиться, в том числе, что телефон перестанет работать.\n\nБудет записано разрешение WRITE_EXTERNAL_STORAGE «media_rw» в файл /system/etc/permissions/platform.xml.
119 | Выбрав, вы соглашаетесь с тем, что это приложение измененит системные файлы с правами суперпользователя.
120 | Применение исправления…
121 |
122 |
123 | - Переместить ваши игры в папку внутренней памяти
124 | - Переместить только ваши сохранения в папку внутренней памяти
125 | - Применить исправление SD карты для этой проблемы (нужен root)
126 |
127 |
--------------------------------------------------------------------------------
/app/src/main/res/values-xlarge/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 27dp
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh/change_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 改动日志
4 |
5 | - v版本 1.2.5,2018年9月29日
6 | - 修正错误
7 | - v版本 1.2.4,2015年8月7日
8 | - 崩溃固定的游戏 (Moon of Darkness)
9 | - v版本 1.2.3,2015年7月25日
10 | - 视频被修理
11 | - 修正错误
12 | - v版本 1.2.2,2015年3月20日
13 | - 修正错误
14 | - v版本 1.2.1,2015年3月3日
15 | - 修正错误
16 | - v版本 1.2.0,2015年2月17日
17 | - +中國
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | (返回)
4 | 退出
5 |
6 |
7 | 找不到内部存储,出错!
8 | 加载字体中…
9 | 在assets中找不到默认字体文件!
10 | 找不到私人目录!
11 | 无法对内部存储读写字体文件!
12 | 无法读取字体!
13 | 没有足够的空间存储设置.
14 | 文件夹已存在,创建新文件夹.
15 | 存储文件已损坏无法加载. 请选择另一个.
16 | 此游戏在启动的时候崩溃,因为丢失或损坏的游戏文件。\n请确认您已经正确的复制所有游戏文件到指定文件夹
17 | "在下列游戏里发现多个文本文档。只有在游戏文件夹下的文本文档会被使用。\n\n未使用:
18 |
19 |
20 | 设置
21 | 改变文件
22 |
23 |
24 | 普通设置
25 |
26 | 渲染
27 | 为了方便阅读显示每个字母的轮廓.
28 | 渲染字体的轮廓
29 |
30 | 控制
31 | 在用户划动呼出控制前隐藏控制.
32 | 划动可见控制
33 | 呼出设置手势.
34 | 划动手势
35 |
36 | 文件夹
37 | 选择一个读取可见小说文件的默认文件夹位置.
38 | 选择默认文件夹
39 |
40 | 关于
41 | 作者:
42 | 版本:
43 | 网页:
44 | 此程序免费并开源. 如果你想用此程序的代码, 请提及 Studio O.G.A. Ogapee 和 Matthew Ng.
45 | 感谢 Studio O.G.A. Ogapee (原作者) 关于此程序的说明和源代码.。\n中文翻译:沈宇抗
46 |
47 | 看改动日志
48 |
49 | 外观
50 | 主题
51 | 白
52 |
53 | - @string/settings_theme_default_entry
54 | - 黒
55 |
56 |
57 | 重放
58 | 使用外部播放器
59 | 使用高质量音频
60 |
61 |
62 | 选择文件夹
63 | 选择
64 | 返回
65 | 下一步
66 | 关闭程序
67 | 重启
68 | 用英语发送SD卡的位置信息到 matthewn4444@gmail.com
69 | 创建新文件夹
70 | 请给个好评!
71 | 好。不要在提示我了
72 |
73 |
74 | 控制
75 | 文本
76 |
77 | 这些控制设置全球通用.
78 |
79 | - 从底部上划
80 | - 从左部划动
81 | - 从右部划动
82 |
83 | 划动打开设置
84 | 划动手势
85 |
86 | 设置放大字体大小.
87 | 大小比例:
88 | 中国 日本語
89 |
90 |
91 | 复制完成. 默认文件夹已被设置为内部存储.
92 | 已完成复制存档文件.
93 | 复制失败.
94 | 内部存储已满, 无法复制游戏文件.
95 | 找不到文件复制.
96 | 因为在安卓 Kitkat 4.4.X, 一些手机限制了此程序的权限所以无法在外部SD卡存档,这就是为什么无法存档.\n请选择如何修复此问题.
97 | 存档文件不存在.
98 | 现在可以读写SD卡,你在内部存储还有存档文件, 你想要将他们移动到此文件夹吗?.
99 | 现在已经可以读写. 你需要复制剩余的存档文件到原游戏文件夹. 此程序会读写游戏文件夹内部的存档文件而不是原存档文件夹.
100 | 因为 plaform.xml 不存在,无法对外置SD卡进行修复读取权限.
101 | 无法对系统进行修复, 请尝试重启? 如果已经重启过仍未修复, 请把这个问题上报到 matthewn4444@gmail.com.
102 | 无法改动系统文件. 请把这个问题上报到 matthewn4444@gmail.com.
103 | 为应用改动请重启设备.
104 |
105 | 改变存档文件夹
106 |
107 | 选择一个存档文件
108 | 选择如何修复
109 | 扫描文件
110 | 复制文件
111 | 选择目标文件夹
112 | 文件:
113 | 大小:
114 | 选择要复制的文件
115 | 剩余可用空间:
116 | (正在替换文件)
117 | 此操作会修复并可以读写外部SD卡存储. 并会用root权限修改系统文件.\n\n此程序对于修改产生的任何问题没有任何责任. \n\n这操作会写入 "media_rw" 到文件 /system/etc/permissions/platform.xml 在 WRITE_EXTERNAL_STORAGE 权限
118 | 你同意让这个程序用root权限修改系统文件.
119 | 正在修复…
120 |
121 |
122 | - 将你的游戏移动到内部存储的文件夹
123 | - 将你的游戏存档移动到内部存储的文件夹
124 | - 对这个问题请使用SD卡修复\n(可能需要root)
125 |
126 |
127 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/values/change_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 10dp
4 | change.log.pref.key
5 | Recent Changes
6 | •
7 |
8 | - vVersion 1.2.5,9/29/2018
9 | - Added a way to view sdcards, should work with most devices/versions, but may not work on some
10 | - vVersion 1.2.4,8/7/2015
11 | - Fixed freezing when not choosing an external video player
12 | - Added more error messages for corrupted save files
13 | - Fixed rendering text for all Korean games
14 | - Blocked PONScripter games
15 | - Fixed Moon of Darkness from crashing on startup (Chinese)
16 | - vVersion 1.2.3,7/25/2015
17 | - Fixed games crashing when \'#\' is used in the script
18 | - Fixed a lot of videos that didn\'t run before (Umineko, Tsuki ni yorisou otome no sahou 2, etc)
19 | - vVersion 1.2.2,3/20/2015
20 | - Added "ext_card" and "MicroSD" paths as external sdcard cards
21 | - Fix several Korean translated games (Hotch Kiss, Auyoki no Eustia, Princess Frontier)
22 | - Unineko is playable
23 | - Fixes some text glitches from Kagetsu Tohya
24 | - vVersion 1.2.1,3/3/2015
25 | - Fixes saving when not providing a save folder
26 | - vVersion 1.2.0,2/17/2015
27 | - Added Chinese language
28 | - Fixes menu decoding when using different script language
29 | - Changed preferences from xml to json
30 | - Fixes Tsukihime Russian Demo so it can play
31 | - vVersion 1.1.18,1/30/2015
32 | - Fixed videos (Akatsuki no Goei, Lovely Quest, Secret Game, etc)
33 | - vVersion 1.1.17,12/24/2014
34 | - Prevent loading corrupted save files that causes crashes
35 | - vVersion 1.1.16,12/15/2014
36 | - Fixed freezing when turning phone on
37 | - Fixed side controls from disappearing
38 | - Fixed a bunch of Korean games (e.g Akatsuki no Goei, Cross channel, Nanatsu no Fushigi no Owaru Toki, etc)
39 | - Fixed save/load slots layout
40 | - vVersion 1.1.15,12/1/2014
41 | - Fixed the black screen on Tsukihime
42 | - Fixed loading issues with Kagetsu Toyha
43 | - Fixed crashing on Gingerbread
44 | - vVersion 1.1.14,11/24/2014
45 | - Added higher quality option in settings
46 | - Fixed video player from crashing
47 | - Hid statusbar for Android 4.0–4.1 when playing a game
48 | - Fixed Gingerbread crashing
49 | - vVersion 1.1.13,11/20/2014
50 | - Bypass Kitkat issue not able to save to external sdcard
51 | - Added fix to allow rooted users to write to sdcard
52 | - Added Kiktat immersion (fullscreen) mode
53 | - Fixed some text placement issues
54 | - vVersion 1.1.12,9/5/2014
55 | - Added more sd card locations
56 | - vVersion 1.1.11,8/1/2014
57 | - Fixes typemoon games (eg. Kagetsu Tohya)
58 | - Fixes bug that did not allow users to pick a custom font
59 | - vVersion 1.1.10,7/26/2014
60 | - Added video support
61 | - Fixes controls for widescreen games
62 | - Increased audio quality
63 | - Reduced ad frequency
64 | - vVersion 1.1.9,7/2/2014
65 | - Fixed various bugs
66 | - vVersion 1.1.8,6/9/2014
67 | - Added Dark Theme
68 | - vVersion 1.1.7,5/29/2014
69 | - Added Japanese menu translation
70 | - Fixed back button from the game
71 | - vVersion 1.1.6,5/7/2014
72 | - Added Russian support
73 | - vVersion 1.1.5,4/16/2014
74 | - Korean (Hangul) font is supported
75 | - Fixes system text for each language
76 |
77 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 0dp
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/hidden_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 738dc93d
4 | ca-app-pub-7827835196460106/7286598875
5 | ca-app-pub-7827835196460106/5549926473
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
15 |
16 |
17 |
22 |
25 |
26 |
27 |
32 |
37 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
21 |
22 |
26 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/about_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/general_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
16 |
17 |
18 |
22 |
30 |
31 |
32 |
35 |
39 |
40 |
41 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/settings_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | }
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:1.3.0'
8 | }
9 | }
10 | allprojects {
11 | repositories {
12 | jcenter()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/design/buttons.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/buttons.psd
--------------------------------------------------------------------------------
/design/feature-image.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/feature-image.psd
--------------------------------------------------------------------------------
/design/folder.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/folder.psd
--------------------------------------------------------------------------------
/design/icon.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/icon.psd
--------------------------------------------------------------------------------
/design/screenshots/ja/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ja/screenshot1.png
--------------------------------------------------------------------------------
/design/screenshots/ja/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ja/screenshot2.png
--------------------------------------------------------------------------------
/design/screenshots/ja/screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ja/screenshot3.png
--------------------------------------------------------------------------------
/design/screenshots/ja/screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ja/screenshot4.png
--------------------------------------------------------------------------------
/design/screenshots/ja/screenshot5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ja/screenshot5.png
--------------------------------------------------------------------------------
/design/screenshots/ja/screenshot6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ja/screenshot6.png
--------------------------------------------------------------------------------
/design/screenshots/ko/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ko/screenshot1.png
--------------------------------------------------------------------------------
/design/screenshots/ko/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ko/screenshot2.png
--------------------------------------------------------------------------------
/design/screenshots/ko/screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ko/screenshot3.png
--------------------------------------------------------------------------------
/design/screenshots/ko/screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ko/screenshot4.png
--------------------------------------------------------------------------------
/design/screenshots/ko/screenshot5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ko/screenshot5.png
--------------------------------------------------------------------------------
/design/screenshots/ru/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ru/screenshot1.png
--------------------------------------------------------------------------------
/design/screenshots/ru/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ru/screenshot2.png
--------------------------------------------------------------------------------
/design/screenshots/ru/screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ru/screenshot3.png
--------------------------------------------------------------------------------
/design/screenshots/ru/screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ru/screenshot4.png
--------------------------------------------------------------------------------
/design/screenshots/ru/screenshot5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ru/screenshot5.png
--------------------------------------------------------------------------------
/design/screenshots/ru/screenshot6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/ru/screenshot6.png
--------------------------------------------------------------------------------
/design/screenshots/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/screenshot1.png
--------------------------------------------------------------------------------
/design/screenshots/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/screenshot2.png
--------------------------------------------------------------------------------
/design/screenshots/screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/screenshot3.png
--------------------------------------------------------------------------------
/design/screenshots/screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/screenshot4.png
--------------------------------------------------------------------------------
/design/screenshots/screenshot5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/screenshot5.png
--------------------------------------------------------------------------------
/design/screenshots/screenshot6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/screenshot6.png
--------------------------------------------------------------------------------
/design/screenshots/screenshot7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/screenshot7.png
--------------------------------------------------------------------------------
/design/screenshots/screenshot8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/design/screenshots/screenshot8.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/onscripter-plus-android/239c6c861757122d10a05beac0a311e6764db9bf/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Aug 09 18:09:25 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | include ':onscripter-engine-android'
3 | include ':VPlayer_library'
4 | project(':VPlayer_library').projectDir = new File(settingsDir, 'VPlayer_lib/VPlayer_library')
5 |
--------------------------------------------------------------------------------