diff --git a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java
index 34fe7598..1cb43428 100755
--- a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java
+++ b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java
@@ -133,17 +133,12 @@ public void onError(final String[] error) {
torErrorGobbler.start();
torOutputGobbler.start();
- // allow to pass in a different datadir directory
-
- // HACK: if user sets a datadir in the bitcoin.conf file that should then be the one
- // used
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
final String useDistribution = prefs.getString("usedistribution", "core");
final String daemon = "liquid".equals(useDistribution) ? "liquidd" : "bitcoind";
final ProcessBuilder pb = new ProcessBuilder(
String.format("%s/%s", path, daemon),
"--server=1",
- String.format("--datadir=%s", Utils.getDataDir(this)),
String.format("--conf=%s", Utils.getBitcoinConf(this)));
pb.directory(new File(path));
diff --git a/app/src/main/java/com/greenaddress/abcore/BitcoinConfEditActivity.java b/app/src/main/java/com/greenaddress/abcore/BitcoinConfEditActivity.java
index f5015d84..e7fa6601 100755
--- a/app/src/main/java/com/greenaddress/abcore/BitcoinConfEditActivity.java
+++ b/app/src/main/java/com/greenaddress/abcore/BitcoinConfEditActivity.java
@@ -1,14 +1,10 @@
package com.greenaddress.abcore;
-import android.Manifest;
-import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
import org.apache.commons.compress.utils.IOUtils;
@@ -32,15 +28,6 @@ protected void onCreate(final Bundle savedInstanceState) {
@Override
protected void onPause() {
super.onPause();
- if (ContextCompat.checkSelfPermission(this,
- Manifest.permission.WRITE_EXTERNAL_STORAGE)
- != PackageManager.PERMISSION_GRANTED &&
- !ActivityCompat.shouldShowRequestPermissionRationale(this,
- Manifest.permission.WRITE_EXTERNAL_STORAGE))
- ActivityCompat.requestPermissions(this,
- new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- 0);
-
// save file
OutputStream f = null;
try {
diff --git a/app/src/main/java/com/greenaddress/abcore/MainActivity.java b/app/src/main/java/com/greenaddress/abcore/MainActivity.java
index e4d9377a..bfac060f 100755
--- a/app/src/main/java/com/greenaddress/abcore/MainActivity.java
+++ b/app/src/main/java/com/greenaddress/abcore/MainActivity.java
@@ -1,12 +1,15 @@
package com.greenaddress.abcore;
+import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Build;
@@ -25,24 +28,35 @@
import android.widget.TextView;
import android.widget.Toast;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
import com.google.zxing.WriterException;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.google.zxing.qrcode.encoder.ByteMatrix;
import com.google.zxing.qrcode.encoder.Encoder;
+import java.io.File;
+
public class MainActivity extends AppCompatActivity {
private final static String TAG = MainActivity.class.getName();
+
+ private final static int SCALE = 4;
+ private final static int STORAGE_PERMISSION_REQUEST = 0;
+
private RPCResponseReceiver mRpcResponseReceiver;
private TextView mTvStatus;
private Switch mSwitchCore;
private TextView mQrCodeText;
private ImageView mImageViewQr;
- private final static int SCALE = 4;
+
+
private boolean mSwitchOn = false;
private enum DaemonStatus {
UNKNOWN,
@@ -99,40 +113,6 @@ else if (mDaemonStatus == DaemonStatus.STARTING || mDaemonStatus == DaemonStatus
}
}
- private void stopDaemonAndSetStatus(){
- mSwitchOn = false;
- mDaemonStatus = DaemonStatus.STOPPING;
- mTvStatus.setText(getString(R.string.status_header, mDaemonStatus.toString()));
- mSwitchCore.setText(R.string.switchcoreon);
- final Intent i = new Intent(MainActivity.this, RPCIntentService.class);
- i.putExtra("stop", "yep");
- startService(i);
- }
-
- private void setSwitch() {
- mSwitchCore.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
- if (isChecked) {
- mSwitchOn = true;
- mDaemonStatus = DaemonStatus.STARTING;
- mTvStatus.setText(getString(R.string.status_header, mDaemonStatus.toString()));
- mSwitchCore.setText(R.string.switchcoreoff);
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
- final SharedPreferences.Editor e = prefs.edit();
- e.putBoolean("magicallystarted", false);
- e.apply();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- startForegroundService(new Intent(MainActivity.this, ABCoreService.class));
- } else {
- startService(new Intent(MainActivity.this, ABCoreService.class));
- }
- } else {
- stopDaemonAndSetStatus();
- }
- }
- });
- }
-
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -230,9 +210,107 @@ public boolean onOptionsItemSelected(final MenuItem item) {
}
}
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == STORAGE_PERMISSION_REQUEST) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ mSwitchCore.setChecked(true);
+ } else {
+ mSwitchCore.setChecked(false);
+ Toast.makeText(MainActivity.this, R.string.permission_required, Toast.LENGTH_LONG).show();
+ }
+ }
+ }
+
+ private void setSwitch() {
+ mSwitchCore.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
+ if (isChecked) {
+ if (checkPermissions()) {
+ checkDataDirExistsAndStart();
+ } else {
+ mSwitchCore.setChecked(false);
+ }
+ } else {
+ stopDaemonAndSetStatus();
+ }
+ }
+ });
+ }
+
+ private void startDaemonAndSetStatus() {
+ mSwitchOn = true;
+ mDaemonStatus = DaemonStatus.STARTING;
+ mTvStatus.setText(getString(R.string.status_header, mDaemonStatus.toString()));
+ mSwitchCore.setText(R.string.switchcoreoff);
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
+ final SharedPreferences.Editor e = prefs.edit();
+ e.putBoolean("magicallystarted", false);
+ e.apply();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ startForegroundService(new Intent(MainActivity.this, ABCoreService.class));
+ } else {
+ startService(new Intent(MainActivity.this, ABCoreService.class));
+ }
+ }
+
+ private void checkDataDirExistsAndStart() {
+ final File dataDirFile = new File(Utils.getDataDir(this));
+ if (dataDirFile.exists() && dataDirFile.isDirectory()) {
+ startDaemonAndSetStatus();
+ } else {
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.create_dir_dialog_title)
+ .setMessage(getString(R.string.create_dir_dialog_msg, dataDirFile.getAbsolutePath()))
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ if (dataDirFile.mkdirs()) {
+ startDaemonAndSetStatus();
+ } else {
+ Toast.makeText(MainActivity.this, R.string.create_dir_failed_msg, Toast.LENGTH_LONG).show();
+ mSwitchCore.setChecked(false);
+ }
+ }
+ })
+ .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ Toast.makeText(MainActivity.this, R.string.create_dir_failed_msg, Toast.LENGTH_LONG).show();
+ mSwitchCore.setChecked(false);
+ }
+ })
+ .create()
+ .show();
+ }
+ }
+
+ private void stopDaemonAndSetStatus(){
+ mSwitchOn = false;
+ mDaemonStatus = DaemonStatus.STOPPING;
+ mTvStatus.setText(getString(R.string.status_header, mDaemonStatus.toString()));
+ mSwitchCore.setText(R.string.switchcoreon);
+ final Intent i = new Intent(MainActivity.this, RPCIntentService.class);
+ i.putExtra("stop", "yep");
+ startService(i);
+ }
+
+ private boolean checkPermissions() {
+ final boolean isInternalStorage =
+ Utils.getDataDir(this).startsWith(getNoBackupFilesDir().getAbsolutePath());
+ final boolean hasStoragePermission =
+ ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
+
+ if (!isInternalStorage && !hasStoragePermission) {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSION_REQUEST);
+ return false;
+ }
+ return true;
+ }
+
public class RPCResponseReceiver extends BroadcastReceiver {
- public static final String ACTION_RESP =
- "com.greenaddress.intent.action.RPC_PROCESSED";
+ public static final String ACTION_RESP = "com.greenaddress.intent.action.RPC_PROCESSED";
@Override
public void onReceive(final Context context, final Intent intent) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f3a33592..49aa56cb 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -23,4 +23,10 @@
Switch ON
Switch OFF
Processed %1d%% (block height %2d)
+ Datadir in external folder requires storage permission.
+ Create Datadir
+ The specified data dir does not exist. Do you want to create it?\n%s
+ YES
+ NO
+ Datadir not created. Cannot start daemon.