diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/activities/MainActivity.java b/app/src/main/java/com/luca0n/joguitos/pluck/activities/MainActivity.java index 0adeb1f..2bda23f 100644 --- a/app/src/main/java/com/luca0n/joguitos/pluck/activities/MainActivity.java +++ b/app/src/main/java/com/luca0n/joguitos/pluck/activities/MainActivity.java @@ -23,9 +23,12 @@ Contact us at . package com.luca0n.joguitos.pluck.activities; +import android.app.Activity; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; +import android.preference.PreferenceManager; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.Spinner; @@ -33,6 +36,7 @@ import androidx.appcompat.app.AlertDialog; import butterknife.BindView; import butterknife.ButterKnife; + import com.luca0n.joguitos.pluck.R; import com.luca0n.joguitos.pluck.trivia.TriviaSource; import com.luca0n.joguitos.pluck.trivia.TriviaCategory; @@ -52,6 +56,8 @@ public class MainActivity extends BaseActivity { @BindView(R.id.spinner_difficulty) Spinner spinnerDifficulty; + private static final int REQUEST_OPEN_DOCUMENT = 0; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -64,6 +70,9 @@ public class MainActivity extends BaseActivity { // Check the Android version. if (Build.VERSION.SDK_INT >= 19){ // TODO: Show the open document dialog and read the trivia file. + Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT); + i.setType("*/*"); + startActivityForResult(i, REQUEST_OPEN_DOCUMENT); return; } else { // Unsupported version. @@ -80,12 +89,28 @@ public class MainActivity extends BaseActivity { TriviaCategory category = (TriviaCategory) spinnerCategory.getSelectedItem(); TriviaDifficulty difficulty = (TriviaDifficulty) spinnerDifficulty.getSelectedItem(); + // Put the server address in the TriviaQuery object. + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + String serverKey = getResources().getString(R.string.pref_network_server); + // Load default server URL in case the player did not specify a custom server URL. + String defaultServer = getResources().getString(R.string.pref_network_server_default); + String base = sp.getString(serverKey, defaultServer) + "?"; // append "?" to the end of the URL so we can specify GET parameters. + + // Check if the custom server URL preference was empty. If it was, change it to the default URL. + if (base.equals("?")){ + base = defaultServer + "?"; + sp.edit().putString(serverKey, defaultServer).commit(); + } + TriviaQuery query = new TriviaQuery.Builder(amount) .category(category) .difficulty(difficulty) + .base(base) .build(); + // Launch the trivia game activity. Intent intent = new Intent(getApplicationContext(), TriviaGameActivity.class); + intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_SOURCE, TriviaSource.SERVER.getName()); // Specify the trivia source. intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_QUERY, query); startActivity(intent); }); @@ -112,4 +137,33 @@ public class MainActivity extends BaseActivity { new ArrayAdapter<>( this, android.R.layout.simple_list_item_1, TriviaDifficulty.values())); } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent extras){ + switch (requestCode){ + case REQUEST_OPEN_DOCUMENT: + // Was the request executed successfully? + if (resultCode == Activity.RESULT_OK){ + // Check if the user canceled the operation. + if (extras == null) + break; + + Intent intent = new Intent(getApplicationContext(), TriviaGameActivity.class); + intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_SOURCE, TriviaSource.FILE.getName()); // Specify the trivia source. + intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_SOURCE_DATA, extras.getData()); // Specify the trivia source data. In this case, since the user chose the "File" source option, we should put the file Uri object here. + startActivity(intent); + } else { + new AlertDialog.Builder(this) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.error) + .setMessage(R.string.error_trivia_file_fetch_unknown) + .setPositiveButton(android.R.string.ok, null) + .show(); + } + break; + default: + super.onActivityResult(requestCode, resultCode, extras); + break; + } + } } diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/activities/TriviaGameActivity.java b/app/src/main/java/com/luca0n/joguitos/pluck/activities/TriviaGameActivity.java index 0167303..e298853 100644 --- a/app/src/main/java/com/luca0n/joguitos/pluck/activities/TriviaGameActivity.java +++ b/app/src/main/java/com/luca0n/joguitos/pluck/activities/TriviaGameActivity.java @@ -23,7 +23,6 @@ Contact us at . package com.luca0n.joguitos.pluck.activities; -import android.app.AlertDialog; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.PorterDuff; @@ -32,6 +31,7 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.net.Uri; import android.view.View; import android.view.MenuItem; import android.widget.Button; @@ -40,30 +40,40 @@ import android.widget.ProgressBar; import android.widget.TextView; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.io.Reader; +import java.io.InputStreamReader; +import java.io.InputStream; +import java.io.BufferedReader; import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; import butterknife.BindView; import butterknife.ButterKnife; import com.luca0n.joguitos.pluck.R; import com.luca0n.joguitos.pluck.exceptions.NoTriviaResultsException; -import com.luca0n.joguitos.pluck.exceptions.InvalidServerResponseException; +import com.luca0n.joguitos.pluck.exceptions.InvalidTriviaFormatException; import com.luca0n.joguitos.pluck.fragments.TriviaGameErrorFragment; import com.luca0n.joguitos.pluck.fragments.TriviaQuestionFragment; import com.luca0n.joguitos.pluck.interfaces.IDownloadTriviaQuestionReceiver; import com.luca0n.joguitos.pluck.trivia.TriviaGame; import com.luca0n.joguitos.pluck.trivia.TriviaQuery; import com.luca0n.joguitos.pluck.trivia.TriviaQuestion; +import com.luca0n.joguitos.pluck.trivia.TriviaSource; import com.luca0n.joguitos.pluck.util.ApiUtil; import com.luca0n.joguitos.pluck.util.SoundUtil; public class TriviaGameActivity extends BaseActivity implements IDownloadTriviaQuestionReceiver { static final String EXTRA_TRIVIA_QUERY = "extra_trivia_query"; + static final String EXTRA_TRIVIA_SOURCE = "extra_trivia_source"; + static final String EXTRA_TRIVIA_SOURCE_DATA = "extra_trivia_source_data"; private final String STATE_TRIVIA_GAME = "state_trivia_game"; private TriviaGame game; + private TriviaSource source; @BindView(R.id.progress_bar) ProgressBar progressBar; @@ -96,22 +106,34 @@ public class TriviaGameActivity extends BaseActivity progressBar.setVisibility(View.VISIBLE); // Gather information about the trivia location. - /*String triviaLocation; - - switch (triviaLocation){ - case "GET_FROM_URL":*/ + String sourceData; + source = TriviaSource.get(bundle.getString(EXTRA_TRIVIA_SOURCE)); + switch (source){ + case SERVER: DownloadTriviaQuestionsTask task = new DownloadTriviaQuestionsTask(); task.setReceiver(this); - task.execute(query);/* + task.execute(query); break; - case "GET_FROM_FILE": - + case FILE: + // Attempt to open the trivia file specified by the player. + // Read the file as a plain text JSON trivia file. + StringBuilder sb = new StringBuilder(); + try { + InputStream is = getContentResolver().openInputStream((Uri) bundle.get(EXTRA_TRIVIA_SOURCE_DATA)); + Reader in = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); + for (int c; (c = in.read()) >= 0;) + sb.append((char) c); + } catch (IOException e){ + onException(e); + return; + } + onTriviaQuestionsDownloaded(sb.toString()); break; default: - // Unknown specified trivia location. + // Unknown trivia source. // TODO: Show error message to the user about this internal error. break; - }*/ + } } } @@ -159,6 +181,8 @@ public class TriviaGameActivity extends BaseActivity this.game = new TriviaGame(ApiUtil.jsonToQuestionArray(json)); } catch (Exception e) { //onNoTriviaResults(); + new AlertDialog.Builder(this) + .setMessage(e.toString()).show(); onException(e); return; } @@ -214,12 +238,19 @@ public class TriviaGameActivity extends BaseActivity // Hide the progress bar. progressBar.setVisibility(View.GONE); String msg; + int id; if (e instanceof NoTriviaResultsException) - msg = getResources().getString(R.string.error_no_trivia_results); - else if (e instanceof InvalidServerResponseException) - msg = getResources().getString(R.string.error_server_response_invalid); - else - msg = getResources().getString(R.string.error_unknown); + id = R.string.error_no_trivia_results; + else if (e instanceof InvalidTriviaFormatException) + // Check the trivia source type. + if (source == TriviaSource.SERVER) + id = R.string.error_server_response_invalid; + else + id = R.string.error_trivia_file_invalid; + else + id = R.string.error_unknown; + + msg = getResources().getString(id); Fragment errorFragment = TriviaGameErrorFragment.newInstance(msg); diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/exceptions/InvalidTriviaFormatException.java b/app/src/main/java/com/luca0n/joguitos/pluck/exceptions/InvalidTriviaFormatException.java new file mode 100644 index 0000000..3832b49 --- /dev/null +++ b/app/src/main/java/com/luca0n/joguitos/pluck/exceptions/InvalidTriviaFormatException.java @@ -0,0 +1,35 @@ +/* +Pluck: an open source trivia game for Android + +Copyright (C) 2021 Joguitos do luca0N! + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . + +This game is a fork of LibreTrivia, and its source code is available at +. + +Contact us at . +*/ + +package com.luca0n.joguitos.pluck.exceptions; + +import java.lang.Throwable; + +public class InvalidTriviaFormatException extends Exception { + public InvalidTriviaFormatException(){ + super(); + } + public InvalidTriviaFormatException(Throwable cause){ + super(cause); + } +} diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaQuery.java b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaQuery.java index f9a0767..59edc52 100644 --- a/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaQuery.java +++ b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaQuery.java @@ -23,15 +23,8 @@ Contact us at . package com.luca0n.joguitos.pluck.trivia; -import com.luca0n.joguitos.pluck.PluckApplication; -import com.luca0n.joguitos.pluck.R; - import java.io.Serializable; -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - public class TriviaQuery implements Serializable { private static final int DEFAULT_AMOUNT = 10; @@ -39,11 +32,13 @@ public class TriviaQuery implements Serializable { private final TriviaCategory category; private final TriviaDifficulty difficulty; private final TriviaType type; + private final String base; private TriviaQuery(Builder builder) { this.amount = builder.amount; this.category = builder.category; this.difficulty = builder.difficulty; + this.base = builder.base; this.type = builder.type; } @@ -52,6 +47,7 @@ public class TriviaQuery implements Serializable { private TriviaCategory category; private TriviaDifficulty difficulty; private TriviaType type; + private String base; public Builder() { this.amount = DEFAULT_AMOUNT; @@ -80,6 +76,11 @@ public class TriviaQuery implements Serializable { return this; } + public Builder base(String base){ + this.base = base; + return this; + } + public TriviaQuery build() { return new TriviaQuery(this); } @@ -89,20 +90,6 @@ public class TriviaQuery implements Serializable { public String toString() { StringBuilder url = new StringBuilder(); - // Load custom server URL. - Context c = PluckApplication.getAppContext(); - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c); - String serverKey = c.getResources().getString(R.string.pref_network_server); - // Load default server URL in case the player did not specify a custom server URL. - String defaultServer = c.getResources().getString(R.string.pref_network_server_default); - String base = sp.getString(serverKey, defaultServer) + "?"; // append "?" to the end of the URL so we can specify GET parameters. - - // Check if the custom server URL preference was empty. If it was, change it to the default URL. - if (base.equals("?")){ - base = defaultServer + "?"; - sp.edit().putString(serverKey, defaultServer).commit(); - } - url.append(base); url.append("amount=").append(this.amount); diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/util/ApiUtil.java b/app/src/main/java/com/luca0n/joguitos/pluck/util/ApiUtil.java index 5a77fb5..610ae15 100644 --- a/app/src/main/java/com/luca0n/joguitos/pluck/util/ApiUtil.java +++ b/app/src/main/java/com/luca0n/joguitos/pluck/util/ApiUtil.java @@ -47,7 +47,7 @@ import java.util.ArrayList; import com.luca0n.joguitos.pluck.R; import com.luca0n.joguitos.pluck.PluckApplication; import com.luca0n.joguitos.pluck.exceptions.NoTriviaResultsException; -import com.luca0n.joguitos.pluck.exceptions.InvalidServerResponseException; +import com.luca0n.joguitos.pluck.exceptions.InvalidTriviaFormatException; import com.luca0n.joguitos.pluck.trivia.TriviaQuery; import com.luca0n.joguitos.pluck.trivia.TriviaQuestion; import com.luca0n.joguitos.pluck.trivia.TriviaQuestionBoolean; @@ -105,13 +105,13 @@ public class ApiUtil { } public static ArrayList jsonToQuestionArray(String json) - throws NoTriviaResultsException, InvalidServerResponseException { + throws NoTriviaResultsException, InvalidTriviaFormatException { JsonObject jsonObject; try{ jsonObject = new JsonParser().parse(json).getAsJsonObject(); } catch (JsonSyntaxException e){ // Unknown server response. - throw new InvalidServerResponseException(); + throw new InvalidTriviaFormatException(e); } if (jsonObject.get("response_code").getAsInt() == 1) { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 9870330..a4d4044 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -44,6 +44,16 @@ Contact us at . app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent"> + + + + + . Server response error!\n\nCould not parse the server response. The server response may be in a unsupported version. If you are using a custom server, make sure the server address points to a valid address and then try again. An unknown error occurred! Trivia files are not supported in this version of Android. + Invalid trivia file!\n\nTrivia files should be in a plain text JSON format. + An unknown error occurred while attempting to read the opened file. Settings