save temporary
This commit is contained in:
parent
2fd2850fbd
commit
38957d9407
@ -5,6 +5,7 @@
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:name=".MainApplication"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
tools:replace="android:icon"
|
||||
@ -46,7 +47,7 @@
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:theme="@style/CebgMainActivity"
|
||||
android:theme="@style/CEBGThemeSelector"
|
||||
android:launchMode="singleTask"
|
||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density"
|
||||
android:resizeableActivity="false"
|
||||
@ -105,7 +106,10 @@
|
||||
android:theme="@style/WebViewTheme" />
|
||||
<activity
|
||||
android:name=".activity.BiometricActivity"
|
||||
android:theme="@style/AppCompatTranslucent" />
|
||||
android:theme="@style/DayNightActivity"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|layoutDirection"
|
||||
/>
|
||||
<activity
|
||||
android:name=".activity.CustomCaptureActivity"
|
||||
android:theme="@style/CaptureTheme" />
|
||||
@ -203,6 +207,9 @@
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen.multitouch.distinct"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
@ -222,7 +229,6 @@
|
||||
android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
@ -230,7 +236,10 @@
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<queries>
|
||||
<package android:name="com.zhiliaoapp.musically" />
|
||||
<package android:name="com.ss.android.ugc.trill" />
|
||||
|
@ -4,6 +4,8 @@ import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRON
|
||||
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
|
||||
|
||||
import android.Manifest;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@ -35,7 +37,6 @@ import com.bytedance.sdk.open.tiktok.base.VideoObject;
|
||||
import com.bytedance.sdk.open.tiktok.share.Share;
|
||||
import com.cege.games.release.activity.BiometricActivity;
|
||||
import com.cege.games.release.activity.CustomCaptureActivity;
|
||||
import com.cege.games.release.activity.UnityPlayerActivity;
|
||||
import com.cege.games.release.activity.WebPageActivity;
|
||||
import com.cege.games.release.apple.AppleLoginActivity;
|
||||
import com.cege.games.release.dialog.QRCodeActivity;
|
||||
@ -67,10 +68,12 @@ import com.jc.jcfw.security.BiometricHelper;
|
||||
import com.jc.jcfw.security.CryptographyManager;
|
||||
import com.jc.jcfw.security.CryptographyManagerImpl;
|
||||
import com.jc.jcfw.security.EncryptedData;
|
||||
import com.jc.jcfw.util.Installation;
|
||||
import com.jc.jcfw.util.JsonUtils;
|
||||
import com.king.zxing.CameraScan;
|
||||
import com.king.zxing.util.CodeUtils;
|
||||
import com.king.zxing.util.LogUtils;
|
||||
import com.unity3d.player.UnityPlayerActivity;
|
||||
|
||||
import net.openid.appauth.AppAuthConfiguration;
|
||||
import net.openid.appauth.AuthState;
|
||||
@ -147,6 +150,7 @@ public class MainActivity extends UnityPlayerActivity
|
||||
private CountDownLatch mAuthIntentLatch = new CountDownLatch(1);
|
||||
|
||||
private TikTokOpenApi tiktokOpenApi;
|
||||
|
||||
public String getFunId() {
|
||||
return funId;
|
||||
}
|
||||
@ -160,8 +164,8 @@ public class MainActivity extends UnityPlayerActivity
|
||||
|
||||
private FirebaseAnalytics mFirebaseAnalytics;
|
||||
private AppEventsLogger fbLogger;
|
||||
private BiometricPrompt.PromptInfo promptInfo;
|
||||
private CryptographyManager cryptographyManager;
|
||||
|
||||
private AccountManager accountManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -204,8 +208,10 @@ public class MainActivity extends UnityPlayerActivity
|
||||
|
||||
PayClient payClient = PayClient.getInstance();
|
||||
payClient.init(this);
|
||||
promptInfo = BiometricHelper.createPromptInfo(this);
|
||||
cryptographyManager = new CryptographyManagerImpl();
|
||||
accountManager = AccountManager.get(this);
|
||||
String id = Installation.id(this);
|
||||
Log.i(TAG, "custom id:: " + id);
|
||||
Log.i(TAG, "build info::" + Installation.getBuildInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -285,7 +291,6 @@ public class MainActivity extends UnityPlayerActivity
|
||||
|
||||
// begin for unity
|
||||
|
||||
|
||||
protected void onLoadNativeLibraries() {
|
||||
try {
|
||||
ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
|
||||
@ -855,15 +860,12 @@ public class MainActivity extends UnityPlayerActivity
|
||||
public void showPage(String fid, final String url) {
|
||||
runOnUiThread(() -> {
|
||||
Log.i(TAG, "show page: " + url);
|
||||
// Intent intent = new Intent(this, WebPageActivity.class);
|
||||
// intent.putExtra("url", url);
|
||||
// Intent intent = new Intent(this, BiometricActivity.class);
|
||||
// intent.putExtra("action", "encrypt");
|
||||
// intent.putExtra("key", "1111");
|
||||
// startActivity(intent);
|
||||
Intent intent = new Intent(this, WebPageActivity.class);
|
||||
intent.putExtra("url", url);
|
||||
startActivity(intent);
|
||||
// picker video file and share to tiktok
|
||||
// openFileSelector();
|
||||
authenticateToEncrypt("1111");
|
||||
// authenticateToEncrypt("1111");
|
||||
});
|
||||
}
|
||||
|
||||
@ -910,32 +912,43 @@ public class MainActivity extends UnityPlayerActivity
|
||||
startActivityForResult(intent, FILE_SELECTOR_CODE);
|
||||
}
|
||||
|
||||
public void authenticateToEncrypt(String text) {
|
||||
if (BiometricManager.from(this).canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL) == BiometricManager
|
||||
.BIOMETRIC_SUCCESS) {
|
||||
Cipher cipher = cryptographyManager.getInitializedCipherForEncryption("cebg_wallet_key");
|
||||
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(MainActivity.this, _cipher -> {
|
||||
EncryptedData encryptedData = cryptographyManager.encryptData(text, _cipher);
|
||||
String encryptedString = Base64.encodeToString(encryptedData.getCiphertext(), Base64.DEFAULT);
|
||||
String ivString = Base64.encodeToString(encryptedData.getInitializationVector(), Base64.DEFAULT);
|
||||
Log.i(TAG, "encrypted msg: " + encryptedString);
|
||||
Log.i(TAG, "encrypted iv: " + ivString);
|
||||
});
|
||||
biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(cipher));
|
||||
}
|
||||
}
|
||||
public void authenticateToDecrypt(String text, String iv) {
|
||||
if (BiometricManager.from(this).canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL) == BiometricManager
|
||||
.BIOMETRIC_SUCCESS) {
|
||||
byte[] ivData = Base64.decode(iv, Base64.DEFAULT);
|
||||
byte[] textData = Base64.decode(text, Base64.DEFAULT);
|
||||
Cipher cipher = cryptographyManager.getInitializedCipherForDecryption("cebg_wallet_key", ivData);
|
||||
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(MainActivity.this, _cipher -> {
|
||||
String decryptedMsg = cryptographyManager.decryptData(textData, _cipher);
|
||||
Log.i(TAG, "decrypted msg: " + decryptedMsg);
|
||||
});
|
||||
biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(cipher));
|
||||
}
|
||||
public void passStorageState(String funid, String account) {
|
||||
Log.i(TAG, "passStorageState with: " + account);
|
||||
}
|
||||
|
||||
public void storagePass(String funid, String account, String password) {
|
||||
Log.i(TAG, "storagePass with: " + account + " | " + password);
|
||||
|
||||
// save to account manage
|
||||
final Account act = new Account(account, "main");
|
||||
accountManager.addAccountExplicitly(act, password, null);
|
||||
// runOnUiThread(() -> {
|
||||
// Intent intent = new Intent(this, BiometricActivity.class);
|
||||
// intent.putExtra("action", "encrypt");
|
||||
// intent.putExtra("funid", funId);
|
||||
// intent.putExtra("account", account);
|
||||
// intent.putExtra("password", password);
|
||||
// startActivity(intent);
|
||||
// });
|
||||
}
|
||||
|
||||
public void authGetStoragePass(String funid, String account) {
|
||||
Log.i(TAG, "authGetStoragePass with: " + account);
|
||||
Account[] accounts = accountManager.getAccounts();
|
||||
for (Account act : accounts) {
|
||||
Log.i(TAG, "authGetStoragePass account: " + act.name + " | " + act.type + " | " + accountManager.getPassword(act));
|
||||
}
|
||||
// runOnUiThread(() -> {
|
||||
// Intent intent = new Intent(this, BiometricActivity.class);
|
||||
// intent.putExtra("action", "decrypt");
|
||||
// intent.putExtra("funid", funId);
|
||||
// intent.putExtra("account", account);
|
||||
// startActivity(intent);
|
||||
// });
|
||||
}
|
||||
|
||||
public void getClientId(String funid) {
|
||||
Log.i(TAG, "getClientId ");
|
||||
|
||||
}
|
||||
}
|
@ -2,9 +2,11 @@ package com.cege.games.release.activity;
|
||||
|
||||
import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG;
|
||||
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
|
||||
import static androidx.biometric.BiometricPrompt.ERROR_USER_CANCELED;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.security.keystore.KeyInfo;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
@ -34,26 +36,36 @@ public class BiometricActivity extends AppCompatActivity {
|
||||
cryptographyManager = new CryptographyManagerImpl();
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getStringExtra("action");
|
||||
String key = intent.getStringExtra("key");
|
||||
String funId = intent.getStringExtra("funid");
|
||||
String account = intent.getStringExtra("account");
|
||||
// check if action is exists
|
||||
// if ("encrypt".equals(action)) {
|
||||
// authenticateToEncrypt(key);
|
||||
// } else if ("decrypt".equals(action)) {
|
||||
// String iv = intent.getStringExtra("iv");
|
||||
// authenticateToDecrypt(key, iv);
|
||||
// }
|
||||
if ("encrypt".equals(action)) {
|
||||
String password = intent.getStringExtra("password");
|
||||
authenticateToEncrypt(funId, password);
|
||||
} else if ("decrypt".equals(action)) {
|
||||
String iv = intent.getStringExtra("iv");
|
||||
authenticateToDecrypt(account, iv);
|
||||
}
|
||||
}
|
||||
|
||||
public void authenticateToEncrypt(String text) {
|
||||
public void authenticateToEncrypt(String funId, String text) {
|
||||
if (BiometricManager.from(this)
|
||||
.canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL) == BiometricManager.BIOMETRIC_SUCCESS) {
|
||||
Cipher cipher = cryptographyManager.getInitializedCipherForEncryption("cebg_wallet_key");
|
||||
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(this, _cipher -> {
|
||||
EncryptedData encryptedData = cryptographyManager.encryptData(text, _cipher);
|
||||
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(this, _result -> {
|
||||
if (_result.isError()) {
|
||||
if (_result.getErrcode() == ERROR_USER_CANCELED) {
|
||||
// close current activity
|
||||
finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
EncryptedData encryptedData = cryptographyManager.encryptData(text, _result.getCipher());
|
||||
String encryptedString = Base64.encodeToString(encryptedData.getCiphertext(), Base64.DEFAULT);
|
||||
String ivString = Base64.encodeToString(encryptedData.getInitializationVector(), Base64.DEFAULT);
|
||||
Log.i(TAG, "encrypted msg: " + encryptedString);
|
||||
Log.i(TAG, "encrypted iv: " + ivString);
|
||||
finish();
|
||||
});
|
||||
biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(cipher));
|
||||
}
|
||||
@ -65,9 +77,17 @@ public class BiometricActivity extends AppCompatActivity {
|
||||
byte[] ivData = Base64.decode(iv, Base64.DEFAULT);
|
||||
byte[] textData = Base64.decode(text, Base64.DEFAULT);
|
||||
Cipher cipher = cryptographyManager.getInitializedCipherForDecryption("cebg_wallet_key", ivData);
|
||||
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(this, _cipher -> {
|
||||
String decryptedMsg = cryptographyManager.decryptData(textData, _cipher);
|
||||
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(this, _result -> {
|
||||
if (_result.isError()) {
|
||||
if (_result.getErrcode() == ERROR_USER_CANCELED) {
|
||||
// close current activity
|
||||
finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
String decryptedMsg = cryptographyManager.decryptData(textData, _result.getCipher());
|
||||
Log.i(TAG, "decrypted msg: " + decryptedMsg);
|
||||
finish();
|
||||
});
|
||||
biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(cipher));
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ public class JcSDK {
|
||||
|
||||
/**
|
||||
* @Deprecated
|
||||
* 不使用该方法, 直接由unity调用cpp方法
|
||||
* 不使用该方法, 直接由unity调用cpp方法
|
||||
* @param password
|
||||
*/
|
||||
public static void initWallet(String password) {
|
||||
@ -58,8 +58,8 @@ public class JcSDK {
|
||||
* check if metamask installed and jump to metamask
|
||||
*
|
||||
* @param url
|
||||
* sample:
|
||||
* "https://metamask.app.link/wc?uri="+ExampleApplication.config.toWCUri();
|
||||
* sample:
|
||||
* "https://metamask.app.link/wc?uri="+ExampleApplication.config.toWCUri();
|
||||
*/
|
||||
|
||||
public static void toWallet(String url) {
|
||||
@ -137,6 +137,7 @@ public class JcSDK {
|
||||
}
|
||||
payClient.queryProductList(funid, skuList);
|
||||
}
|
||||
|
||||
public static void buyProduct(String funid, String productId, String orderId) {
|
||||
Log.i(TAG, "buyProduct with: " + productId);
|
||||
if (payClient == null) {
|
||||
@ -153,6 +154,26 @@ public class JcSDK {
|
||||
payClient.queryPurchase(funid);
|
||||
}
|
||||
|
||||
public static void passStorageState(String funid, String account) {
|
||||
Log.i(TAG, "passStorageState with: " + account);
|
||||
MainActivity.app.passStorageState(funid, account);
|
||||
}
|
||||
|
||||
public static void storagePass(String funid, String account, String password) {
|
||||
Log.i(TAG, "storagePass with: " + account);
|
||||
MainActivity.app.storagePass(funid, account, password);
|
||||
}
|
||||
|
||||
public static void authGetStoragePass(String funid, String account) {
|
||||
Log.i(TAG, "authGetStoragePass with: " + account);
|
||||
MainActivity.app.authGetStoragePass(funid, account);
|
||||
}
|
||||
|
||||
public static void getClientId(String funid) {
|
||||
Log.i(TAG, "getClientId ");
|
||||
MainActivity.app.getClientId(funid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调至js
|
||||
*/
|
||||
|
@ -19,6 +19,9 @@ import java.util.function.Consumer;
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class BiometricHelper {
|
||||
|
||||
public static final int ERROR_BIOMETRIC_FAIL = 100;
|
||||
public static final int ERROR_BIOMETRIC_NO_CIPHER = 101;
|
||||
private static final String TAG = BiometricHelper.class.getSimpleName();
|
||||
public static BiometricPrompt.PromptInfo createPromptInfo(Context context) {
|
||||
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
|
||||
@ -34,28 +37,26 @@ public class BiometricHelper {
|
||||
return promptInfo;
|
||||
}
|
||||
|
||||
public static BiometricPrompt createBiometricPrompt(FragmentActivity activity, Consumer<Cipher> func) {
|
||||
public static BiometricPrompt createBiometricPrompt(FragmentActivity activity, Consumer<BiometricResult> func) {
|
||||
Executor executor = ContextCompat.getMainExecutor(activity.getApplicationContext());
|
||||
return new BiometricPrompt(activity, executor, new BiometricPrompt.AuthenticationCallback() {
|
||||
@Override
|
||||
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
|
||||
super.onAuthenticationError(errorCode, errString);
|
||||
Log.i(TAG, "Authentication error: " + errString);
|
||||
public void onAuthenticationError(int errcode, @NonNull CharSequence errString) {
|
||||
super.onAuthenticationError(errcode, errString);
|
||||
Log.i(TAG, "Authentication error: " + errcode +" | "+ errString);
|
||||
func.accept(new BiometricResult(errcode, (String) errString));
|
||||
}
|
||||
@Override
|
||||
public void onAuthenticationFailed() {
|
||||
super.onAuthenticationFailed();
|
||||
Log.i(TAG, "Authentication failed!");
|
||||
func.accept(new BiometricResult(ERROR_BIOMETRIC_FAIL, "Authentication failed"));
|
||||
}
|
||||
@Override
|
||||
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
|
||||
super.onAuthenticationSucceeded(result);
|
||||
Log.i(TAG, "Authentication succeeded!");
|
||||
try {
|
||||
func.accept(result.getCryptoObject().getCipher());
|
||||
} catch (Exception e) {
|
||||
Log.e("BiometricHelper", e.getMessage());
|
||||
}
|
||||
func.accept(new BiometricResult(result.getCryptoObject().getCipher()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
61
app/src/com/jc/jcfw/security/BiometricResult.java
Normal file
61
app/src/com/jc/jcfw/security/BiometricResult.java
Normal file
@ -0,0 +1,61 @@
|
||||
package com.jc.jcfw.security;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class BiometricResult {
|
||||
private Cipher cipher;
|
||||
private boolean error;
|
||||
private int errcode;
|
||||
private String errmsg;
|
||||
|
||||
public BiometricResult(Cipher cipher) {
|
||||
if (null != cipher) {
|
||||
this.cipher = cipher;
|
||||
this.error = false;
|
||||
} else {
|
||||
this.error = true;
|
||||
this.errcode = 101;
|
||||
this.errmsg = "cipher is null";
|
||||
}
|
||||
}
|
||||
|
||||
public BiometricResult(int errcode, String errmsg) {
|
||||
this.error = true;
|
||||
this.errcode = errcode;
|
||||
this.errmsg = errmsg;
|
||||
}
|
||||
@Nullable
|
||||
public Cipher getCipher() {
|
||||
return cipher;
|
||||
}
|
||||
|
||||
public void setCipher(Cipher cipher) {
|
||||
this.cipher = cipher;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(boolean error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public int getErrcode() {
|
||||
return errcode;
|
||||
}
|
||||
|
||||
public void setErrcode(int errcode) {
|
||||
this.errcode = errcode;
|
||||
}
|
||||
|
||||
public String getErrmsg() {
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
public void setErrmsg(String errmsg) {
|
||||
this.errmsg = errmsg;
|
||||
}
|
||||
}
|
@ -5,15 +5,19 @@ import static android.security.keystore.KeyProperties.ENCRYPTION_PADDING_PKCS7;
|
||||
|
||||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.util.Log;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.KeyStore;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class CryptographyManagerImpl implements CryptographyManager {
|
||||
|
||||
|
56
app/src/com/jc/jcfw/util/Installation.java
Normal file
56
app/src/com/jc/jcfw/util/Installation.java
Normal file
@ -0,0 +1,56 @@
|
||||
package com.jc.jcfw.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Installation {
|
||||
private static String sID = null;
|
||||
private static final String INSTALLATION = "INSTALLATION";
|
||||
|
||||
public synchronized static String id(Context context) {
|
||||
if (sID == null) {
|
||||
File installation = new File(context.getFilesDir(), INSTALLATION);
|
||||
try {
|
||||
if (!installation.exists())
|
||||
writeInstallationFile(installation);
|
||||
sID = readInstallationFile(installation);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return sID;
|
||||
}
|
||||
|
||||
private static String readInstallationFile(File installation) throws IOException {
|
||||
RandomAccessFile f = new RandomAccessFile(installation, "r");
|
||||
byte[] bytes = new byte[(int) f.length()];
|
||||
f.readFully(bytes);
|
||||
f.close();
|
||||
return new String(bytes);
|
||||
}
|
||||
|
||||
private static void writeInstallationFile(File installation) throws IOException {
|
||||
FileOutputStream out = new FileOutputStream(installation);
|
||||
String id = UUID.randomUUID().toString();
|
||||
out.write(id.getBytes());
|
||||
out.close();
|
||||
}
|
||||
|
||||
public static String getBuildInfo() {
|
||||
//这里选用了几个不会随系统更新而改变的值
|
||||
StringBuffer buildSB = new StringBuffer();
|
||||
buildSB.append(Build.BRAND).append("/");
|
||||
buildSB.append(Build.PRODUCT).append("/");
|
||||
buildSB.append(Build.DEVICE).append("/");
|
||||
buildSB.append(Build.ID).append("/");
|
||||
buildSB.append(Build.VERSION.INCREMENTAL);
|
||||
return buildSB.toString();
|
||||
// return Build.FINGERPRINT;
|
||||
}
|
||||
}
|
@ -14,6 +14,11 @@
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
<item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
|
||||
</style>
|
||||
<style name="DayNightActivity" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
</style>
|
||||
<style name="CebgMainActivity" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="android:windowBackground">@android:color/black</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
|
Loading…
x
Reference in New Issue
Block a user