├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── trianguloy
│ │ └── numericriddlegenerator
│ │ ├── Preferences.java
│ │ ├── Riddle.java
│ │ └── Utils.java
│ ├── play
│ ├── contact-email.txt
│ ├── contact-website.txt
│ ├── listings
│ │ └── en-US
│ │ │ ├── full-description.txt
│ │ │ ├── graphics
│ │ │ ├── feature-graphic
│ │ │ │ └── featured.png
│ │ │ ├── icon
│ │ │ │ └── ic_launcher-playstore.png
│ │ │ └── phone-screenshots
│ │ │ │ ├── 1.png
│ │ │ │ ├── 2.png
│ │ │ │ ├── 3.png
│ │ │ │ ├── 4.png
│ │ │ │ ├── 5.png
│ │ │ │ ├── 6.png
│ │ │ │ ├── 7.png
│ │ │ │ └── 99.png
│ │ │ ├── short-description.txt
│ │ │ └── title.txt
│ └── release-notes
│ │ └── en-US
│ │ └── default.txt
│ └── res
│ ├── drawable-hdpi
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ └── ic_launcher.png
│ ├── drawable-xxxhdpi
│ └── ic_launcher.png
│ ├── layout
│ └── activity_riddle.xml
│ ├── raw
│ ├── demozip
│ └── readme
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── dimens.xml
│ └── strings.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 | mapping.txt
5 | output.json
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 |
18 | # Gradle files
19 | .gradle/
20 | build/
21 |
22 | # Local configuration file (sdk path, etc)
23 | local.properties
24 |
25 | # Proguard folder generated by Eclipse
26 | proguard/
27 |
28 | # Log Files
29 | *.log
30 |
31 | # Android Studio Navigation editor temp files
32 | .navigation/
33 |
34 | # Android Studio captures folder
35 | captures/
36 |
37 | # Intellij
38 | *.iml
39 | .idea/
40 |
41 | # Keystore files
42 | *.jks
43 |
44 | # External native build folder generated in Android Studio 2.2 and later
45 | .externalNativeBuild
46 |
47 | # Google Services (e.g. APIs or Firebase)
48 | google-services.json
49 |
50 | # Freeline
51 | freeline.py
52 | freeline/
53 | freeline_project_description.json
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Custom Riddle Generator
2 |
3 | Android app made by TrianguloY
4 |
5 | Get it on Google Play:\
6 | https://play.google.com/store/apps/details?id=com.trianguloy.numericriddlegenerator \
7 | [
](https://play.google.com/store/apps/details?id=com.trianguloy.numericriddlegenerator)
10 |
11 | Get it on F-Droid:\
12 | https://f-droid.org/packages/com.trianguloy.numericriddlegenerator/ \
13 | [
](https://f-droid.org/packages/com.trianguloy.numericriddlegenerator/)
16 |
17 | You can use parts of this project in your own ones, create pull request, or upload modified versions of it AS LONG AS you credit me.
18 |
19 | How to credit:
20 | - You must add my nick (TrianguloY) in an 'about' or 'acknowledgments' section visible to the user.
21 | - You must add a link to this GitHub main page (https://github.com/TrianguloY/NumericRiddleGenerator) or subpage (if you used a part of the code or an asset) in an 'about' or 'acknowledgments' section visible to the user.
22 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion '29.0.3'
6 | defaultConfig {
7 | applicationId "com.trianguloy.numericriddlegenerator"
8 | minSdkVersion 14
9 | targetSdkVersion 29
10 | versionCode 7
11 | versionName "2.1"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled true
16 | shrinkResources true
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | implementation fileTree(dir: 'libs', include: ['*.jar'])
24 | }
25 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in E:\Users\abeln\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/trianguloy/numericriddlegenerator/Preferences.java:
--------------------------------------------------------------------------------
1 | package com.trianguloy.numericriddlegenerator;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | /**
7 | * Class to store and retrieve preferences
8 | * Sort of a wrapper of SharedPreferences
9 | */
10 |
11 | class Preferences {
12 |
13 | //the android SharedPreferences
14 | private static final String PREF_NAME = "pref";
15 | private SharedPreferences preferences;
16 | /**
17 | * Constructor, initializates the preferences
18 | * @param context the context from where load the SharedPreferences class
19 | */
20 | Preferences(Context context) {
21 | preferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
22 | }
23 |
24 |
25 |
26 | private static final String KEY_VERSION = "version";
27 | private static final String DEFAULT_VERSION = "";
28 |
29 | String getVersion(){
30 | return preferences.getString(KEY_VERSION,DEFAULT_VERSION);
31 | }
32 |
33 | void setVersion(String version){
34 | preferences.edit().putString(KEY_VERSION,version).apply();
35 | }
36 |
37 |
38 |
39 |
40 | /**
41 | * Ask again
42 | */
43 | private static final String KEY_DONTSHOWAGAIN = "dontShow";
44 | private static final Boolean DEFAULT_DONTSHOWAGAIN = false;
45 |
46 | /**
47 | * Getter for the account name
48 | * @return the selected account name, null if nothing selected
49 | */
50 | Boolean getDontShowAgain(){
51 | return preferences.getBoolean(KEY_DONTSHOWAGAIN,DEFAULT_DONTSHOWAGAIN);
52 | }
53 |
54 | /**
55 | * Setter for the account name
56 | * @param dontShowAgain the account name
57 | */
58 | void setDontShowAgain(Boolean dontShowAgain){
59 | preferences.edit().putBoolean(KEY_DONTSHOWAGAIN,dontShowAgain).apply();
60 | }
61 |
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/trianguloy/numericriddlegenerator/Riddle.java:
--------------------------------------------------------------------------------
1 | package com.trianguloy.numericriddlegenerator;
2 |
3 | import android.Manifest;
4 | import android.annotation.TargetApi;
5 | import android.app.Activity;
6 | import android.app.AlertDialog;
7 | import android.content.Context;
8 | import android.content.DialogInterface;
9 | import android.content.pm.PackageManager;
10 | import android.graphics.Bitmap;
11 | import android.graphics.BitmapFactory;
12 | import android.os.Build;
13 | import android.os.Bundle;
14 | import android.os.Environment;
15 | import android.util.Log;
16 | import android.view.View;
17 | import android.widget.ImageView;
18 | import android.widget.NumberPicker;
19 | import android.widget.ProgressBar;
20 | import android.widget.ScrollView;
21 | import android.widget.TextView;
22 |
23 | import java.io.File;
24 |
25 | public class Riddle extends Activity {
26 |
27 | private NumberPicker[] pickers;
28 | private File folder;
29 | private TextView textView;
30 | private ImageView imageView;
31 | private ScrollView scrollView;
32 | private ProgressBar progressBarView;
33 |
34 | private Preferences pref;
35 |
36 | ///////////////////// INITIALIZATIONS /////////////////////////////
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | setContentView(R.layout.activity_riddle);
42 |
43 | pref = new Preferences(this);
44 |
45 | initializeViews();
46 |
47 | if (checksPermission()) {
48 | initialize_readme();
49 | }
50 |
51 |
52 | }
53 |
54 | private void initializeViews() {
55 | //text
56 | textView = (TextView) findViewById(R.id.textView);
57 |
58 | //image
59 | imageView = (ImageView) findViewById(R.id.imageView_picture);
60 | imageView.setVisibility(View.GONE);
61 |
62 | //scrollView
63 | scrollView = (ScrollView) findViewById(R.id.scrollView);
64 |
65 | //progressBar
66 | progressBarView = (ProgressBar) findViewById(R.id.progressBar);
67 | progressBarView.setVisibility(View.GONE);
68 |
69 | //pickers
70 | pickers = new NumberPicker[4];
71 |
72 | pickers[0] = (NumberPicker) findViewById(R.id.numberPicker0);
73 | pickers[1] = (NumberPicker) findViewById(R.id.numberPicker1);
74 | pickers[2] = (NumberPicker) findViewById(R.id.numberPicker2);
75 | pickers[3] = (NumberPicker) findViewById(R.id.numberPicker3);
76 |
77 | for (int i = 0; i < 4; ++i) {
78 | pickers[i].setMinValue(0);
79 | pickers[i].setMaxValue(9);
80 | pickers[i].setWrapSelectorWheel(true);
81 | }
82 |
83 | }
84 |
85 | private void initialize_readme() {
86 |
87 | boolean saveDemo = false;
88 | boolean saveReadme = false;
89 |
90 | //folder
91 | folder = new File(Environment.getExternalStorageDirectory().getPath(), getString(R.string.filename_directory));
92 | if (!folder.exists()) {
93 | saveDemo = true;
94 | saveReadme = true;
95 | folder.mkdirs();
96 |
97 |
98 | File nomedia = new File(folder, getString(R.string.filename_nomedia));
99 | Utils.createFileIfNecessary(nomedia, getString(R.string.filecontent_nomedia));
100 | }
101 |
102 | //readme
103 | boolean showMessage = !pref.getDontShowAgain();
104 | if (!pref.getVersion().equals(BuildConfig.VERSION_NAME)) {
105 | pref.setVersion(BuildConfig.VERSION_NAME);
106 | saveReadme = true;
107 | }
108 |
109 |
110 | if (saveReadme || showMessage) {
111 | String readmeString = Utils.getRawResource(this, R.raw.readme);
112 | if (saveReadme) {
113 | File f = new File(folder, getString(R.string.filename_readme));
114 | f.delete();
115 | Utils.createFileIfNecessary(f, readmeString);
116 | }
117 | if (showMessage) {
118 | final boolean finalSaveDemo = saveDemo;
119 | new AlertDialog.Builder(this)
120 | .setTitle(R.string.title_readme)
121 | .setMessage(readmeString)
122 | .setCancelable(false)
123 | .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
124 | @Override
125 | public void onClick(DialogInterface dialogInterface, int i) {
126 | if(finalSaveDemo) {
127 | askCopyDemo();
128 | }else{
129 | initialize_app();
130 | }
131 | }
132 | })
133 | .setNegativeButton(R.string.dontShowAgain, new DialogInterface.OnClickListener() {
134 | @Override
135 | public void onClick(DialogInterface dialogInterface, int i) {
136 | pref.setDontShowAgain(true);
137 | if(finalSaveDemo) {
138 | askCopyDemo();
139 | }else{
140 | initialize_app();
141 | }
142 | }
143 | })
144 | .show();
145 | return;
146 | }
147 | }
148 |
149 | initialize_app();
150 |
151 | }
152 |
153 | private void askCopyDemo() {
154 | new AlertDialog.Builder(this)
155 | .setTitle(R.string.title_demo)
156 | .setMessage(R.string.message_demo)
157 | .setCancelable(false)
158 | .setPositiveButton("Load demo", new DialogInterface.OnClickListener() {
159 | @Override
160 | public void onClick(DialogInterface dialogInterface, int i) {
161 | Utils.copyDemo(getApplicationContext(), new File(Environment.getExternalStorageDirectory().getPath(), getString(R.string.filename_directory)));
162 | initialize_app();
163 | }
164 | })
165 | .setNegativeButton("Don't load", new DialogInterface.OnClickListener() {
166 | @Override
167 | public void onClick(DialogInterface dialogInterface, int i) {
168 | initialize_app();
169 | }
170 | })
171 | .show();
172 | }
173 |
174 | private void initialize_app(){
175 |
176 | //title
177 | File title = new File(folder, getString(R.string.filename_title));
178 | Utils.createFileIfNecessary(title, getString(R.string.app_name));
179 | setTitle(Utils.getStringFromFile(this, title));
180 |
181 | //as if button was clicked
182 | buttonClick(null);
183 | }
184 |
185 |
186 | ///////////////////// ACTIONS /////////////////////////////
187 |
188 | public void buttonClick(View view) {
189 | final Context cntx = this;
190 | progressBarView.setVisibility(View.VISIBLE);
191 | progressBarView.post(new Runnable() {
192 | @Override
193 | public void run() {
194 |
195 | //get the current number
196 | StringBuilder n = new StringBuilder();
197 | for (NumberPicker picker : pickers) {
198 | n.append(picker.getValue());
199 | }
200 | Log.d("number", n.toString());
201 |
202 | //get the textfile (can exist or not)
203 | File textFile = new File(folder, n.toString() + getString(R.string.extension_text));
204 |
205 | //get the image (can exist or not)
206 | File imageFile = null;
207 | for (String extension : getString(R.string.extension_image_list).split(getString(R.string.extension_image_split))) {
208 | imageFile = new File(folder, n.toString() + extension);
209 | if (imageFile.exists()) {
210 | break;
211 | }
212 | }
213 |
214 | //show/hide the image
215 | if (imageFile != null && imageFile.exists()) {
216 | Bitmap myBitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
217 | imageView.setImageBitmap(myBitmap);
218 | imageView.setVisibility(View.VISIBLE);
219 | } else {
220 | imageView.setVisibility(View.GONE);
221 | }
222 | imageView.requestLayout();
223 |
224 | //show/hide the text
225 | if (textFile.exists()) {
226 | textView.setText(Utils.getStringFromFile(cntx, textFile));
227 | textView.setVisibility(View.VISIBLE);
228 | } else {
229 | if (imageFile != null && imageFile.exists()) {
230 | textView.setText("");
231 | textView.setVisibility(View.GONE);
232 | } else {
233 | File defaultfile = new File(folder, getString(R.string.filename_default));
234 | Utils.createFileIfNecessary(defaultfile, getString(R.string.default_default));
235 | textView.setText(Utils.getStringFromFile(cntx, defaultfile));
236 | textView.setVisibility(View.VISIBLE);
237 | }
238 | }
239 | textView.requestLayout();
240 |
241 | //scroll to be always on top
242 | scrollView.scrollTo(0, 0);
243 |
244 | progressBarView.setVisibility(View.GONE);
245 | }
246 | });
247 | }
248 |
249 | /////////////////////////////// PERMISIONS ////////////////////////////////
250 |
251 |
252 | final private int NUMBER = 7642853;//I smashed the numeric row
253 |
254 |
255 | private boolean checksPermission() {
256 | if (Build.VERSION.SDK_INT < 23) {
257 | //should be granted
258 | return true;
259 | }
260 |
261 | if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
262 | if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
263 | Utils.showMessage(this, getString(R.string.title_askPermission), getString(R.string.message_askPermission), new DialogInterface.OnClickListener() {
264 | @TargetApi(Build.VERSION_CODES.M)
265 | @Override
266 | public void onClick(DialogInterface dialogInterface, int i) {
267 | requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, NUMBER);
268 | }
269 | });
270 | } else {
271 | requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, NUMBER);
272 | }
273 | return false;
274 | }
275 | return true;
276 | }
277 |
278 | @Override
279 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
280 | switch (requestCode) {
281 | case NUMBER:
282 | initialize_readme();
283 | break;
284 | default:
285 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
286 | }
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/app/src/main/java/com/trianguloy/numericriddlegenerator/Utils.java:
--------------------------------------------------------------------------------
1 | package com.trianguloy.numericriddlegenerator;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 |
7 | import java.io.BufferedInputStream;
8 | import java.io.BufferedReader;
9 | import java.io.File;
10 | import java.io.FileInputStream;
11 | import java.io.FileOutputStream;
12 | import java.io.FileWriter;
13 | import java.io.IOException;
14 | import java.io.InputStream;
15 | import java.io.InputStreamReader;
16 | import java.util.zip.ZipEntry;
17 | import java.util.zip.ZipInputStream;
18 |
19 | /**
20 | * Utility functions (all static)
21 | */
22 |
23 | public class Utils {
24 |
25 | //adapted from http://stackoverflow.com/questions/12910503/read-file-as-string
26 | public static String convertStreamToString(InputStream is) throws Exception {
27 | BufferedReader reader = new BufferedReader(new InputStreamReader(is));
28 | StringBuilder sb = new StringBuilder();
29 | String line;
30 | while ((line = reader.readLine()) != null) {
31 | sb.append(line).append("\n");
32 | }
33 | reader.close();
34 | return sb.toString();
35 | }
36 |
37 | public static String getStringFromFile(Context cntx, File fl) {
38 | FileInputStream fin = null;
39 | String ret = cntx.getString(R.string.error);
40 | try {
41 | fin = new FileInputStream(fl);
42 | ret = convertStreamToString(fin);
43 | } catch (Exception e) {
44 | e.printStackTrace();
45 | }finally {
46 | //Make sure you close all streams.
47 | if(fin!=null){
48 | try {
49 | fin.close();
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | }
53 | }
54 | }
55 |
56 | return ret;
57 | }
58 |
59 | public static String getRawResource(Context cntx, int resourceId){
60 | InputStream in = cntx.getResources().openRawResource(resourceId);
61 |
62 | try {
63 | return convertStreamToString(in);
64 | } catch (Exception e) {
65 | e.printStackTrace();
66 | return cntx.getString(R.string.error);
67 | }finally {
68 | try {
69 | in.close();
70 | } catch (IOException e) {
71 | e.printStackTrace();
72 | }
73 | }
74 | }
75 |
76 |
77 | public static void showMessage(Context cntx, String title, String message, DialogInterface.OnClickListener listener) {
78 | new AlertDialog.Builder(cntx)
79 | .setTitle(title)
80 | .setMessage(message)
81 | .setCancelable(false)
82 | .setPositiveButton("Ok",listener)
83 | .show();
84 | }
85 |
86 | public static void showMessageDontShowAgain(Context cntx, String title, String message, DialogInterface.OnClickListener listenerDontShowAgain) {
87 | new AlertDialog.Builder(cntx)
88 | .setTitle(title)
89 | .setMessage(message)
90 | .setCancelable(false)
91 | .setPositiveButton("Ok", null)
92 | .setNegativeButton(cntx.getString(R.string.dontShowAgain),listenerDontShowAgain)
93 | .show();
94 | }
95 |
96 | public static void createFileIfNecessary(File file, String content) {
97 | if(!file.exists()) {
98 | try {
99 | file.createNewFile();
100 | FileWriter fw = new FileWriter(file);
101 | fw.write(content);
102 | fw.close();
103 | } catch (IOException e) {
104 | e.printStackTrace();
105 | }
106 | }
107 | }
108 |
109 | //adapted from https://stackoverflow.com/questions/3382996/how-to-unzip-files-programmatically-in-android
110 | public static void copyDemo(Context cntx, File folder) {
111 | ZipInputStream zis;
112 | try
113 | {
114 | String filename;
115 | zis = new ZipInputStream(new BufferedInputStream(cntx.getResources().openRawResource(R.raw.demozip)));
116 | ZipEntry ze;
117 | byte[] buffer = new byte[1024];
118 | int count;
119 |
120 | while ((ze = zis.getNextEntry()) != null)
121 | {
122 | filename = ze.getName();
123 |
124 | // Need to create directories if not exists, or
125 | // it will generate an Exception...
126 | File fmd = new File(folder, filename);
127 | if (ze.isDirectory()) {
128 | fmd.mkdirs();
129 | continue;
130 | }
131 |
132 | FileOutputStream fout = new FileOutputStream(fmd);
133 |
134 | while ((count = zis.read(buffer)) != -1)
135 | {
136 | fout.write(buffer, 0, count);
137 | }
138 |
139 | fout.close();
140 | zis.closeEntry();
141 | }
142 |
143 | zis.close();
144 | }
145 | catch(IOException e)
146 | {
147 | e.printStackTrace();
148 | }
149 |
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/app/src/main/play/contact-email.txt:
--------------------------------------------------------------------------------
1 | correo--correo+appNRG@hotmail.com
--------------------------------------------------------------------------------
/app/src/main/play/contact-website.txt:
--------------------------------------------------------------------------------
1 | https://triangularapps.blogspot.com/
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/full-description.txt:
--------------------------------------------------------------------------------
1 | This app is a tool to create your own riddles/escape rooms (those with relations number->text/image) to play at home with friends or anywhere else.
2 |
3 | Note: you can specify only text, only image or both for each 4-digit number
4 |
5 | This is the list of things you can customize:
6 | - Title of the app
7 | - Text of a specific number
8 | - Image of a specific number
9 | - Text of not-specified number
10 |
11 | This is the list of things you can't customize (yet)
12 | - Theme of the app
13 | - Background
14 | - Number of digits (only 4)
15 | - Image of not-specified number
16 |
17 | As of update 2.0 there is now a demo you can load to see how it works.
18 | Many thanks to Jorge del Castillo for it!
19 |
20 |
21 | If you have any suggestion feel free to contact me (or write it in the comments) although I can't promise I'll be able to implement it :/
22 |
23 | The source code is available on GitHub; https://github.com/TrianguloY/NumericRiddleGenerator
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/feature-graphic/featured.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/feature-graphic/featured.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/icon/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/icon/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/phone-screenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/phone-screenshots/1.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/phone-screenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/phone-screenshots/2.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/phone-screenshots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/phone-screenshots/3.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/phone-screenshots/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/phone-screenshots/4.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/phone-screenshots/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/phone-screenshots/5.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/phone-screenshots/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/phone-screenshots/6.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/phone-screenshots/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/phone-screenshots/7.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/graphics/phone-screenshots/99.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/play/listings/en-US/graphics/phone-screenshots/99.png
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/short-description.txt:
--------------------------------------------------------------------------------
1 | A tool app to create your own custom riddle apps (number->text/image).
--------------------------------------------------------------------------------
/app/src/main/play/listings/en-US/title.txt:
--------------------------------------------------------------------------------
1 | Custom Riddle Generator [small, no ads]
--------------------------------------------------------------------------------
/app/src/main/play/release-notes/en-US/default.txt:
--------------------------------------------------------------------------------
1 | V 2.1
2 | - Removed controversial Mulan reference in the demo (note: this will only be applied to new installs or when the app folder is deleted)
3 |
4 | V 2.0
5 | Added demo/tutorial. Remember this app allows YOU to create your own riddles, but now there is a demo you can load.
6 | Many thanks to Jorge del Castillo for it!
7 |
8 | V 1.0
9 | Initial release on Play Store
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_riddle.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
21 |
22 |
29 |
30 |
37 |
38 |
45 |
46 |
53 |
54 |
62 |
63 |
64 |
67 |
68 |
75 |
76 |
82 |
83 |
92 |
93 |
105 |
106 |
107 |
108 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/demozip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/app/src/main/res/raw/demozip
--------------------------------------------------------------------------------
/app/src/main/res/raw/readme:
--------------------------------------------------------------------------------
1 | This app is a tool to create your own riddles/escape rooms (those with relations number->text/image).
2 |
3 | Note: you can specify only text, only image or both for each 4-digit number
4 |
5 | To start go to your external/internal memory and open the folder 'CustomRiddle'.
6 |
7 | There you need to put all the necessary files, either editing them directly on your device or copying them from your computer. The app will not modify any of them (except the readme) even after uninstalling the app.
8 |
9 | This is the format you need for the files:
10 |
11 | Message of a number
12 | - Name of file: digits (all 4) + '.txt' {example '0123.txt'}
13 | - Content: The text you want to be shown when the user inputs that number {example 'Correct, the next number is 4567'}
14 |
15 | Image of a number
16 | - Name of file: digits(all 4) + '.png' OR '.jpg' {example '0123.jpg'}
17 | - Content: Any image. It will be scaled to have the width as the device, can be scrolled vertically if necessary.
18 |
19 | Message of an invalid number (default message)
20 | - Name of file: default.txt
21 | - Content: The text you want to be shown when the user inputs a number without a specific file. {example: 'Incorrect, try again'}
22 |
23 | Title of app
24 | - Name of file: title.txt
25 | - Content: The text to shown as title of the activity {example 'My awesome escape room'}
26 |
27 | Final note: This message will be shown on each startup, click on 'don't show again' to disable this.
28 | But don't worry, this message is saved on the folder as readme.txt to check it when necessary.
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Numeric riddle generator
3 |
4 | Incorrect. Try again!
5 | Uh oh, this was unexpected :$\n(There was an error extracting the string from the file, did you granted the write permission?)
6 | Loading…
7 |
8 | readme.txt
9 | title.txt
10 | default.txt
11 | CustomRiddle
12 | .nomedia
13 |
14 | .txt
15 | .jpg;.png
16 | ;
17 |
18 | Don\'t show again
19 |
20 | Readme
21 | Permission needed
22 | Demo riddle
23 |
24 | This app reads the files from the external storage. You need to grant the write permission, otherwise this app will be useless.
25 | This seems your first time running this app. Do you want to load the demo riddle?\nThis will create some files in the app folder, which you can use to learn from example how to create your own riddle.\nThis option is recommended unless you already used the app in the past and already know how to create riddles.
26 |
27 | ]]>
28 | Image
29 | This file tells android not to show media files on the gallery app.
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:4.0.1'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | google()
20 | }
21 | }
22 |
23 | task clean(type: Delete) {
24 | delete rootProject.buildDir
25 | }
26 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrianguloY/NumericRiddleGenerator/d99b48b59a0e6c5bd8458f4794983591d9f3b52e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Aug 30 12:22:49 CEST 2020
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-6.1.1-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 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------