|
@ -1,104 +1,46 @@ |
|
|
package awais.instagrabber.utils; |
|
|
package awais.instagrabber.utils; |
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint; |
|
|
|
|
|
import android.content.ActivityNotFoundException; |
|
|
|
|
|
import android.content.Context; |
|
|
import android.content.Context; |
|
|
import android.content.DialogInterface; |
|
|
|
|
|
import android.content.Intent; |
|
|
|
|
|
import android.content.pm.PackageInfo; |
|
|
|
|
|
import android.content.pm.PackageManager; |
|
|
|
|
|
import android.content.pm.Signature; |
|
|
|
|
|
import android.content.res.Resources; |
|
|
|
|
|
import android.net.Uri; |
|
|
|
|
|
import android.os.AsyncTask; |
|
|
|
|
|
import android.util.Log; |
|
|
|
|
|
import android.widget.Toast; |
|
|
import android.widget.Toast; |
|
|
|
|
|
|
|
|
import androidx.annotation.NonNull; |
|
|
import androidx.annotation.NonNull; |
|
|
import androidx.appcompat.app.AlertDialog; |
|
|
|
|
|
import androidx.appcompat.app.AppCompatActivity; |
|
|
import androidx.appcompat.app.AppCompatActivity; |
|
|
|
|
|
|
|
|
import java.security.MessageDigest; |
|
|
|
|
|
import java.security.NoSuchAlgorithmException; |
|
|
|
|
|
import java.util.concurrent.ThreadLocalRandom; |
|
|
import java.util.concurrent.ThreadLocalRandom; |
|
|
|
|
|
|
|
|
import javax.security.cert.CertificateException; |
|
|
|
|
|
import javax.security.cert.X509Certificate; |
|
|
|
|
|
|
|
|
|
|
|
import awais.instagrabber.BuildConfig; |
|
|
import awais.instagrabber.BuildConfig; |
|
|
import awais.instagrabber.R; |
|
|
import awais.instagrabber.R; |
|
|
import awais.instagrabber.databinding.DialogUpdateBinding; |
|
|
|
|
|
|
|
|
|
|
|
import static awais.instagrabber.utils.Utils.settingsHelper; |
|
|
import static awais.instagrabber.utils.Utils.settingsHelper; |
|
|
|
|
|
|
|
|
public final class FlavorTown { |
|
|
public final class FlavorTown { |
|
|
private static final String TAG = "FlavorTown"; |
|
|
private static final String TAG = "FlavorTown"; |
|
|
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); |
|
|
private static final UpdateChecker UPDATE_CHECKER = UpdateChecker.getInstance(); |
|
|
private static AlertDialog dialog; |
|
|
private static boolean checking = false; |
|
|
|
|
|
|
|
|
public static void updateCheck(@NonNull final AppCompatActivity context) { |
|
|
public static void updateCheck(@NonNull final AppCompatActivity context) { |
|
|
updateCheck(context, false); |
|
|
updateCheck(context, false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@SuppressLint("PackageManagerGetSignatures") |
|
|
public static void updateCheck(@NonNull final AppCompatActivity context, |
|
|
public static void updateCheck(@NonNull final AppCompatActivity context, final boolean force) { |
|
|
final boolean force) { |
|
|
boolean isInstalledFromFdroid = false; |
|
|
if (checking) return; |
|
|
final PackageInfo packageInfo; |
|
|
checking = true; |
|
|
try { |
|
|
AppExecutors.getInstance().networkIO().execute(() -> { |
|
|
packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); |
|
|
final String version = UPDATE_CHECKER.getLatestVersion(); |
|
|
for (Signature signature : packageInfo.signatures) { |
|
|
if (version == null) return; |
|
|
final X509Certificate cert = X509Certificate.getInstance(signature.toByteArray()); |
|
|
|
|
|
final String fingerprint = bytesToHex(MessageDigest.getInstance("SHA-1").digest(cert.getEncoded())); |
|
|
|
|
|
isInstalledFromFdroid = fingerprint.equals(Constants.FDROID_SHA1_FINGERPRINT); |
|
|
|
|
|
// Log.d(TAG, "fingerprint:" + fingerprint); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException | CertificateException e) { |
|
|
|
|
|
Log.e(TAG, "Error", e); |
|
|
|
|
|
} |
|
|
|
|
|
if (isInstalledFromFdroid) return; |
|
|
|
|
|
final DialogUpdateBinding binding = DialogUpdateBinding.inflate(context.getLayoutInflater(), null, false); |
|
|
|
|
|
binding.skipUpdate.setOnCheckedChangeListener((buttonView, isChecked) -> { |
|
|
|
|
|
if (dialog == null) return; |
|
|
|
|
|
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(!isChecked); |
|
|
|
|
|
}); |
|
|
|
|
|
Resources res = context.getResources(); |
|
|
|
|
|
new UpdateChecker(version -> { |
|
|
|
|
|
if (force && version.equals(BuildConfig.VERSION_NAME)) { |
|
|
if (force && version.equals(BuildConfig.VERSION_NAME)) { |
|
|
Toast.makeText(context, "You're already on the latest version", Toast.LENGTH_SHORT).show(); |
|
|
Toast.makeText(context, "You're already on the latest version", Toast.LENGTH_SHORT).show(); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
final String skippedVersion = settingsHelper.getString(Constants.SKIPPED_VERSION); |
|
|
final boolean shouldShowDialog = UpdateCheckCommon.shouldShowUpdateDialog(force, version); |
|
|
final boolean shouldShowDialog = force || (!version.equals(BuildConfig.VERSION_NAME) && !BuildConfig.DEBUG && !skippedVersion |
|
|
|
|
|
.equals(version)); |
|
|
|
|
|
if (!shouldShowDialog) return; |
|
|
if (!shouldShowDialog) return; |
|
|
dialog = new AlertDialog.Builder(context) |
|
|
UpdateCheckCommon.showUpdateDialog(context, version, (dialog, which) -> { |
|
|
.setTitle(res.getString(R.string.update_available, version)) |
|
|
UPDATE_CHECKER.onDownload(context); |
|
|
.setView(binding.getRoot()) |
|
|
dialog.dismiss(); |
|
|
.setNeutralButton(R.string.cancel, (dialog, which) -> { |
|
|
}); |
|
|
if (binding.skipUpdate.isChecked()) { |
|
|
}); |
|
|
settingsHelper.putString(Constants.SKIPPED_VERSION, version); |
|
|
|
|
|
} |
|
|
|
|
|
dialog.dismiss(); |
|
|
|
|
|
}) |
|
|
|
|
|
.setPositiveButton(R.string.action_github, (dialog1, which) -> { |
|
|
|
|
|
try { |
|
|
|
|
|
context.startActivity(new Intent(Intent.ACTION_VIEW).setData( |
|
|
|
|
|
Uri.parse("https://github.com/austinhuang0131/instagrabber/releases/latest"))); |
|
|
|
|
|
} catch (final ActivityNotFoundException e) { |
|
|
|
|
|
// do nothing |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
// if we don't show dialog for fdroid users, is the below required? |
|
|
|
|
|
.setNegativeButton(R.string.action_fdroid, (dialog, which) -> { |
|
|
|
|
|
try { |
|
|
|
|
|
context.startActivity(new Intent(Intent.ACTION_VIEW).setData( |
|
|
|
|
|
Uri.parse("https://f-droid.org/packages/me.austinhuang.instagrabber/"))); |
|
|
|
|
|
} catch (final ActivityNotFoundException e) { |
|
|
|
|
|
// do nothing |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
.show(); |
|
|
|
|
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public static void changelogCheck(@NonNull final Context context) { |
|
|
public static void changelogCheck(@NonNull final Context context) { |
|
@ -121,14 +63,4 @@ public final class FlavorTown { |
|
|
settingsHelper.putInteger(Constants.PREV_INSTALL_VERSION, BuildConfig.VERSION_CODE); |
|
|
settingsHelper.putInteger(Constants.PREV_INSTALL_VERSION, BuildConfig.VERSION_CODE); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public static String bytesToHex(byte[] bytes) { |
|
|
|
|
|
char[] hexChars = new char[bytes.length * 2]; |
|
|
|
|
|
for (int j = 0; j < bytes.length; j++) { |
|
|
|
|
|
int v = bytes[j] & 0xFF; |
|
|
|
|
|
hexChars[j * 2] = HEX_ARRAY[v >>> 4]; |
|
|
|
|
|
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; |
|
|
|
|
|
} |
|
|
|
|
|
return new String(hexChars); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
xxxxxxxxxx