Ich benutze die Bibliothek bitcoinj, um eine Android-Brieftasche zu erstellen. Der Fall ist, dass ich möchte, dass die Blockchain im Hintergrund heruntergeladen wird, so dass der Benutzer die anderen Funktionen der App nutzen kann. Wenn er jedoch den Download startet und eine neue Aktivität öffnet, friert die Anwendung ein und Sie können nichts mehr verwenden , nicht einmal zum vorherigen Bildschirm zurückkehren. Dies ist Teil des Codes:Android-Benutzeroberfläche einfrieren, wenn der Dienst Fortschritt herunterlädt
public class BitcoinService extends Service {
private final PeerDataEventListener blockchainDownloadListener = new AbstractPeerEventListener() {
private final long CALLBACK_TIME = 1000L;
private final AtomicLong lastMessageTime = new AtomicLong(0);
private int height;
private int blocksLeft;
private Block block;
@Override
public void onBlocksDownloaded(final Peer peer, final Block block, final FilteredBlock filteredBlock, final int blocksLeft) {
config.maybeIncrementBestChainHeightEver(blockChain.getChainHead().getHeight());
delayHandler.removeCallbacksAndMessages(null);
final long now = System.currentTimeMillis();
this.block = block;
this.height = (int) peer.getBestHeight() - blocksLeft;
this.blocksLeft = blocksLeft;
if (now - lastMessageTime.get() > CALLBACK_TIME) {
delayHandler.post(RUNNER);
} else {
delayHandler.postDelayed(RUNNER, CALLBACK_TIME);
}
}
private final Runnable RUNNER = new Runnable() {
@Override
public void run() {
notifyBlockchainProgress(height, (height + blocksLeft));
Log.e(TAG, "LAST_BLOCK=" + height + ", REMAINS=" + blocksLeft);
if (blocksLeft == 0) {
broadcastBlockchainDownloaded();
}
}
};
};
private final BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {
@SuppressLint("Wakelock")
@Override
public void onReceive(final Context context, final Intent intent) {
Log.d(TAG, "acquiring wakelock");
wakeLock.acquire();
// consistency check
final int walletLastBlockSeenHeight = wallet.getLastBlockSeenHeight();
final int bestChainHeight = blockChain.getBestChainHeight();
if (walletLastBlockSeenHeight != -1 && walletLastBlockSeenHeight != bestChainHeight) {
final String message = "wallet/blockchain out of sync: " + walletLastBlockSeenHeight + "/" + bestChainHeight;
Log.e(TAG, message);
}
Log.i(TAG, "starting peergroup");
peerGroup = new PeerGroup(Constants.WALLET.NETWORK_PARAMETERS, blockChain);
peerGroup.setDownloadTxDependencies(false);
peerGroup.setUserAgent("TestWallet", "0.0.1");
peerGroup.setMaxConnections(6);
peerGroup.setConnectTimeoutMillis(15000);
peerGroup.setPeerDiscoveryTimeoutMillis(10000);
// start peergroup
peerGroup.startAsync();
peerGroup.startBlockChainDownload(blockchainDownloadListener);
}
};
private final Handler delayHandler = new Handler();
private PeerGroup peerGroup;
private WakeLock wakeLock;
private PeerConnectivityListener peerConnectivityListener;
private NotificationManager nm;
private Configuration config;
private Wallet wallet;
@Override
public void onCreate() {
wallet = new Wallet(Constants.WALLET.NETWORK_PARAMETERS);
nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
final String lockName = getPackageName() + " blockchain sync";
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName);
config = Configuration.getInstance();
broadcastPeerState(0);
blockChainFile = Constants.WALLET.BLOCKCHAIN_FILE;
final boolean blockChainFileExists = blockChainFile.exists();
if (!blockChainFileExists) {
new File(Constants.WALLET.WALLET_PATH).mkdirs();
}
try {
blockStore = new SPVBlockStore(Constants.WALLET.NETWORK_PARAMETERS, blockChainFile);
blockStore.getChainHead(); // detect corruptions as early as possible
final long earliestKeyCreationTime = wallet.getEarliestKeyCreationTime();
if (!blockChainFileExists && earliestKeyCreationTime > 0){
try {
config.setDeletingBlockchain(true);
final long start = System.currentTimeMillis();
final InputStream checkpointsInputStream = getAssets().open("bitcoin/" + Constants.WALLET.CHECKPOINTS_FILENAME);
CheckpointManager.checkpoint(Constants.WALLET.NETWORK_PARAMETERS, checkpointsInputStream, blockStore, earliestKeyCreationTime);
Log.i(TAG, String.format("checkpoints loaded from '%1$s', took %2$dms", Constants.WALLET.CHECKPOINTS_FILENAME, System.currentTimeMillis() - start));
} catch (final IOException x) {
Log.e(TAG, "problem reading checkpoints, continuing without", x);
}
}
} catch (final BlockStoreException x) {
blockChainFile.delete();
final String msg = "blockstore cannot be created";
Log.e(TAG, msg, x);
}
try {
blockChain = new BlockChain(Constants.WALLET.NETWORK_PARAMETERS, walletHelper.getMainWallet(), blockStore);
} catch (final BlockStoreException x) {
throw new Error("blockchain cannot be created", x);
}
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
registerReceiver(connectivityReceiver, intentFilter); // implicitly start PeerGroup
}
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
Log.e(TAG, "onStartCommand");
...
return START_NOT_STICKY;
}
private void notifyBlockchainProgress(int progress, int max) {
boolean isCompleted = progress == max;
if (config.isDeletingBlockchain()) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
long percent = Math.round(Math.floor((progress * 100)/max));
mBuilder.setContentTitle("Blockchain download")
.setContentText(" Synchronization in progress - " + percent + "%")
.setSmallIcon(R.drawable.ic_logo_splash)
.setProgress(max, progress, false)
.setAutoCancel(false);
if (isCompleted) {
mBuilder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setProgress(0, 0, false)
.setAutoCancel(true)
.setContentText(getString(R.string.synchronization_completed));
config.setDeletingBlockchain(false);
}
Notification notif = mBuilder.build();
if (isCompleted) {
notif.flags = Notification.FLAG_FOREGROUND_SERVICE;
} else {
notif.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE;
}
nm.notify(2, notif);
}
}
public void broadcastBlockchainDownloaded() {
Intent i = new Intent(UiRefreshReceiver.REFRESH_UI);
LocalBroadcastManager.getInstance(this).sendBroadcast(i);
}
}
ich Teil des Codes des offiziellen Projektes des Android wallet verwendet
Überprüfen Sie diese: http://stackoverflow.com/questions/7875926/does-android-service-run-from-a-seperated-thread-instead-of-ui –
Foreground-Dienste auf dem UI-Thread ausgeführt. Jede E/A-gebundene Arbeit sollte mit AsyncTasks, neuen Threads (Senden von Nachrichten an Ihren Handler) oder (** beste Option **) RxJava erfolgen. –
Verwenden Sie IntentService zum Herunterladen –