| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- /*
- * Copyright (c) 2006-2024 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
- package org.love2d.android;
- import android.annotation.SuppressLint;
- import android.content.Intent;
- import android.net.Uri;
- import android.os.Build;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Menu;
- import android.view.MenuInflater;
- import android.view.MenuItem;
- import android.view.View;
- import androidx.activity.result.ActivityResultLauncher;
- import androidx.activity.result.contract.ActivityResultContracts;
- import androidx.appcompat.app.AlertDialog;
- import androidx.appcompat.app.AppCompatActivity;
- import androidx.constraintlayout.widget.ConstraintLayout;
- import androidx.recyclerview.widget.LinearLayoutManager;
- import androidx.recyclerview.widget.RecyclerView;
- import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
- import java.io.File;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.concurrent.Executor;
- import java.util.concurrent.Executors;
- import java.util.zip.ZipFile;
- public class MainActivity extends AppCompatActivity {
- private static final String TAG = "MainActivity";
- private final Executor executor = Executors.newSingleThreadExecutor();
- private final ActivityResultLauncher<String[]> openFileLauncher = registerForActivityResult(
- new ActivityResultContracts.OpenDocument(),
- (Uri result) -> {
- if (result != null) {
- Intent intent = new Intent(this, GameActivity.class);
- intent.setData(result);
- startActivity(intent);
- }
- }
- );
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- RecyclerView recyclerView = findViewById(R.id.recyclerView);
- SwipeRefreshLayout swipeLayout = findViewById(R.id.swipeRefreshLayout);
- ConstraintLayout noGameText = findViewById(R.id.constraintLayout);
- GameListAdapter adapter = new GameListAdapter();
- // Set refresh listener
- swipeLayout.setOnRefreshListener(() -> {
- scanGames(adapter, noGameText, swipeLayout);
- });
- // Set layout manager and adapter
- recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
- recyclerView.setAdapter(adapter);
- scanGames(adapter, noGameText, null);
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.options_menu, menu);
- return true;
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- int itemId = item.getItemId();
- // Handle item selection
- if (itemId == R.id.optionItem) {
- openFileLauncher.launch(new String[]{"*/*"});
- return true;
- } else if (itemId == R.id.optionItem2) {
- Intent intent = new Intent(this, GameActivity.class);
- startActivity(intent);
- return true;
- } else if (itemId == R.id.optionItem3) {
- getGameFolderDialog().show();
- return true;
- } else if (itemId == R.id.optionItem4) {
- Intent intent = new Intent(this, AboutActivity.class);
- startActivity(intent);
- return true;
- } else {
- return super.onOptionsItemSelected(item);
- }
- }
- private AlertDialog getGameFolderDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this)
- .setTitle(getString(R.string.game_folder))
- .setPositiveButton(R.string.ok, (dialog1, which) -> {
- });
- StringBuilder message = new StringBuilder()
- .append(getString(R.string.game_folder_location, getPackageName()))
- .append("\n\n");
- if (Build.VERSION.SDK_INT >= 30) {
- message.append(getString(R.string.game_folder_inaccessible));
- } else {
- message.append(getString(R.string.game_folder_accessible));
- }
- return builder.setMessage(message.toString()).create();
- }
- @SuppressLint("NotifyDataSetChanged")
- private void scanGames(GameListAdapter adapter, ConstraintLayout noGameText, SwipeRefreshLayout swipeRefreshLayout) {
- executor.execute(() -> {
- File extDir = getExternalFilesDir("games");
- if (extDir != null) {
- if (!extDir.isDirectory()) {
- if (!extDir.mkdir()) {
- // Scan failure, abort
- runOnUiThread(() -> {
- if (swipeRefreshLayout != null) {
- swipeRefreshLayout.setRefreshing(false);
- }
- });
- Log.e(TAG, "Directory creation failure.");
- return;
- }
- }
- ArrayList<GameListAdapter.Data> validGames = new ArrayList<>();
- File[] files = extDir.listFiles();
- if (files != null) {
- for (File file : files) {
- GameListAdapter.Data gameData = null;
- if (file.isDirectory()) {
- if (isValidGamedir(file)) {
- gameData = new GameListAdapter.Data();
- gameData.path = file;
- gameData.directory = true;
- }
- } else {
- if (isValidLovegame(file)) {
- gameData = new GameListAdapter.Data();
- gameData.path = file;
- gameData.directory = false;
- }
- }
- if (gameData != null) {
- validGames.add(gameData);
- }
- }
- }
- boolean empty = validGames.isEmpty();
- runOnUiThread(() -> {
- if (empty) {
- adapter.setData(null);
- } else {
- GameListAdapter.Data[] gameDatas = new GameListAdapter.Data[validGames.size()];
- validGames.toArray(gameDatas);
- adapter.setData(gameDatas);
- }
- adapter.notifyDataSetChanged();
- if (swipeRefreshLayout != null) {
- swipeRefreshLayout.setRefreshing(false);
- }
- noGameText.setVisibility(empty ? View.VISIBLE : View.INVISIBLE);
- });
- }
- });
- }
- public static boolean isValidLovegame(File file) {
- boolean valid = false;
- try {
- ZipFile zip = new ZipFile(file, ZipFile.OPEN_READ);
- valid = zip.getEntry("main.lua") != null;
- zip.close();
- } catch (IOException ignored) {
- }
- return valid;
- }
- public static boolean isValidGamedir(File file) {
- File mainLua = new File(file, "main.lua");
- return mainLua.isFile();
- }
- }
|