diff --git a/app/build.gradle b/app/build.gradle index cdf1158..b44a6b7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,11 +3,11 @@ plugins { } android { - namespace 'pink.yuv.android_id' + namespace 'com.psmreborn.pkgj' compileSdk 10 defaultConfig { - applicationId "pink.yuv.android_id" + applicationId "com.psmreborn.pkgj" minSdk 10 //noinspection ExpiredTargetSdkVersion dont care about google play targetSdk 10 @@ -18,7 +18,6 @@ android { buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro deleted file mode 100644 index 481bb43..0000000 --- a/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7088138..9ffa267 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,8 +1,9 @@ - - + + + titleAdapter; + private ArrayList games = null; + + public void addGame(Game game){ + this.games.add(game); + } + + public void updateGames(){ + this.titleAdapter.notifyDataSetChanged(); + } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + this.games = new ArrayList(); + + titleAdapter = new ArrayAdapter(this.getApplicationContext(), R.layout.list_item, R.id.list_content, this.games); + ListView lstView = (ListView)this.findViewById(R.id.gameList); + lstView.setAdapter(titleAdapter); + + (new NoPayStationParser(this, false)).execute(); + + lstView.setOnItemClickListener(new AdapterView.OnItemClickListener(){ + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + Game item = (Game)adapterView.getItemAtPosition(i); + (new PsmGameDownloader(MainActivity.this, item)).execute(); + } + }); + + + } + +} diff --git a/app/src/main/java/com/psmreborn/pkgj/NoPayStationParser.java b/app/src/main/java/com/psmreborn/pkgj/NoPayStationParser.java new file mode 100644 index 0000000..5a37f99 --- /dev/null +++ b/app/src/main/java/com/psmreborn/pkgj/NoPayStationParser.java @@ -0,0 +1,118 @@ +package com.psmreborn.pkgj; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.os.AsyncTask; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLConnection; + +public class NoPayStationParser extends AsyncTask { + private boolean wasError = false; + private String errorMsg = ""; + private Context ctx = null; + private ProgressDialog dialog = null; + private File psmGamesFile = null; + private boolean forceRefresh = false; + public NoPayStationParser(Context context, boolean refresh){ + this.ctx = context; + this.psmGamesFile = new File(ctx.getFilesDir(), "PSM_GAMES.tsv"); + this.forceRefresh = true; + } + + + + private void download() throws IOException { + if(psmGamesFile.exists() && !forceRefresh) { + return; + } + + URL url = new URL("http://nopaystation.com/tsv/PSM_GAMES.tsv"); + URLConnection connection = url.openConnection(); + connection.connect(); + + InputStream input = new BufferedInputStream(url.openStream(), 8192); + OutputStream output = new FileOutputStream(this.psmGamesFile); + + StrUtil.copyTo(input, output); + output.close(); + input.close(); + } + + private void parse() throws IOException { + BufferedReader tsvReader = new BufferedReader(new FileReader(this.psmGamesFile)); + tsvReader.readLine(); // skip the first line + + String line = tsvReader.readLine(); + while(line != null) { + + String[] values = line.split("\t"); + + if(values.length >= 4){ + String titleId = values[0]; + String title = values[2]; + String downloadUrl = values[3]; + String zRif = values[4]; + + if(!title.contains("[Unity]") && !zRif.equals("MISSING")){ + ((MainActivity)ctx).addGame(new Game(titleId, title, downloadUrl, zRif)); + } + } + + line = tsvReader.readLine(); + }; + } + + @Override + protected void onPreExecute() { + dialog = new ProgressDialog(ctx); + dialog.setTitle("Refreshing Items..."); + dialog.setMessage("Downloading index ..."); + dialog.setIndeterminate(true); + dialog.setCancelable(false); + dialog.show(); + + } + + @Override + protected Void doInBackground(Void... voids) { + + try { + download(); + parse(); + } + catch(Exception e){ + this.wasError = true; + this.errorMsg = e.toString(); + return null; + } + + return null; + } + + + @Override + protected void onPostExecute(Void result) { + dialog.dismiss(); + ((MainActivity)ctx).updateGames(); + + if(wasError) { + new AlertDialog.Builder((Activity)ctx) + .setTitle("Error Obtaining PSM_GAMES.TSV..") + .setMessage(this.errorMsg) + .setCancelable(false) + .setPositiveButton("OK",null).show(); + } + } + +} diff --git a/app/src/main/java/com/psmreborn/pkgj/PsmGameDownloader.java b/app/src/main/java/com/psmreborn/pkgj/PsmGameDownloader.java new file mode 100644 index 0000000..3f02cce --- /dev/null +++ b/app/src/main/java/com/psmreborn/pkgj/PsmGameDownloader.java @@ -0,0 +1,105 @@ +package com.psmreborn.pkgj; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.os.AsyncTask; +import android.os.Environment; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLConnection; + +public class PsmGameDownloader extends AsyncTask { + private boolean wasError = false; + private String errorMsg = ""; + private Context ctx = null; + private File psmApplicationsFolder = null; + + private ProgressDialog dialog = null; + private Game gameDownloading = null; + + public PsmGameDownloader(Context context, Game downloadGame){ + this.ctx = context; + + this.gameDownloading = downloadGame; + + // get psm data folder ... + this.psmApplicationsFolder = new File(new File(new File(new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data"), "com.playstation.psstore"), "files"), "psm"); + this.psmApplicationsFolder.mkdirs(); + + } + @Override + protected void onPreExecute() { + dialog = new ProgressDialog(ctx); + dialog.setTitle("Downloading: "+gameDownloading.getPkgFilename()); + dialog.setMessage(gameDownloading.getTitle()); + dialog.setIndeterminate(false); + dialog.setMax(100); + dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + dialog.setCancelable(false); + dialog.show(); + + } + + private void download() throws IOException { + URL url = new URL(gameDownloading.getDownloadUrl()); + URLConnection connection = url.openConnection(); + connection.connect(); + + InputStream input = new BufferedInputStream(url.openStream(), 8192); + OutputStream output = new FileOutputStream(new File(this.psmApplicationsFolder, gameDownloading.getPkgFilename())); + + int fileLength = connection.getContentLength(); + + byte[] data = new byte[8192]; + + int count = 0; + long total = 0; + + while ((count = input.read(data)) != -1) { + total += count; + dialog.setProgress((int) ((total * 100) / fileLength)); + output.write(data, 0, count); + } + + // flushing output + output.flush(); + output.close(); + input.close(); + + } + + @Override + protected Void doInBackground(Void... voids) { + try{ + download(); + // TODO: extract pkg, extract zrif + } + catch (Exception e){ + this.wasError = true; + this.errorMsg = e.toString(); + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + dialog.dismiss(); + ((MainActivity)ctx).updateGames(); + + if(wasError) { + new AlertDialog.Builder((Activity)ctx) + .setTitle("Error Downloading: "+ gameDownloading.getTitleId()) + .setMessage(this.errorMsg) + .setCancelable(false) + .setPositiveButton("OK",null).show(); + } + } +} diff --git a/app/src/main/java/com/psmreborn/pkgj/StrUtil.java b/app/src/main/java/com/psmreborn/pkgj/StrUtil.java new file mode 100644 index 0000000..533918f --- /dev/null +++ b/app/src/main/java/com/psmreborn/pkgj/StrUtil.java @@ -0,0 +1,22 @@ +package com.psmreborn.pkgj; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class StrUtil { + public static void copyTo(InputStream inpStream, OutputStream outStream) throws IOException { + byte[] buffer = new byte[8192]; + int totalRead = 0; + + while(true){ + totalRead = inpStream.read(buffer, 0, buffer.length); + if(totalRead == -1) + break; + outStream.write(buffer, 0, totalRead); + } + + outStream.flush(); + } + +} diff --git a/app/src/main/java/pink/yuv/android_id/MainActivity.java b/app/src/main/java/pink/yuv/android_id/MainActivity.java deleted file mode 100644 index 95eeb30..0000000 --- a/app/src/main/java/pink/yuv/android_id/MainActivity.java +++ /dev/null @@ -1,105 +0,0 @@ -package pink.yuv.android_id; - -import android.app.Activity; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Bundle; -import android.provider.Settings.Secure; -import android.telephony.TelephonyManager; -import android.widget.TextView; - - -public class MainActivity extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - TextView androidIdTextView = (TextView)findViewById(R.id.androidId); - String android_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); - System.out.println("android_id: "+android_id); - androidIdTextView.setText("android_id: "+android_id); - - String psmAppId = "app not installed"; - - try{ - ApplicationInfo psmAppInfo = this.getApplicationContext().getPackageManager().getApplicationInfo("com.playstation.psstore", 0); - if(psmAppInfo != null) - psmAppId = String.valueOf(psmAppInfo.uid); - } - catch (PackageManager.NameNotFoundException e) { }; - - TextView psmAppIdTextView = (TextView)findViewById(R.id.psmAppId); - System.out.println("psstore_uid: "+psmAppId); - psmAppIdTextView.setText("psstore_uid: "+psmAppId); - - Context appCtx = getApplicationContext(); - TelephonyManager tm = ((TelephonyManager) appCtx.getSystemService( Context.TELEPHONY_SERVICE)); - String deviceId = tm.getDeviceId(); - if(deviceId == null) - deviceId = "(blank)"; - - String serial = Build.SERIAL; - if(serial == null) - serial = "(blank)"; - - String brand = Build.BRAND; - if(brand == null) - brand = "(blank)"; - - String manu = Build.MANUFACTURER; - if(manu == null) - manu = "(blank)"; - - String model = Build.MODEL; - if(model == null) - model = "(blank)"; - - String product = Build.PRODUCT; - if(product == null) - product = "(blank)"; - - String device = Build.DEVICE; - if(device == null) - device = "(blank)"; - - String type = Build.TYPE; - if(type == null) - type = "(blank)"; - - - TextView devPhoneIdTextview = (TextView)findViewById(R.id.devPhoneId); - System.out.println("getDeviceId(): " + deviceId); - devPhoneIdTextview.setText("getDeviceId(): "+deviceId); - - TextView devSerialTextview = (TextView)findViewById(R.id.devSerial); - System.out.println("SERIAL: " + serial); - devSerialTextview.setText("SERIAL: "+serial); - - TextView devBrandTextview = (TextView)findViewById(R.id.devBrand); - System.out.println("BRAND: " + brand); - devBrandTextview.setText("BRAND: "+brand); - - TextView devManuTextview = (TextView)findViewById(R.id.devManu); - System.out.println("MANUFACTURER: " + manu); - devManuTextview.setText("MANUFACTURER: "+manu); - - TextView devModelTextview = (TextView)findViewById(R.id.devModel); - System.out.println("MODEL: " + model); - devModelTextview.setText("MODEL: "+model); - - TextView devProductTextview = (TextView)findViewById(R.id.devProduct); - System.out.println("PRODUCT: " + product); - devProductTextview.setText("PRODUCT: "+product); - - TextView devDeviceTextview = (TextView)findViewById(R.id.devDevice); - System.out.println("DEVICE: " + device); - devDeviceTextview.setText("DEVICE: "+device); - - TextView devTyoeTextview = (TextView)findViewById(R.id.devType); - System.out.println("TYPE: " + type); - devTyoeTextview.setText("TYPE: "+type); - } -} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 00210e6..5b9f04e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,111 +4,15 @@ android:layout_height="match_parent" android:paddingTop="8dp" android:paddingBottom="8dp" - android:orientation="vertical"> - + + + android:layout_height="match_parent" + android:textColor="@color/white" /> - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/list_item.xml b/app/src/main/res/layout/list_item.xml new file mode 100644 index 0000000..331ff41 --- /dev/null +++ b/app/src/main/res/layout/list_item.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a721642..20f8f9a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,3 @@ - android_id + PKGJ \ No newline at end of file diff --git a/build.gradle b/build.gradle index 1454d1b..abf99bc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.0.1' apply false - id 'com.android.library' version '8.0.1' apply false + id 'com.android.application' version '8.3.2' apply false + id 'com.android.library' version '8.3.2' apply false } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5fc7b23..205b41b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon Aug 14 02:01:41 CEST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index 7a6b0e5..687055b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,5 +12,5 @@ dependencyResolutionManagement { mavenCentral() } } -rootProject.name = "android_id" +rootProject.name = "pkgj" include ':app'