diff --git a/app/libs/Obdmobile.aar b/app/libs/Obdmobile.aar index cdc5eebb..c27ac5cb 100644 Binary files a/app/libs/Obdmobile.aar and b/app/libs/Obdmobile.aar differ diff --git a/app/src/main/java/com/omni/wallet/base/AppBaseActivity.java b/app/src/main/java/com/omni/wallet/base/AppBaseActivity.java index c4faa930..2891ab62 100644 --- a/app/src/main/java/com/omni/wallet/base/AppBaseActivity.java +++ b/app/src/main/java/com/omni/wallet/base/AppBaseActivity.java @@ -1,14 +1,39 @@ package com.omni.wallet.base; +import android.accounts.Account; +import android.app.Activity; import android.app.ActivityManager; import android.content.Context; +import android.content.Intent; +import android.os.Environment; +import android.support.annotation.NonNull; import android.util.Log; +import com.google.android.gms.auth.api.signin.GoogleSignIn; +import com.google.android.gms.auth.api.signin.GoogleSignInClient; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.common.api.Scope; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.api.client.extensions.android.http.AndroidHttp; +import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential; +import com.google.api.client.json.gson.GsonFactory; +import com.google.api.services.drive.Drive; +import com.google.api.services.drive.DriveScopes; +import com.omni.wallet.baselibrary.utils.LogUtils; +import com.omni.wallet.baselibrary.utils.StringUtils; +import com.omni.wallet.baselibrary.utils.ToastUtils; import com.omni.wallet.common.ConstantInOB; +import com.omni.wallet.common.ConstantWithNetwork; import com.omni.wallet.framelibrary.base.FrameBaseActivity; +import com.omni.wallet.framelibrary.entity.User; +import com.omni.wallet.utils.DriveServiceHelper; +import com.omni.wallet.utils.MoveCacheFileToFileObd; import com.omni.wallet.view.dialog.UnlockDialog; +import java.io.File; +import java.util.Collections; import java.util.List; /** @@ -22,9 +47,12 @@ public abstract class AppBaseActivity extends FrameBaseActivity { private static boolean stopApp = false; UnlockDialog mUnlockDialog; - private String getRunningActivityName(){ - ActivityManager activityManager=(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); - String runningActivity=activityManager.getRunningTasks(1).get(0).topActivity.getClassName(); + private static final int REQUEST_CODE_SIGN_IN = 30; + private DriveServiceHelper mDriveServiceHelper; + + public String getRunningActivityName() { + ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + String runningActivity = activityManager.getRunningTasks(1).get(0).topActivity.getClassName(); return runningActivity; } @@ -57,12 +85,11 @@ public boolean isRunningForeground() { return false; } - - @Override + @Override protected void onStop() { super.onStop(); boolean isRunningSelf = isRunningForeground(); - if (!isRunningSelf){ + if (!isRunningSelf) { long stopTime = System.currentTimeMillis(); setStopTime(stopTime); setStopApp(true); @@ -72,17 +99,17 @@ protected void onStop() { @Override protected void onResume() { super.onResume(); - if (isStopApp()){ + if (isStopApp()) { long startTime = System.currentTimeMillis(); long stopTime = getStopTime(); long stopMills = startTime - stopTime; setStopApp(false); - if (stopMills >= ConstantInOB.MINUTE_MILLIS * 5){ + if (stopMills >= ConstantInOB.MINUTE_MILLIS * 5) { String runningActivityName = getRunningActivityName(); - String [] runningActivityNameArr = runningActivityName.split("\\."); - String name = runningActivityNameArr[5]; - Log.e(TAG+ "onResume: ", name); - switch (name){ + String[] runningActivityNameArr = runningActivityName.split("\\."); + String name = runningActivityNameArr[5]; + Log.e(TAG + "onResume: ", name); + switch (name) { case "UnlockActivity": case "backup": case "recoverwallet": @@ -99,16 +126,167 @@ protected void onResume() { } } } + } + + public void autoBackupFiles() { + File walletPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadDirectory() + "wallet.db"); + File channelPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadChannelDirectory() + "channel.db"); + String storagePath = Environment.getExternalStorageDirectory() + "/OBMainnetBackupFiles"; + File toWalletPath = new File(Environment.getExternalStorageDirectory() + "/OBMainnetBackupFiles/wallet.db"); + File toChannelPath = new File(Environment.getExternalStorageDirectory() + "/OBMainnetBackupFiles/channel.db"); + if (walletPath.exists() && channelPath.exists()) { + // 本地备份(Local backup) + MoveCacheFileToFileObd.createDirs(storagePath); + MoveCacheFileToFileObd.copyFile(walletPath, toWalletPath); + MoveCacheFileToFileObd.copyFile(channelPath, toChannelPath); + MoveCacheFileToFileObd.createFile(storagePath + "/address.txt", User.getInstance().getWalletAddress(mContext)); + // Authenticate the user. For most apps, this should be done when the user performs an + // action that requires Drive access rather than in onCreate. + if (StringUtils.isEmpty(User.getInstance().getGoogleAccountName(mContext))) { + requestSignIn(); + } else { + GoogleAccountCredential credential = + GoogleAccountCredential.usingOAuth2( + this, Collections.singleton(DriveScopes.DRIVE_FILE)); + credential.setSelectedAccount(new Account(User.getInstance().getGoogleAccountName(mContext), User.getInstance().getGoogleAccountType(mContext))); + Drive googleDriveService = + new Drive.Builder( + AndroidHttp.newCompatibleTransport(), + new GsonFactory(), + credential) + .setApplicationName("OB Wallet") + .build(); + + // The DriveServiceHelper encapsulates all REST API and SAF functionality. + // Its instantiation is required before handling any onClick actions. + mDriveServiceHelper = new DriveServiceHelper(googleDriveService); + createAddressFile(); + } + } else { + ToastUtils.showToast(mContext, "The backup file does not exist"); + } + } + /** + * Starts a sign-in activity using {@link #REQUEST_CODE_SIGN_IN}. + */ + private void requestSignIn() { + LogUtils.e(TAG, "Requesting sign-in"); + + GoogleSignInOptions signInOptions = + new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestEmail() + .requestScopes(new Scope(DriveScopes.DRIVE_FILE)) + .build(); + GoogleSignInClient client = GoogleSignIn.getClient(this, signInOptions); + + // The result of the sign-in Intent is handled in onActivityResult. + startActivityForResult(client.getSignInIntent(), REQUEST_CODE_SIGN_IN); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent resultData) { + switch (requestCode) { + case REQUEST_CODE_SIGN_IN: + if (resultCode == Activity.RESULT_OK && resultData != null) { + handleSignInResult(resultData); + } + break; + } + + super.onActivityResult(requestCode, resultCode, resultData); + } + + /** + * Handles the {@code result} of a completed sign-in activity initiated from requestSignIn. + */ + private void handleSignInResult(Intent result) { + GoogleSignIn.getSignedInAccountFromIntent(result) + .addOnSuccessListener(googleAccount -> { + LogUtils.e(TAG, "Signed in as " + googleAccount.getEmail()); + + // Use the authenticated account to sign in to the Drive service. + GoogleAccountCredential credential = + GoogleAccountCredential.usingOAuth2( + this, Collections.singleton(DriveScopes.DRIVE_FILE)); + credential.setSelectedAccount(googleAccount.getAccount()); + User.getInstance().setGoogleAccountName(mContext, googleAccount.getAccount().name); + User.getInstance().setGoogleAccountType(mContext, googleAccount.getAccount().type); + Drive googleDriveService = + new Drive.Builder( + AndroidHttp.newCompatibleTransport(), + new GsonFactory(), + credential) + .setApplicationName("OB Wallet") + .build(); + + // The DriveServiceHelper encapsulates all REST API and SAF functionality. + // Its instantiation is required before handling any onClick actions. + mDriveServiceHelper = new DriveServiceHelper(googleDriveService); + createAddressFile(); + }) + .addOnFailureListener(exception -> LogUtils.e(TAG, "Unable to sign in.", exception)); + } + + /** + * Creates a new file via the Drive REST API. + */ + private void createAddressFile() { + if (mDriveServiceHelper != null) { + LogUtils.e(TAG, "Creating a address file."); + mDriveServiceHelper.createFile(User.getInstance().getWalletAddress(mContext) + "_mainnet") + .addOnSuccessListener(fileId -> createWalletFile()) + .addOnFailureListener(exception -> { + LogUtils.e(TAG, "Couldn't create address file.", exception); + }); + } + } + + private void createWalletFile() { + if (mDriveServiceHelper != null) { + LogUtils.e(TAG, "Creating wallet file."); + String filePath = mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadDirectory() + "wallet.db"; + LogUtils.e(TAG, filePath); + mDriveServiceHelper.createFile(filePath, "wallet_mainnet.db").addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(String s) { + createChannelFile(); + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + LogUtils.e(TAG, "Couldn't create wallet file.", e); + } + }); + } + } + + private void createChannelFile() { + if (mDriveServiceHelper != null) { + LogUtils.e(TAG, "Creating channel file."); + String filePath = mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadChannelDirectory() + "channel.db"; + LogUtils.e(TAG, filePath); + mDriveServiceHelper.createFile(filePath, "channel_mainnet.db").addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(String s) { + LogUtils.e(TAG, "Channel fileId" + s); + User.getInstance().setAutoBackUp(mContext, true); + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + LogUtils.e(TAG, "Couldn't create channel file.", e); + } + }); + } } @Override protected void onDestroy() { super.onDestroy(); setStopApp(false); - if (mUnlockDialog != null){ + if (mUnlockDialog != null) { mUnlockDialog.release(); } - } } diff --git a/app/src/main/java/com/omni/wallet/base/BaseWebViewActivity.java b/app/src/main/java/com/omni/wallet/base/BaseWebViewActivity.java index 8d178b43..a3a2fc52 100644 --- a/app/src/main/java/com/omni/wallet/base/BaseWebViewActivity.java +++ b/app/src/main/java/com/omni/wallet/base/BaseWebViewActivity.java @@ -138,7 +138,7 @@ public boolean onWebViewShouldOverrideUrl(WebView webView, String url) { } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // // 友盟QQ分享的回调 // UMUtils.with(this).onActivityResult(requestCode, resultCode, data); diff --git a/app/src/main/java/com/omni/wallet/entity/event/PayInvoiceSuccessEvent.java b/app/src/main/java/com/omni/wallet/entity/event/PayInvoiceSuccessEvent.java index 14d6f690..98475350 100644 --- a/app/src/main/java/com/omni/wallet/entity/event/PayInvoiceSuccessEvent.java +++ b/app/src/main/java/com/omni/wallet/entity/event/PayInvoiceSuccessEvent.java @@ -7,4 +7,13 @@ * date: 2022/11/27 */ public class PayInvoiceSuccessEvent { + private int tag; + + public int getTag() { + return tag; + } + + public void setTag(int tag) { + this.tag = tag; + } } diff --git a/app/src/main/java/com/omni/wallet/entity/event/SubscribeChannelChangeEvent.java b/app/src/main/java/com/omni/wallet/entity/event/SubscribeChannelChangeEvent.java new file mode 100644 index 00000000..0a514873 --- /dev/null +++ b/app/src/main/java/com/omni/wallet/entity/event/SubscribeChannelChangeEvent.java @@ -0,0 +1,10 @@ +package com.omni.wallet.entity.event; + +/** + * 汉: 订阅通道相关变化的通知实体 + * En: SubscribeChannelChangeEvent + * author: guoyalei + * date: 2023/6/20 + */ +public class SubscribeChannelChangeEvent { +} \ No newline at end of file diff --git a/app/src/main/java/com/omni/wallet/ui/activity/AccountLightningActivity.java b/app/src/main/java/com/omni/wallet/ui/activity/AccountLightningActivity.java index 4fcf0a5a..e698ccc8 100644 --- a/app/src/main/java/com/omni/wallet/ui/activity/AccountLightningActivity.java +++ b/app/src/main/java/com/omni/wallet/ui/activity/AccountLightningActivity.java @@ -72,6 +72,7 @@ import com.omni.wallet.entity.event.SelectAccountEvent; import com.omni.wallet.entity.event.SendSuccessEvent; import com.omni.wallet.entity.event.StartNodeEvent; +import com.omni.wallet.entity.event.SubscribeChannelChangeEvent; import com.omni.wallet.entity.event.UpdateAssetsDataEvent; import com.omni.wallet.entity.event.UpdateBalanceEvent; import com.omni.wallet.framelibrary.entity.User; @@ -115,6 +116,7 @@ import lnrpc.LightningOuterClass; import obdmobile.Callback; import obdmobile.Obdmobile; +import obdmobile.RecvStream; public class AccountLightningActivity extends AppBaseActivity { private static final String TAG = AccountLightningActivity.class.getSimpleName(); @@ -1070,6 +1072,14 @@ public void onUpdateBalanceEvent(UpdateBalanceEvent event) { @Subscribe(threadMode = ThreadMode.MAIN) public void onPayInvoiceSuccessEvent(PayInvoiceSuccessEvent event) { getAssetAndBtcData(); + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + if (event.getTag() == 1) { + autoBackupFiles(); + } + } + }); } /** @@ -1159,6 +1169,7 @@ public void run() { isRequest = true; User.getInstance().setUserId(mContext, "1"); User.getInstance().setBackUp(mContext, true); + subscribeChannelChange(); } }); if (StringUtils.isEmpty(User.getInstance().getWalletAddress(mContext))) { @@ -1205,34 +1216,79 @@ public void onResponse(byte[] bytes) { WalletState.getInstance().setWalletStateCallback(walletStateCallback); } + private void subscribeChannelChange() { + LightningOuterClass.ChannelBackupSubscription channelBackupSubscription = LightningOuterClass.ChannelBackupSubscription.newBuilder().build(); + Obdmobile.subscribeChannelChange(channelBackupSubscription.toByteArray(), new RecvStream() { + @Override + public void onError(Exception e) { + LogUtils.e(TAG, e.getMessage()); + } + + @Override + public void onResponse(byte[] bytes) { + if (bytes == null) { + return; + } + LogUtils.e(TAG, "subscribeChannelChange"); + User.getInstance().setAutoBackUp(mContext, false); + EventBus.getDefault().post(new SubscribeChannelChangeEvent()); + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSubscribeChannelChangeEvent(SubscribeChannelChangeEvent event) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + String runningActivityName = getRunningActivityName(); + String[] runningActivityNameArr = runningActivityName.split("\\."); + String name = runningActivityNameArr[5]; + switch (name) { + case "AccountLightningActivity": + if (User.getInstance().isAutoBackUp(mContext) == false) { + autoBackupFiles(); + } + break; + default: + break; + } + } + }); + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onBackUpEventEvent(BackUpEvent event) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { if (event.getCode() == 1) { - File walletPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadDirectory() + "wallet.db"); - File channelPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadChannelDirectory() + "channel.db"); - String storagePath = Environment.getExternalStorageDirectory() + "/OBBackupFiles"; - File toWalletPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/wallet.db"); - File toChannelPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/channel.db"); - if (walletPath.exists() && channelPath.exists()) { - // 本地备份(Local backup) - MoveCacheFileToFileObd.createDirs(storagePath); - MoveCacheFileToFileObd.copyFile(walletPath, toWalletPath); - MoveCacheFileToFileObd.copyFile(channelPath, toChannelPath); - MoveCacheFileToFileObd.createFile(storagePath + "/address.txt", User.getInstance().getWalletAddress(mContext)); - // Authenticate the user. For most apps, this should be done when the user performs an - // action that requires Drive access rather than in onCreate. - requestSignIn(); - } else { - ToastUtils.showToast(mContext, "The backup file does not exist"); - } + backupFiles(); } } }); } + private void backupFiles() { + File walletPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadDirectory() + "wallet.db"); + File channelPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadChannelDirectory() + "channel.db"); + String storagePath = Environment.getExternalStorageDirectory() + "/OBBackupFiles"; + File toWalletPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/wallet.db"); + File toChannelPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/channel.db"); + if (walletPath.exists() && channelPath.exists()) { + // 本地备份(Local backup) + MoveCacheFileToFileObd.createDirs(storagePath); + MoveCacheFileToFileObd.copyFile(walletPath, toWalletPath); + MoveCacheFileToFileObd.copyFile(channelPath, toChannelPath); + MoveCacheFileToFileObd.createFile(storagePath + "/address.txt", User.getInstance().getWalletAddress(mContext)); + // Authenticate the user. For most apps, this should be done when the user performs an + // action that requires Drive access rather than in onCreate. + requestSignIn(); + } else { + ToastUtils.showToast(mContext, "The backup file does not exist"); + } + } + /** * Starts a sign-in activity using {@link #REQUEST_CODE_SIGN_IN}. */ @@ -1264,8 +1320,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent resultData) } /** - * Handles the {@code result} of a completed sign-in activity initiated from {@link - * #requestSignIn()}. + * Handles the {@code result} of a completed sign-in activity initiated from requestSignIn. */ private void handleSignInResult(Intent result) { GoogleSignIn.getSignedInAccountFromIntent(result) @@ -1277,6 +1332,8 @@ private void handleSignInResult(Intent result) { GoogleAccountCredential.usingOAuth2( this, Collections.singleton(DriveScopes.DRIVE_FILE)); credential.setSelectedAccount(googleAccount.getAccount()); + User.getInstance().setGoogleAccountName(mContext, googleAccount.getAccount().name); + User.getInstance().setGoogleAccountType(mContext, googleAccount.getAccount().type); Drive googleDriveService = new Drive.Builder( AndroidHttp.newCompatibleTransport(), diff --git a/app/src/main/java/com/omni/wallet/ui/activity/BalanceDetailActivity.java b/app/src/main/java/com/omni/wallet/ui/activity/BalanceDetailActivity.java index d6a6c1df..e462e4c9 100644 --- a/app/src/main/java/com/omni/wallet/ui/activity/BalanceDetailActivity.java +++ b/app/src/main/java/com/omni/wallet/ui/activity/BalanceDetailActivity.java @@ -68,6 +68,7 @@ import com.omni.wallet.entity.event.RebootEvent; import com.omni.wallet.entity.event.ScanResultEvent; import com.omni.wallet.entity.event.SendSuccessEvent; +import com.omni.wallet.entity.event.SubscribeChannelChangeEvent; import com.omni.wallet.framelibrary.entity.User; import com.omni.wallet.ui.activity.channel.ChannelsActivity; import com.omni.wallet.utils.CopyUtil; @@ -1991,6 +1992,14 @@ public void onPayInvoiceSuccessEvent(PayInvoiceSuccessEvent event) { mFilterTimeTv.setText(DateUtils.YearMonth(filterTime)); fetchTransactionsFromLND(filterTime); fetchPaymentsFromLND(); + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + if (event.getTag() == 2) { + autoBackupFiles(); + } + } + }); } /** @@ -2088,34 +2097,59 @@ public static void removeDuplicateInvoice(List list) { System.out.println(list); } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSubscribeChannelChangeEvent(SubscribeChannelChangeEvent event) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + String runningActivityName = getRunningActivityName(); + String[] runningActivityNameArr = runningActivityName.split("\\."); + String name = runningActivityNameArr[5]; + switch (name) { + case "BalanceDetailActivity": + if (User.getInstance().isAutoBackUp(mContext) == false) { + autoBackupFiles(); + } + break; + default: + break; + } + } + }); + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onBackUpEventEvent(BackUpEvent event) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { if (event.getCode() == 2) { - File walletPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadDirectory() + "wallet.db"); - File channelPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadChannelDirectory() + "channel.db"); - String storagePath = Environment.getExternalStorageDirectory() + "/OBBackupFiles"; - File toWalletPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/wallet.db"); - File toChannelPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/channel.db"); - if (walletPath.exists() && channelPath.exists()) { - // 本地备份(Local backup) - MoveCacheFileToFileObd.createDirs(storagePath); - MoveCacheFileToFileObd.copyFile(walletPath, toWalletPath); - MoveCacheFileToFileObd.copyFile(channelPath, toChannelPath); - MoveCacheFileToFileObd.createFile(storagePath + "/address.txt", User.getInstance().getWalletAddress(mContext)); - // Authenticate the user. For most apps, this should be done when the user performs an - // action that requires Drive access rather than in onCreate. - requestSignIn(); - } else { - ToastUtils.showToast(mContext, "The backup file does not exist"); - } + backupFiles(); } } }); } + private void backupFiles() { + File walletPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadDirectory() + "wallet.db"); + File channelPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadChannelDirectory() + "channel.db"); + String storagePath = Environment.getExternalStorageDirectory() + "/OBBackupFiles"; + File toWalletPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/wallet.db"); + File toChannelPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/channel.db"); + if (walletPath.exists() && channelPath.exists()) { + // 本地备份(Local backup) + MoveCacheFileToFileObd.createDirs(storagePath); + MoveCacheFileToFileObd.copyFile(walletPath, toWalletPath); + MoveCacheFileToFileObd.copyFile(channelPath, toChannelPath); + MoveCacheFileToFileObd.createFile(storagePath + "/address.txt", User.getInstance().getWalletAddress(mContext)); + // Authenticate the user. For most apps, this should be done when the user performs an + // action that requires Drive access rather than in onCreate. + requestSignIn(); + } else { + ToastUtils.showToast(mContext, "The backup file does not exist"); + } + } + /** * Starts a sign-in activity using {@link #REQUEST_CODE_SIGN_IN}. */ @@ -2147,8 +2181,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent resultData) } /** - * Handles the {@code result} of a completed sign-in activity initiated from {@link - * #requestSignIn()}. + * Handles the {@code result} of a completed sign-in activity initiated from requestSignIn. */ private void handleSignInResult(Intent result) { GoogleSignIn.getSignedInAccountFromIntent(result) @@ -2160,6 +2193,8 @@ private void handleSignInResult(Intent result) { GoogleAccountCredential.usingOAuth2( this, Collections.singleton(DriveScopes.DRIVE_FILE)); credential.setSelectedAccount(googleAccount.getAccount()); + User.getInstance().setGoogleAccountName(mContext, googleAccount.getAccount().name); + User.getInstance().setGoogleAccountType(mContext, googleAccount.getAccount().type); Drive googleDriveService = new Drive.Builder( AndroidHttp.newCompatibleTransport(), diff --git a/app/src/main/java/com/omni/wallet/ui/activity/ChooseRestoreTypeActivity.java b/app/src/main/java/com/omni/wallet/ui/activity/ChooseRestoreTypeActivity.java index 7e96816c..4fef6571 100644 --- a/app/src/main/java/com/omni/wallet/ui/activity/ChooseRestoreTypeActivity.java +++ b/app/src/main/java/com/omni/wallet/ui/activity/ChooseRestoreTypeActivity.java @@ -200,8 +200,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent resultData) } /** - * Handles the {@code result} of a completed sign-in activity initiated from {@link - * #requestSignIn()}. + * Handles the {@code result} of a completed sign-in activity initiated from requestSignIn. */ private void handleSignInResult(Intent result) { GoogleSignIn.getSignedInAccountFromIntent(result) diff --git a/app/src/main/java/com/omni/wallet/ui/activity/channel/ChannelsActivity.java b/app/src/main/java/com/omni/wallet/ui/activity/channel/ChannelsActivity.java index 97ac4e26..e88eb71d 100644 --- a/app/src/main/java/com/omni/wallet/ui/activity/channel/ChannelsActivity.java +++ b/app/src/main/java/com/omni/wallet/ui/activity/channel/ChannelsActivity.java @@ -43,8 +43,10 @@ import com.omni.wallet.common.NetworkType; import com.omni.wallet.entity.event.BackUpEvent; import com.omni.wallet.entity.event.CloseChannelEvent; +import com.omni.wallet.entity.event.PayInvoiceSuccessEvent; import com.omni.wallet.entity.event.RebootEvent; import com.omni.wallet.entity.event.ScanResultEvent; +import com.omni.wallet.entity.event.SubscribeChannelChangeEvent; import com.omni.wallet.framelibrary.entity.User; import com.omni.wallet.ui.activity.ScanActivity; import com.omni.wallet.ui.activity.UnlockActivity; @@ -501,6 +503,22 @@ public void run() { } } + /** + * 支付发票成功的消息通知监听 + * Message notification monitoring after pay invoice success + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPayInvoiceSuccessEvent(PayInvoiceSuccessEvent event) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + if (event.getTag() == 3) { + autoBackupFiles(); + } + } + }); + } + /** * 关闭通道后的消息通知监听 * Message notification monitoring after open channel @@ -520,34 +538,59 @@ public void onRebootEvent(RebootEvent event) { switchActivityFinish(UnlockActivity.class); } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSubscribeChannelChangeEvent(SubscribeChannelChangeEvent event) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + String runningActivityName = getRunningActivityName(); + String[] runningActivityNameArr = runningActivityName.split("\\."); + String name = runningActivityNameArr[5]; + switch (name) { + case "channel": + if (User.getInstance().isAutoBackUp(mContext) == false) { + autoBackupFiles(); + } + break; + default: + break; + } + } + }); + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onBackUpEventEvent(BackUpEvent event) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { if (event.getCode() == 3) { - File walletPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadDirectory() + "wallet.db"); - File channelPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadChannelDirectory() + "channel.db"); - String storagePath = Environment.getExternalStorageDirectory() + "/OBBackupFiles"; - File toWalletPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/wallet.db"); - File toChannelPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/channel.db"); - if (walletPath.exists() && channelPath.exists()) { - // 本地备份(Local backup) - MoveCacheFileToFileObd.createDirs(storagePath); - MoveCacheFileToFileObd.copyFile(walletPath, toWalletPath); - MoveCacheFileToFileObd.copyFile(channelPath, toChannelPath); - MoveCacheFileToFileObd.createFile(storagePath + "/address.txt", User.getInstance().getWalletAddress(mContext)); - // Authenticate the user. For most apps, this should be done when the user performs an - // action that requires Drive access rather than in onCreate. - requestSignIn(); - } else { - ToastUtils.showToast(mContext, "The backup file does not exist"); - } + backupFiles(); } } }); } + private void backupFiles() { + File walletPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadDirectory() + "wallet.db"); + File channelPath = new File(mContext.getExternalFilesDir(null) + "/obd" + ConstantWithNetwork.getInstance(ConstantInOB.networkType).getDownloadChannelDirectory() + "channel.db"); + String storagePath = Environment.getExternalStorageDirectory() + "/OBBackupFiles"; + File toWalletPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/wallet.db"); + File toChannelPath = new File(Environment.getExternalStorageDirectory() + "/OBBackupFiles/channel.db"); + if (walletPath.exists() && channelPath.exists()) { + // 本地备份(Local backup) + MoveCacheFileToFileObd.createDirs(storagePath); + MoveCacheFileToFileObd.copyFile(walletPath, toWalletPath); + MoveCacheFileToFileObd.copyFile(channelPath, toChannelPath); + MoveCacheFileToFileObd.createFile(storagePath + "/address.txt", User.getInstance().getWalletAddress(mContext)); + // Authenticate the user. For most apps, this should be done when the user performs an + // action that requires Drive access rather than in onCreate. + requestSignIn(); + } else { + ToastUtils.showToast(mContext, "The backup file does not exist"); + } + } + /** * Starts a sign-in activity using {@link #REQUEST_CODE_SIGN_IN}. */ @@ -579,8 +622,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent resultData) } /** - * Handles the {@code result} of a completed sign-in activity initiated from {@link - * #requestSignIn()}. + * Handles the {@code result} of a completed sign-in activity initiated from requestSignIn. */ private void handleSignInResult(Intent result) { GoogleSignIn.getSignedInAccountFromIntent(result) @@ -592,6 +634,8 @@ private void handleSignInResult(Intent result) { GoogleAccountCredential.usingOAuth2( this, Collections.singleton(DriveScopes.DRIVE_FILE)); credential.setSelectedAccount(googleAccount.getAccount()); + User.getInstance().setGoogleAccountName(mContext, googleAccount.getAccount().name); + User.getInstance().setGoogleAccountType(mContext, googleAccount.getAccount().type); Drive googleDriveService = new Drive.Builder( AndroidHttp.newCompatibleTransport(), diff --git a/app/src/main/java/com/omni/wallet/view/dialog/CreateChannelDialog.java b/app/src/main/java/com/omni/wallet/view/dialog/CreateChannelDialog.java index 845d212c..b54bc605 100644 --- a/app/src/main/java/com/omni/wallet/view/dialog/CreateChannelDialog.java +++ b/app/src/main/java/com/omni/wallet/view/dialog/CreateChannelDialog.java @@ -653,7 +653,7 @@ private void openChannelConnected(String pubkey, long balanceAmount, String wall .setNodePubkey(ByteString.copyFrom(nodeKeyBytes)) .setTargetConf(time) .setPrivate(false) - .setLocalFundingBtcAmount(20000) + .setLocalFundingBtcAmount(40000) .setLocalFundingAssetAmount((long) (CalculateUtil.mul(Double.parseDouble(assetBalance), 100000000))) .setAssetId((int) assetId) .build(); diff --git a/app/src/main/java/com/omni/wallet/view/dialog/PayInvoiceDialog.java b/app/src/main/java/com/omni/wallet/view/dialog/PayInvoiceDialog.java index d49f4666..66218c5d 100644 --- a/app/src/main/java/com/omni/wallet/view/dialog/PayInvoiceDialog.java +++ b/app/src/main/java/com/omni/wallet/view/dialog/PayInvoiceDialog.java @@ -64,6 +64,7 @@ public class PayInvoiceDialog { private AlertDialog mAlertDialog; String mAddress; long mAssetId; + int mTag; String toNodeAddress; long payAmount; String lnInvoice; @@ -93,6 +94,7 @@ public void show(String address, long assetId, String invoiceAddr, int tag) { mLoadingDialog = new LoadingDialog(mContext); mAddress = address; mAssetId = assetId; + mTag = tag; showStepOne(invoiceAddr, tag); /** * @备注: 点击cancel 按钮 @@ -538,7 +540,9 @@ public void onResponse(byte[] bytes) { @Override public void run() { updateInvoiceList(); - EventBus.getDefault().post(new PayInvoiceSuccessEvent()); + PayInvoiceSuccessEvent event = new PayInvoiceSuccessEvent(); + event.setTag(mTag); + EventBus.getDefault().post(event); mLoadingDialog.dismiss(); // updated the history, so it is shown the next time the user views it mAlertDialog.findViewById(R.id.lv_pay_invoice_step_two).setVisibility(View.GONE); @@ -596,7 +600,9 @@ public void run() { LogUtils.e(TAG, "------------------routerOB_SendPaymentV2OnResponse-----------------" + resp); if (resp.getStatus() == LightningOuterClass.Payment.PaymentStatus.SUCCEEDED) { updateInvoiceList(); - EventBus.getDefault().post(new PayInvoiceSuccessEvent()); + PayInvoiceSuccessEvent event = new PayInvoiceSuccessEvent(); + event.setTag(mTag); + EventBus.getDefault().post(event); mLoadingDialog.dismiss(); mAlertDialog.findViewById(R.id.lv_pay_invoice_step_two).setVisibility(View.GONE); mAlertDialog.findViewById(R.id.lv_pay_invoice_step_three).setVisibility(View.VISIBLE); @@ -691,7 +697,9 @@ public void run() { LogUtils.e(TAG, "------------------noRouterOB_SendPaymentV2OnResponse-----------------" + resp); if (resp.getStatus() == LightningOuterClass.Payment.PaymentStatus.SUCCEEDED) { updateInvoiceList(); - EventBus.getDefault().post(new PayInvoiceSuccessEvent()); + PayInvoiceSuccessEvent event = new PayInvoiceSuccessEvent(); + event.setTag(mTag); + EventBus.getDefault().post(event); mLoadingDialog.dismiss(); mAlertDialog.findViewById(R.id.lv_pay_invoice_step_two).setVisibility(View.GONE); mAlertDialog.findViewById(R.id.lv_pay_invoice_step_three).setVisibility(View.VISIBLE); diff --git a/app/src/main/java/com/omni/wallet/view/popupwindow/createinvoice/CreateLuckyPacketPopupWindow.java b/app/src/main/java/com/omni/wallet/view/popupwindow/createinvoice/CreateLuckyPacketPopupWindow.java index 3e018ece..cfc271f9 100644 --- a/app/src/main/java/com/omni/wallet/view/popupwindow/createinvoice/CreateLuckyPacketPopupWindow.java +++ b/app/src/main/java/com/omni/wallet/view/popupwindow/createinvoice/CreateLuckyPacketPopupWindow.java @@ -553,7 +553,9 @@ public void onResponse(byte[] bytes) { @Override public void run() { updateInvoiceList(); - EventBus.getDefault().post(new PayInvoiceSuccessEvent()); + PayInvoiceSuccessEvent event = new PayInvoiceSuccessEvent(); + event.setTag(2); + EventBus.getDefault().post(event); mLoadingDialog.dismiss(); // updated the history, so it is shown the next time the user views it rootView.findViewById(R.id.lv_lucky_packet_step_one).setVisibility(View.GONE); @@ -607,7 +609,9 @@ public void run() { LogUtils.e(TAG, "------------------routerOB_SendPaymentV2OnResponse-----------------" + resp); if (resp.getStatus() == LightningOuterClass.Payment.PaymentStatus.SUCCEEDED) { updateInvoiceList(); - EventBus.getDefault().post(new PayInvoiceSuccessEvent()); + PayInvoiceSuccessEvent event = new PayInvoiceSuccessEvent(); + event.setTag(2); + EventBus.getDefault().post(event); mLoadingDialog.dismiss(); rootView.findViewById(R.id.lv_lucky_packet_step_one).setVisibility(View.GONE); rootView.findViewById(R.id.lv_lucky_packet_success).setVisibility(View.VISIBLE); @@ -694,7 +698,9 @@ public void run() { LogUtils.e(TAG, "------------------noRouterOB_SendPaymentV2OnResponse-----------------" + resp); if (resp.getStatus() == LightningOuterClass.Payment.PaymentStatus.SUCCEEDED) { updateInvoiceList(); - EventBus.getDefault().post(new PayInvoiceSuccessEvent()); + PayInvoiceSuccessEvent event = new PayInvoiceSuccessEvent(); + event.setTag(2); + EventBus.getDefault().post(event); mLoadingDialog.dismiss(); rootView.findViewById(R.id.lv_lucky_packet_step_one).setVisibility(View.GONE); rootView.findViewById(R.id.lv_lucky_packet_success).setVisibility(View.VISIBLE); diff --git a/app/src/main/proto/lightning.proto b/app/src/main/proto/lightning.proto index 9a0542e9..07317d5a 100644 --- a/app/src/main/proto/lightning.proto +++ b/app/src/main/proto/lightning.proto @@ -135,6 +135,7 @@ service Lightning { rpc SendCoins (SendCoinsRequest) returns (SendCoinsResponse); rpc OB_SendCoinsFrom (SendCoinsFromRequest) returns (SendCoinsResponse); + rpc OB_MintNft (MintNftRequest) returns (SendCoinsResponse); /* lncli: `listunspent` Deprecated, use walletrpc.ListUnspent instead. @@ -583,6 +584,9 @@ service Lightning { rpc SubscribeChannelBackups (ChannelBackupSubscription) returns (stream ChanBackupSnapshot); + rpc SubscribeChannelChange (ChannelBackupSubscription) + returns (stream SubscribeChannelChangeRes); + /* lncli: `bakemacaroon` BakeMacaroon allows the creation of a new macaroon with custom read and write permissions. No first-party caveats are added since this can be done @@ -1280,6 +1284,36 @@ message SendCoinsFromRequest { bool spend_unconfirmed = 9; } +message MintNftRequest { + // The address to send nft to + string addr = 1; + + // The target number of blocks that this transaction should be confirmed + // by. + int32 target_conf = 3; + + // A manual fee rate set in sat/vbyte that should be used when crafting the + // transaction. + uint64 sat_per_vbyte = 4; + + // Deprecated, use sat_per_vbyte. + // A manual fee rate set in sat/vbyte that should be used when crafting the + // transaction. + int64 sat_per_byte = 5 [deprecated = true]; + + // An optional label for the transaction, limited to 500 characters. + string label = 7; + + // The minimum number of confirmations each one of your outputs used for + // the transaction must satisfy. + int32 min_confs = 8; + + // Whether unconfirmed outputs should be used as inputs for the transaction. + bool spend_unconfirmed = 9; + + string nftFilePath = 10; +} + message SendCoinsRequest { // The address to send coins to string addr = 1; @@ -4330,6 +4364,9 @@ message ChanBackupSnapshot { */ MultiChanBackup multi_chan_backup = 2; } +message SubscribeChannelChangeRes { + string Res = 1; +} message ChannelBackups { /* diff --git a/config.gradle b/config.gradle index 9b2733df..6eb66ab7 100644 --- a/config.gradle +++ b/config.gradle @@ -6,8 +6,8 @@ ext { targetSdkVersion: 28, compileVersion : 28, buildToolVersion: "28.0.3", - versionCode : 3, - versionName : "0.1.2" + versionCode : 4, + versionName : "0.1.3" ] // 依赖相关版本控制 depVersion = [ diff --git a/framelibrary/src/main/java/com/omni/wallet/framelibrary/entity/User.java b/framelibrary/src/main/java/com/omni/wallet/framelibrary/entity/User.java index 63195f18..aee9ac87 100644 --- a/framelibrary/src/main/java/com/omni/wallet/framelibrary/entity/User.java +++ b/framelibrary/src/main/java/com/omni/wallet/framelibrary/entity/User.java @@ -114,6 +114,12 @@ public static User getInstance() { private boolean isBackUp; + private boolean isAutoBackUp; + + private String googleAccountName; + + private String googleAccountType; + public String getToken(Context context) { token = PreferencesUtils.getTokenFromLocal(context); return token; @@ -610,4 +616,33 @@ public void setBackUp(Context context, boolean isBackUp) { PreferencesUtils.saveBackUp(context, isBackUp); this.isBackUp = isBackUp; } + public boolean isAutoBackUp(Context context){ + isAutoBackUp = PreferencesUtils.getAutoBackUp(context); + return isAutoBackUp; + } + + public void setAutoBackUp(Context context, boolean isAutoBackUp) { + PreferencesUtils.saveAutoBackUp(context, isAutoBackUp); + this.isAutoBackUp = isAutoBackUp; + } + + public String getGoogleAccountName(Context context) { + googleAccountName = PreferencesUtils.getGoogleAccountNameFromLocal(context); + return googleAccountName; + } + + public void setGoogleAccountName(Context context, String googleAccountName) { + PreferencesUtils.saveGoogleAccountNameToLocal(context, googleAccountName); + this.googleAccountName = googleAccountName; + } + + public String getGoogleAccountType(Context context) { + googleAccountType = PreferencesUtils.getGoogleAccountTypeFromLocal(context); + return googleAccountType; + } + + public void setGoogleAccountType(Context context, String googleAccountType) { + PreferencesUtils.saveGoogleAccountTypeToLocal(context, googleAccountType); + this.googleAccountType = googleAccountType; + } } diff --git a/framelibrary/src/main/java/com/omni/wallet/framelibrary/utils/PreferencesUtils.java b/framelibrary/src/main/java/com/omni/wallet/framelibrary/utils/PreferencesUtils.java index f814cd9d..73766bd3 100644 --- a/framelibrary/src/main/java/com/omni/wallet/framelibrary/utils/PreferencesUtils.java +++ b/framelibrary/src/main/java/com/omni/wallet/framelibrary/utils/PreferencesUtils.java @@ -63,6 +63,9 @@ public class PreferencesUtils extends BasePreferencesUtils { private static final String WALLET_INFO_MOVED = "walletInfoMoved"; private static final String SEED_STRING_SECRETED = "seedStringSecreted"; private static final String KEY_BACKUP = "backupKey"; + private static final String KEY_AUTO_BACKUP = "autoBackupKey"; + private static final String KEY_GOOGLE_ACCOUNT_NAME = "googleAccountNameKey"; + private static final String KEY_GOOGLE_ACCOUNT_TYPE = "googleAccountTypeKey"; /** * 版本信息本地化 @@ -568,4 +571,28 @@ public static void saveBackUp(Context context, boolean value) { public static boolean getBackUp(Context context) { return getBoolean(SETTINGS,context,KEY_BACKUP); } + + public static void saveAutoBackUp(Context context, boolean value) { + putBoolean(SETTINGS, context, KEY_AUTO_BACKUP, value); + } + + public static boolean getAutoBackUp(Context context) { + return getBoolean(SETTINGS, context, KEY_AUTO_BACKUP); + } + + public static String getGoogleAccountNameFromLocal(Context context) { + return getString(SETTINGS, context, KEY_GOOGLE_ACCOUNT_NAME); + } + + public static void saveGoogleAccountNameToLocal(Context context, String value) { + putString(SETTINGS, context, KEY_GOOGLE_ACCOUNT_NAME, value); + } + + public static String getGoogleAccountTypeFromLocal(Context context) { + return getString(SETTINGS, context, KEY_GOOGLE_ACCOUNT_TYPE); + } + + public static void saveGoogleAccountTypeToLocal(Context context, String value) { + putString(SETTINGS, context, KEY_GOOGLE_ACCOUNT_TYPE, value); + } }