mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 08:30:44 +00:00
Move utility methods out of CheckForNewAppVersion
This commit is contained in:
parent
b8e389c6e8
commit
1602befc51
@ -1,12 +1,9 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.app.IntentService;
|
import android.app.IntentService;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.Signature;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -14,29 +11,17 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
import androidx.core.content.pm.PackageInfoCompat;
|
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
import com.grack.nanojson.JsonParserException;
|
import com.grack.nanojson.JsonParserException;
|
||||||
|
|
||||||
import org.schabi.newpipe.error.ErrorInfo;
|
|
||||||
import org.schabi.newpipe.error.ErrorUtil;
|
|
||||||
import org.schabi.newpipe.error.UserAction;
|
|
||||||
import org.schabi.newpipe.extractor.downloader.Response;
|
import org.schabi.newpipe.extractor.downloader.Response;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||||
|
import org.schabi.newpipe.util.ReleaseVersionUtil;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.CertificateEncodingException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public final class CheckForNewAppVersion extends IntentService {
|
public final class CheckForNewAppVersion extends IntentService {
|
||||||
public CheckForNewAppVersion() {
|
public CheckForNewAppVersion() {
|
||||||
@ -45,122 +30,45 @@ public final class CheckForNewAppVersion extends IntentService {
|
|||||||
|
|
||||||
private static final boolean DEBUG = MainActivity.DEBUG;
|
private static final boolean DEBUG = MainActivity.DEBUG;
|
||||||
private static final String TAG = CheckForNewAppVersion.class.getSimpleName();
|
private static final String TAG = CheckForNewAppVersion.class.getSimpleName();
|
||||||
|
|
||||||
// Public key of the certificate that is used in NewPipe release versions
|
|
||||||
private static final String RELEASE_CERT_PUBLIC_KEY_SHA1
|
|
||||||
= "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15";
|
|
||||||
private static final String NEWPIPE_API_URL = "https://newpipe.net/api/data.json";
|
private static final String NEWPIPE_API_URL = "https://newpipe.net/api/data.json";
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to get the APK's SHA1 key. See https://stackoverflow.com/questions/9293019/#22506133.
|
|
||||||
*
|
|
||||||
* @param application The application
|
|
||||||
* @return String with the APK's SHA1 fingerprint in hexadecimal
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private static String getCertificateSHA1Fingerprint(@NonNull final Application application) {
|
|
||||||
final List<Signature> signatures;
|
|
||||||
try {
|
|
||||||
signatures = PackageInfoCompat.getSignatures(application.getPackageManager(),
|
|
||||||
application.getPackageName());
|
|
||||||
} catch (final PackageManager.NameNotFoundException e) {
|
|
||||||
ErrorUtil.createNotification(application, new ErrorInfo(e,
|
|
||||||
UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not find package info"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (signatures.isEmpty()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
final X509Certificate c;
|
|
||||||
try {
|
|
||||||
final byte[] cert = signatures.get(0).toByteArray();
|
|
||||||
final InputStream input = new ByteArrayInputStream(cert);
|
|
||||||
final CertificateFactory cf = CertificateFactory.getInstance("X509");
|
|
||||||
c = (X509Certificate) cf.generateCertificate(input);
|
|
||||||
} catch (final CertificateException e) {
|
|
||||||
ErrorUtil.createNotification(application, new ErrorInfo(e,
|
|
||||||
UserAction.CHECK_FOR_NEW_APP_VERSION, "Certificate error"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
final MessageDigest md = MessageDigest.getInstance("SHA1");
|
|
||||||
final byte[] publicKey = md.digest(c.getEncoded());
|
|
||||||
return byte2HexFormatted(publicKey);
|
|
||||||
} catch (NoSuchAlgorithmException | CertificateEncodingException e) {
|
|
||||||
ErrorUtil.createNotification(application, new ErrorInfo(e,
|
|
||||||
UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not retrieve SHA1 key"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String byte2HexFormatted(final byte[] arr) {
|
|
||||||
final StringBuilder str = new StringBuilder(arr.length * 2);
|
|
||||||
|
|
||||||
for (int i = 0; i < arr.length; i++) {
|
|
||||||
String h = Integer.toHexString(arr[i]);
|
|
||||||
final int l = h.length();
|
|
||||||
if (l == 1) {
|
|
||||||
h = "0" + h;
|
|
||||||
}
|
|
||||||
if (l > 2) {
|
|
||||||
h = h.substring(l - 2, l);
|
|
||||||
}
|
|
||||||
str.append(h.toUpperCase());
|
|
||||||
if (i < (arr.length - 1)) {
|
|
||||||
str.append(':');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to compare the current and latest available app version.
|
* Method to compare the current and latest available app version.
|
||||||
* If a newer version is available, we show the update notification.
|
* If a newer version is available, we show the update notification.
|
||||||
*
|
*
|
||||||
* @param application The application
|
|
||||||
* @param versionName Name of new version
|
* @param versionName Name of new version
|
||||||
* @param apkLocationUrl Url with the new apk
|
* @param apkLocationUrl Url with the new apk
|
||||||
* @param versionCode Code of new version
|
* @param versionCode Code of new version
|
||||||
*/
|
*/
|
||||||
private static void compareAppVersionAndShowNotification(@NonNull final Application application,
|
private static void compareAppVersionAndShowNotification(final String versionName,
|
||||||
final String versionName,
|
|
||||||
final String apkLocationUrl,
|
final String apkLocationUrl,
|
||||||
final int versionCode) {
|
final int versionCode) {
|
||||||
if (BuildConfig.VERSION_CODE >= versionCode) {
|
if (BuildConfig.VERSION_CODE >= versionCode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final App app = App.getApp();
|
||||||
// A pending intent to open the apk location url in the browser.
|
// A pending intent to open the apk location url in the browser.
|
||||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl));
|
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl));
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
final PendingIntent pendingIntent
|
final PendingIntent pendingIntent = PendingIntent.getActivity(app, 0, intent, 0);
|
||||||
= PendingIntent.getActivity(application, 0, intent, 0);
|
|
||||||
|
|
||||||
final String channelId = application
|
final String channelId = app.getString(R.string.app_update_notification_channel_id);
|
||||||
.getString(R.string.app_update_notification_channel_id);
|
|
||||||
final NotificationCompat.Builder notificationBuilder
|
final NotificationCompat.Builder notificationBuilder
|
||||||
= new NotificationCompat.Builder(application, channelId)
|
= new NotificationCompat.Builder(app, channelId)
|
||||||
.setSmallIcon(R.drawable.ic_newpipe_update)
|
.setSmallIcon(R.drawable.ic_newpipe_update)
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
.setContentIntent(pendingIntent)
|
.setContentIntent(pendingIntent)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setContentTitle(application
|
.setContentTitle(app.getString(R.string.app_update_notification_content_title))
|
||||||
.getString(R.string.app_update_notification_content_title))
|
.setContentText(app.getString(R.string.app_update_notification_content_text)
|
||||||
.setContentText(application
|
|
||||||
.getString(R.string.app_update_notification_content_text)
|
|
||||||
+ " " + versionName);
|
+ " " + versionName);
|
||||||
|
|
||||||
final NotificationManagerCompat notificationManager
|
final NotificationManagerCompat notificationManager
|
||||||
= NotificationManagerCompat.from(application);
|
= NotificationManagerCompat.from(app);
|
||||||
notificationManager.notify(2000, notificationBuilder.build());
|
notificationManager.notify(2000, notificationBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isReleaseApk(@NonNull final App app) {
|
|
||||||
return getCertificateSHA1Fingerprint(app).equals(RELEASE_CERT_PUBLIC_KEY_SHA1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkNewVersion() throws IOException, ReCaptchaException {
|
private void checkNewVersion() throws IOException, ReCaptchaException {
|
||||||
final App app = App.getApp();
|
final App app = App.getApp();
|
||||||
|
|
||||||
@ -168,7 +76,7 @@ public final class CheckForNewAppVersion extends IntentService {
|
|||||||
final NewVersionManager manager = new NewVersionManager();
|
final NewVersionManager manager = new NewVersionManager();
|
||||||
|
|
||||||
// Check if the current apk is a github one or not.
|
// Check if the current apk is a github one or not.
|
||||||
if (!isReleaseApk(app)) {
|
if (!ReleaseVersionUtil.isReleaseApk()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,13 +89,13 @@ public final class CheckForNewAppVersion extends IntentService {
|
|||||||
|
|
||||||
// Make a network request to get latest NewPipe data.
|
// Make a network request to get latest NewPipe data.
|
||||||
final Response response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL);
|
final Response response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL);
|
||||||
handleResponse(response, manager, prefs, app);
|
handleResponse(response, manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleResponse(@NonNull final Response response,
|
private void handleResponse(@NonNull final Response response,
|
||||||
@NonNull final NewVersionManager manager,
|
@NonNull final NewVersionManager manager) {
|
||||||
@NonNull final SharedPreferences prefs,
|
final App app = App.getApp();
|
||||||
@NonNull final App app) {
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app);
|
||||||
try {
|
try {
|
||||||
// Store a timestamp which needs to be exceeded,
|
// Store a timestamp which needs to be exceeded,
|
||||||
// before a new request to the API is made.
|
// before a new request to the API is made.
|
||||||
@ -209,14 +117,11 @@ public final class CheckForNewAppVersion extends IntentService {
|
|||||||
.from(response.responseBody()).getObject("flavors")
|
.from(response.responseBody()).getObject("flavors")
|
||||||
.getObject("github").getObject("stable");
|
.getObject("github").getObject("stable");
|
||||||
|
|
||||||
final String versionName = githubStableObject
|
final String versionName = githubStableObject.getString("version");
|
||||||
.getString("version");
|
final int versionCode = githubStableObject.getInt("version_code");
|
||||||
final int versionCode = githubStableObject
|
final String apkLocationUrl = githubStableObject.getString("apk");
|
||||||
.getInt("version_code");
|
|
||||||
final String apkLocationUrl = githubStableObject
|
|
||||||
.getString("apk");
|
|
||||||
|
|
||||||
compareAppVersionAndShowNotification(app, versionName,
|
compareAppVersionAndShowNotification(versionName,
|
||||||
apkLocationUrl, versionCode);
|
apkLocationUrl, versionCode);
|
||||||
} catch (final JsonParserException e) {
|
} catch (final JsonParserException e) {
|
||||||
// Most likely something is wrong in data received from NEWPIPE_API_URL.
|
// Most likely something is wrong in data received from NEWPIPE_API_URL.
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService;
|
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
@ -177,7 +176,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
// Start the service which is checking all conditions
|
// Start the service which is checking all conditions
|
||||||
// and eventually searching for a new version.
|
// and eventually searching for a new version.
|
||||||
// The service searching for a new NewPipe version must not be started in background.
|
// The service searching for a new NewPipe version must not be started in background.
|
||||||
startNewVersionCheckService();
|
CheckForNewAppVersion.startNewVersionCheckService();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,10 +7,9 @@ import android.view.MenuItem;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.schabi.newpipe.App;
|
|
||||||
import org.schabi.newpipe.CheckForNewAppVersion;
|
|
||||||
import org.schabi.newpipe.MainActivity;
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.util.ReleaseVersionUtil;
|
||||||
|
|
||||||
public class MainSettingsFragment extends BasePreferenceFragment {
|
public class MainSettingsFragment extends BasePreferenceFragment {
|
||||||
public static final boolean DEBUG = MainActivity.DEBUG;
|
public static final boolean DEBUG = MainActivity.DEBUG;
|
||||||
@ -24,7 +23,7 @@ public class MainSettingsFragment extends BasePreferenceFragment {
|
|||||||
setHasOptionsMenu(true); // Otherwise onCreateOptionsMenu is not called
|
setHasOptionsMenu(true); // Otherwise onCreateOptionsMenu is not called
|
||||||
|
|
||||||
// Check if the app is updatable
|
// Check if the app is updatable
|
||||||
if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) {
|
if (!ReleaseVersionUtil.isReleaseApk()) {
|
||||||
getPreferenceScreen().removePreference(
|
getPreferenceScreen().removePreference(
|
||||||
findPreference(getString(R.string.update_pref_screen_key)));
|
findPreference(getString(R.string.update_pref_screen_key)));
|
||||||
|
|
||||||
|
@ -23,8 +23,6 @@ import androidx.preference.PreferenceFragmentCompat;
|
|||||||
|
|
||||||
import com.jakewharton.rxbinding4.widget.RxTextView;
|
import com.jakewharton.rxbinding4.widget.RxTextView;
|
||||||
|
|
||||||
import org.schabi.newpipe.App;
|
|
||||||
import org.schabi.newpipe.CheckForNewAppVersion;
|
|
||||||
import org.schabi.newpipe.MainActivity;
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.databinding.SettingsLayoutBinding;
|
import org.schabi.newpipe.databinding.SettingsLayoutBinding;
|
||||||
@ -37,6 +35,7 @@ import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchResultListen
|
|||||||
import org.schabi.newpipe.settings.preferencesearch.PreferenceSearcher;
|
import org.schabi.newpipe.settings.preferencesearch.PreferenceSearcher;
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.KeyboardUtil;
|
import org.schabi.newpipe.util.KeyboardUtil;
|
||||||
|
import org.schabi.newpipe.util.ReleaseVersionUtil;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
import org.schabi.newpipe.views.FocusOverlayView;
|
import org.schabi.newpipe.views.FocusOverlayView;
|
||||||
|
|
||||||
@ -267,7 +266,7 @@ public class SettingsActivity extends AppCompatActivity implements
|
|||||||
*/
|
*/
|
||||||
private void ensureSearchRepresentsApplicationState() {
|
private void ensureSearchRepresentsApplicationState() {
|
||||||
// Check if the update settings are available
|
// Check if the update settings are available
|
||||||
if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) {
|
if (!ReleaseVersionUtil.isReleaseApk()) {
|
||||||
SettingsResourceRegistry.getInstance()
|
SettingsResourceRegistry.getInstance()
|
||||||
.getEntryByPreferencesResId(R.xml.update_settings)
|
.getEntryByPreferencesResId(R.xml.update_settings)
|
||||||
.setSearchable(false);
|
.setSearchable(false);
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
package org.schabi.newpipe.util;
|
||||||
|
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.Signature;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.pm.PackageInfoCompat;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.App;
|
||||||
|
import org.schabi.newpipe.error.ErrorInfo;
|
||||||
|
import org.schabi.newpipe.error.ErrorUtil;
|
||||||
|
import org.schabi.newpipe.error.UserAction;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ReleaseVersionUtil {
|
||||||
|
// Public key of the certificate that is used in NewPipe release versions
|
||||||
|
private static final String RELEASE_CERT_PUBLIC_KEY_SHA1
|
||||||
|
= "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15";
|
||||||
|
|
||||||
|
public static boolean isReleaseApk() {
|
||||||
|
return getCertificateSHA1Fingerprint().equals(RELEASE_CERT_PUBLIC_KEY_SHA1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to get the APK's SHA1 key. See https://stackoverflow.com/questions/9293019/#22506133.
|
||||||
|
*
|
||||||
|
* @return String with the APK's SHA1 fingerprint in hexadecimal
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private static String getCertificateSHA1Fingerprint() {
|
||||||
|
final App app = App.getApp();
|
||||||
|
final List<Signature> signatures;
|
||||||
|
try {
|
||||||
|
signatures = PackageInfoCompat.getSignatures(app.getPackageManager(),
|
||||||
|
app.getPackageName());
|
||||||
|
} catch (final PackageManager.NameNotFoundException e) {
|
||||||
|
ErrorUtil.createNotification(app, new ErrorInfo(e,
|
||||||
|
UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not find package info"));
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (signatures.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
final X509Certificate c;
|
||||||
|
try {
|
||||||
|
final byte[] cert = signatures.get(0).toByteArray();
|
||||||
|
final InputStream input = new ByteArrayInputStream(cert);
|
||||||
|
final CertificateFactory cf = CertificateFactory.getInstance("X509");
|
||||||
|
c = (X509Certificate) cf.generateCertificate(input);
|
||||||
|
} catch (final CertificateException e) {
|
||||||
|
ErrorUtil.createNotification(app, new ErrorInfo(e,
|
||||||
|
UserAction.CHECK_FOR_NEW_APP_VERSION, "Certificate error"));
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final MessageDigest md = MessageDigest.getInstance("SHA1");
|
||||||
|
final byte[] publicKey = md.digest(c.getEncoded());
|
||||||
|
return byte2HexFormatted(publicKey);
|
||||||
|
} catch (NoSuchAlgorithmException | CertificateEncodingException e) {
|
||||||
|
ErrorUtil.createNotification(app, new ErrorInfo(e,
|
||||||
|
UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not retrieve SHA1 key"));
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String byte2HexFormatted(final byte[] arr) {
|
||||||
|
final StringBuilder str = new StringBuilder(arr.length * 2);
|
||||||
|
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
String h = Integer.toHexString(arr[i]);
|
||||||
|
final int l = h.length();
|
||||||
|
if (l == 1) {
|
||||||
|
h = "0" + h;
|
||||||
|
}
|
||||||
|
if (l > 2) {
|
||||||
|
h = h.substring(l - 2, l);
|
||||||
|
}
|
||||||
|
str.append(h.toUpperCase());
|
||||||
|
if (i < (arr.length - 1)) {
|
||||||
|
str.append(':');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user