Skip to content

Commit

Permalink
feat(iOS, Android): add AppUUID Lib for plugins (#5690)
Browse files Browse the repository at this point in the history
* feat(iOS, Android): add AppUUID Lib for plugins

* chore: fmt

* chore: swift standard style changes
  • Loading branch information
IT-MikeS committed Jun 17, 2022
1 parent 62f0a5e commit 05e76cf
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
65 changes: 65 additions & 0 deletions android/capacitor/src/main/java/com/getcapacitor/AppUUID.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.getcapacitor;

import android.content.Context;
import android.content.SharedPreferences;
import androidx.appcompat.app.AppCompatActivity;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
import java.util.UUID;

public final class AppUUID {

private static final String KEY = "CapacitorAppUUID";

public static String getAppUUID(AppCompatActivity activity) throws Exception {
assertAppUUID(activity);
return readUUID(activity);
}

public static void regenerateAppUUID(AppCompatActivity activity) throws Exception {
try {
String uuid = generateUUID();
writeUUID(activity, uuid);
} catch (NoSuchAlgorithmException ex) {
throw new Exception("Capacitor App UUID could not be generated.");
}
}

private static void assertAppUUID(AppCompatActivity activity) throws Exception {
String uuid = readUUID(activity);
if (uuid.equals("")) {
regenerateAppUUID(activity);
}
}

private static String generateUUID() throws NoSuchAlgorithmException {
MessageDigest salt = MessageDigest.getInstance("SHA-256");
salt.update(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
return bytesToHex(salt.digest());
}

private static String readUUID(AppCompatActivity activity) {
SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
return sharedPref.getString(KEY, "");
}

private static void writeUUID(AppCompatActivity activity, String uuid) {
SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(KEY, uuid);
editor.apply();
}

private static String bytesToHex(byte[] bytes) {
byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
byte[] hexChars = new byte[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, StandardCharsets.UTF_8);
}
}
4 changes: 4 additions & 0 deletions ios/Capacitor/Capacitor.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
0F83E885285A332E006C43CB /* AppUUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F83E884285A332D006C43CB /* AppUUID.swift */; };
2F81F5C926FB7CB400DD35BE /* CAPBridgeViewController+CDVScreenOrientationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F81F5C726FB7CB400DD35BE /* CAPBridgeViewController+CDVScreenOrientationDelegate.h */; };
2F81F5CA26FB7CB400DD35BE /* CAPBridgeViewController+CDVScreenOrientationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F81F5C826FB7CB400DD35BE /* CAPBridgeViewController+CDVScreenOrientationDelegate.m */; };
373A69C1255C9360000A6F44 /* NotificationHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373A69C0255C9360000A6F44 /* NotificationHandlerProtocol.swift */; };
Expand Down Expand Up @@ -138,6 +139,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
0F83E884285A332D006C43CB /* AppUUID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUUID.swift; sourceTree = "<group>"; };
2F81F5C726FB7CB400DD35BE /* CAPBridgeViewController+CDVScreenOrientationDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CAPBridgeViewController+CDVScreenOrientationDelegate.h"; sourceTree = "<group>"; };
2F81F5C826FB7CB400DD35BE /* CAPBridgeViewController+CDVScreenOrientationDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CAPBridgeViewController+CDVScreenOrientationDelegate.m"; sourceTree = "<group>"; };
373A69C0255C9360000A6F44 /* NotificationHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationHandlerProtocol.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -355,6 +357,7 @@
373A69F1255C95D0000A6F44 /* NotificationRouter.swift */,
62E79C562638AF7500414164 /* assets */,
A71289E527F380A500DADDF3 /* Router.swift */,
0F83E884285A332D006C43CB /* AppUUID.swift */,
);
path = Capacitor;
sourceTree = "<group>";
Expand Down Expand Up @@ -616,6 +619,7 @@
62FABD1A25AE5C01007B3814 /* Array+Capacitor.swift in Sources */,
62959B172524DA7800A3D7F1 /* JSExport.swift in Sources */,
373A69C1255C9360000A6F44 /* NotificationHandlerProtocol.swift in Sources */,
0F83E885285A332E006C43CB /* AppUUID.swift in Sources */,
625AF1ED258963C700869675 /* WebViewAssetHandler.swift in Sources */,
62959B3C2524DA7800A3D7F1 /* CAPBridgeDelegate.swift in Sources */,
62959B2F2524DA7800A3D7F1 /* DefaultPlugins.m in Sources */,
Expand Down
53 changes: 53 additions & 0 deletions ios/Capacitor/Capacitor/AppUUID.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import CommonCrypto
import Foundation

private func hexString(_ iterator: Array<UInt8>.Iterator) -> String {
return iterator.map { String(format: "%02x", $0) }.joined()
}

extension Data {
public var sha256: String {
var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
self.withUnsafeBytes { bytes in
_ = CC_SHA256(bytes.baseAddress, CC_LONG(self.count), &digest)
}
return hexString(digest.makeIterator())
}
}

public class AppUUID {
private static let key: String = "CapacitorAppUUID"

public static func getAppUUID() -> String {
assertAppUUID()
return readUUID()
}

public static func regenerateAppUUID() {
let uuid = generateUUID()
writeUUID(uuid)
}

private static func assertAppUUID() {
let uuid = readUUID()
if uuid == "" {
regenerateAppUUID()
}
}

private static func generateUUID() -> String {
let uuid: String = UUID.init().uuidString
return uuid.data(using: .utf8)!.sha256
}

private static func readUUID() -> String {
let defaults = UserDefaults.standard
return defaults.string(forKey: key) ?? ""
}

private static func writeUUID(_ uuid: String) {
let defaults = UserDefaults.standard
defaults.set(uuid, forKey: key)
}

}

0 comments on commit 05e76cf

Please sign in to comment.