Here are the examples of the java api android.app.LoaderManager taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
42 Examples
19
Source : ChangedContacts.java
with Apache License 2.0
from jiyouliang
with Apache License 2.0
from jiyouliang
private void changeClick() {
mChangeAdapter.swapCursor(null);
LoaderManager manager = getLoaderManager();
manager.destroyLoader(ID_DELETE_LOADER);
manager.restartLoader(ID_CHANGE_LOADER, null, this);
}
19
Source : ChangedContacts.java
with Apache License 2.0
from jiyouliang
with Apache License 2.0
from jiyouliang
private void deleteClick() {
mChangeAdapter.swapCursor(null);
LoaderManager manager = getLoaderManager();
manager.destroyLoader(ID_CHANGE_LOADER);
manager.restartLoader(ID_DELETE_LOADER, null, this);
}
19
Source : MediaPickerData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
public void init(final LoaderManager loaderManager) {
mLoaderManager = loaderManager;
}
18
Source : LoaderManagerSubject.java
with Apache License 2.0
from pkware
with Apache License 2.0
from pkware
/**
* Propositions for {@link LoaderManager} subjects.
*/
public clreplaced LoaderManagerSubject extends Subject {
@Nullable
private final LoaderManager actual;
public LoaderManagerSubject(@Nonnull FailureMetadata failureMetadata, @Nullable LoaderManager actual) {
super(failureMetadata, actual);
this.actual = actual;
}
public void hasLoader(int id) {
check("getLoader(id)").withMessage("Has loader with id <%s>", id).that(actual.getLoader(id)).isNotNull();
}
}
18
Source : LoaderQueryRunner.java
with Apache License 2.0
from androidx
with Apache License 2.0
from androidx
/**
* A {@link ContentPager.QueryRunner} that executes queries using a {@link LoaderManager}.
* Use this when preparing {@link ContentPager} to run in an Activity or Fragment scope.
*/
public final clreplaced LoaderQueryRunner implements ContentPager.QueryRunner {
private static final boolean DEBUG = false;
private static final String TAG = "LoaderQueryRunner";
@SuppressWarnings("WeakerAccess")
final Context /* synthetic access */
mContext;
@SuppressWarnings("WeakerAccess")
final LoaderManager /* synthetic access */
mLoaderMgr;
public LoaderQueryRunner(@NonNull Context context, @NonNull LoaderManager loaderMgr) {
mContext = context;
mLoaderMgr = loaderMgr;
}
@Override
@SuppressWarnings({ "unchecked", "deprecation" })
public void query(@NonNull final Query query, @NonNull final Callback callback) {
if (DEBUG)
Log.d(TAG, "Handling query: " + query);
android.app.LoaderManager.LoaderCallbacks<Cursor> callbacks = new android.app.LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
if (DEBUG)
Log.i(TAG, "Loading results for query: " + query);
checkArgument(id == query.getId(), "Id doesn't match query id.");
return new android.content.CursorLoader(mContext) {
@Override
public Cursor loadInBackground() {
return callback.runQueryInBackground(query);
}
};
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if (DEBUG)
Log.i(TAG, "Finished loading: " + query);
mLoaderMgr.destroyLoader(query.getId());
callback.onQueryFinished(query, cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
if (DEBUG)
Log.w(TAG, "Ignoring loader reset for query: " + query);
}
};
mLoaderMgr.restartLoader(query.getId(), null, callbacks);
}
@Override
public boolean isRunning(@NonNull Query query) {
Loader<Cursor> loader = mLoaderMgr.getLoader(query.getId());
return loader != null && loader.isStarted();
// Hmm, when exactly would the loader not be started? Does it imply that it will
// be starting at some point?
}
@Override
public void cancel(@NonNull Query query) {
mLoaderMgr.destroyLoader(query.getId());
}
}
18
Source : SettingsData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
/**
* Services SettingsFragment's data needs for loading active self participants to display
* the list of active subscriptions.
*/
public clreplaced SettingsData extends BindableData implements LoaderManager.LoaderCallbacks<Cursor> {
public interface SettingsDataListener {
void onSelfParticipantDataLoaded(SettingsData data);
}
public static clreplaced SettingsItem {
public static final int TYPE_GENERAL_SETTINGS = 1;
public static final int TYPE_PER_SUBSCRIPTION_SETTINGS = 2;
private final String mDisplayName;
private final String mDisplayDetail;
private final String mActivityreplacedle;
private final int mType;
private final int mSubId;
private SettingsItem(final String displayName, final String displayDetail, final String activityreplacedle, final int type, final int subId) {
mDisplayName = displayName;
mDisplayDetail = displayDetail;
mActivityreplacedle = activityreplacedle;
mType = type;
mSubId = subId;
}
public String getDisplayName() {
return mDisplayName;
}
public String getDisplayDetail() {
return mDisplayDetail;
}
public int getType() {
return mType;
}
public int getSubId() {
return mSubId;
}
public String getActivityreplacedle() {
return mActivityreplacedle;
}
public static SettingsItem fromSelfParticipant(final Context context, final ParticipantData self) {
replacedert.isTrue(self.isSelf());
replacedert.isTrue(self.isActiveSubscription());
final String displayDetail = TextUtils.isEmpty(self.getDisplayDestination()) ? context.getString(R.string.sim_settings_unknown_number) : self.getDisplayDestination();
final String displayName = context.getString(R.string.sim_specific_settings, self.getSubscriptionName());
return new SettingsItem(displayName, displayDetail, displayName, TYPE_PER_SUBSCRIPTION_SETTINGS, self.getSubId());
}
public static SettingsItem createGeneralSettingsItem(final Context context) {
return new SettingsItem(context.getString(R.string.general_settings), null, context.getString(R.string.general_settings_activity_replacedle), TYPE_GENERAL_SETTINGS, -1);
}
public static SettingsItem createDefaultMmsSettingsItem(final Context context, final int subId) {
return new SettingsItem(context.getString(R.string.advanced_settings), null, context.getString(R.string.advanced_settings_activity_replacedle), TYPE_PER_SUBSCRIPTION_SETTINGS, subId);
}
}
private static final String BINDING_ID = "bindingId";
private final Context mContext;
private final SelfParticipantsData mSelfParticipantsData;
private LoaderManager mLoaderManager;
private SettingsDataListener mListener;
public SettingsData(final Context context, final SettingsDataListener listener) {
mListener = listener;
mContext = context;
mSelfParticipantsData = new SelfParticipantsData();
}
private static final int SELF_PARTICIPANT_LOADER = 1;
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
replacedert.equals(SELF_PARTICIPANT_LOADER, id);
Loader<Cursor> loader = null;
final String bindingId = args.getString(BINDING_ID);
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
loader = new BoundCursorLoader(bindingId, mContext, MessagingContentProvider.PARTICIPANTS_URI, ParticipantData.ParticipantsQuery.PROJECTION, ParticipantColumns.SUB_ID + " <> ?", new String[] { String.valueOf(ParticipantData.OTHER_THAN_SELF_SUB_ID) }, null);
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Creating self loader after unbinding");
}
return loader;
}
@Override
public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
mSelfParticipantsData.bind(data);
mListener.onSelfParticipantDataLoaded(this);
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Self loader finished after unbinding");
}
}
@Override
public void onLoaderReset(final Loader<Cursor> generic) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
mSelfParticipantsData.bind(null);
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Self loader reset after unbinding");
}
}
public void init(final LoaderManager loaderManager, final BindingBase<SettingsData> binding) {
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(SELF_PARTICIPANT_LOADER, args, this);
}
@Override
protected void unregisterListeners() {
mListener = null;
// This could be null if we bind but the caller doesn't init the BindableData
if (mLoaderManager != null) {
mLoaderManager.destroyLoader(SELF_PARTICIPANT_LOADER);
mLoaderManager = null;
}
}
public List<SettingsItem> getSettingsItems() {
final List<ParticipantData> selfs = mSelfParticipantsData.getSelfParticipants(true);
final List<SettingsItem> settingsItems = new ArrayList<SettingsItem>();
// First goes the general settings, followed by per-subscription settings.
settingsItems.add(SettingsItem.createGeneralSettingsItem(mContext));
// For per-subscription settings, show the actual SIM name with phone number if the
// platorm is at least L-MR1 and there are multiple active SIMs.
final int activeSubCountExcludingDefault = mSelfParticipantsData.getSelfParticipantsCountExcludingDefault(true);
if (OsUtil.isAtLeastL_MR1() && activeSubCountExcludingDefault > 0) {
for (ParticipantData self : selfs) {
if (!self.isDefaultSelf()) {
if (activeSubCountExcludingDefault > 1) {
settingsItems.add(SettingsItem.fromSelfParticipant(mContext, self));
} else {
// This is the only active non-default SIM.
settingsItems.add(SettingsItem.createDefaultMmsSettingsItem(mContext, self.getSubId()));
break;
}
}
}
} else {
// Either pre-L-MR1, or there's no active SIM, so show the default MMS settings.
settingsItems.add(SettingsItem.createDefaultMmsSettingsItem(mContext, ParticipantData.DEFAULT_SELF_SUB_ID));
}
return settingsItems;
}
}
18
Source : PeopleAndOptionsData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
/**
* Services data needs for PeopleAndOptionsFragment.
*/
public clreplaced PeopleAndOptionsData extends BindableData implements LoaderManager.LoaderCallbacks<Cursor> {
public interface PeopleAndOptionsDataListener {
void onOptionsCursorUpdated(PeopleAndOptionsData data, Cursor cursor);
void onParticipantsListLoaded(PeopleAndOptionsData data, List<ParticipantData> participants);
}
private static final String BINDING_ID = "bindingId";
private final Context mContext;
private final String mConversationId;
private final ConversationParticipantsData mParticipantData;
private LoaderManager mLoaderManager;
private PeopleAndOptionsDataListener mListener;
public PeopleAndOptionsData(final String conversationId, final Context context, final PeopleAndOptionsDataListener listener) {
mListener = listener;
mContext = context;
mConversationId = conversationId;
mParticipantData = new ConversationParticipantsData();
}
private static final int CONVERSATION_OPTIONS_LOADER = 1;
private static final int PARTICIPANT_LOADER = 2;
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
final String bindingId = args.getString(BINDING_ID);
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
switch(id) {
case CONVERSATION_OPTIONS_LOADER:
{
final Uri uri = MessagingContentProvider.buildConversationMetadataUri(mConversationId);
return new BoundCursorLoader(bindingId, mContext, uri, PeopleOptionsItemData.PROJECTION, null, null, null);
}
case PARTICIPANT_LOADER:
{
final Uri uri = MessagingContentProvider.buildConversationParticipantsUri(mConversationId);
return new BoundCursorLoader(bindingId, mContext, uri, ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
}
default:
replacedert.fail("Unknown loader id for PeopleAndOptionsFragment!");
break;
}
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Loader created after unbinding PeopleAndOptionsFragment");
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
if (isBound(cursorLoader.getBindingId())) {
switch(loader.getId()) {
case CONVERSATION_OPTIONS_LOADER:
mListener.onOptionsCursorUpdated(this, data);
break;
case PARTICIPANT_LOADER:
mParticipantData.bind(data);
mListener.onParticipantsListLoaded(this, mParticipantData.getParticipantListExcludingSelf());
break;
default:
replacedert.fail("Unknown loader id for PeopleAndOptionsFragment!");
break;
}
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Loader finished after unbinding PeopleAndOptionsFragment");
}
}
/**
* {@inheritDoc}
*/
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
if (isBound(cursorLoader.getBindingId())) {
switch(loader.getId()) {
case CONVERSATION_OPTIONS_LOADER:
mListener.onOptionsCursorUpdated(this, null);
break;
case PARTICIPANT_LOADER:
mParticipantData.bind(null);
break;
default:
replacedert.fail("Unknown loader id for PeopleAndOptionsFragment!");
break;
}
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Loader reset after unbinding PeopleAndOptionsFragment");
}
}
public void init(final LoaderManager loaderManager, final BindingBase<PeopleAndOptionsData> binding) {
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(CONVERSATION_OPTIONS_LOADER, args, this);
mLoaderManager.initLoader(PARTICIPANT_LOADER, args, this);
}
@Override
protected void unregisterListeners() {
mListener = null;
// This could be null if we bind but the caller doesn't init the BindableData
if (mLoaderManager != null) {
mLoaderManager.destroyLoader(CONVERSATION_OPTIONS_LOADER);
mLoaderManager.destroyLoader(PARTICIPANT_LOADER);
mLoaderManager = null;
}
}
public void enableConversationNotifications(final BindingBase<PeopleAndOptionsData> binding, final boolean enable) {
final String bindingId = binding.getBindingId();
if (isBound(bindingId)) {
UpdateConversationOptionsAction.enableConversationNotifications(mConversationId, enable);
}
}
public void setConversationNotificationSound(final BindingBase<PeopleAndOptionsData> binding, final String ringtoneUri) {
final String bindingId = binding.getBindingId();
if (isBound(bindingId)) {
UpdateConversationOptionsAction.setConversationNotificationSound(mConversationId, ringtoneUri);
}
}
public void enableConversationNotificationVibration(final BindingBase<PeopleAndOptionsData> binding, final boolean enable) {
final String bindingId = binding.getBindingId();
if (isBound(bindingId)) {
UpdateConversationOptionsAction.enableVibrationForConversationNotification(mConversationId, enable);
}
}
public void setDestinationBlocked(final BindingBase<PeopleAndOptionsData> binding, final boolean blocked) {
final String bindingId = binding.getBindingId();
final ParticipantData participantData = mParticipantData.getOtherParticipant();
if (isBound(bindingId) && participantData != null) {
UpdateDestinationBlockedAction.updateDestinationBlocked(participantData.getNormalizedDestination(), blocked, mConversationId, BugleActionToasts.makeUpdateDestinationBlockedActionListener(mContext));
}
}
}
18
Source : MediaPickerData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
/**
* Services data needs for MediaPicker.
*/
public clreplaced MediaPickerData extends BindableData {
public interface MediaPickerDataListener {
void onMediaPickerDataUpdated(MediaPickerData mediaPickerData, Object data, int loaderId);
}
private static final String BINDING_ID = "bindingId";
private final Context mContext;
private LoaderManager mLoaderManager;
private final GalleryLoaderCallbacks mGalleryLoaderCallbacks;
private MediaPickerDataListener mListener;
public MediaPickerData(final Context context) {
mContext = context;
mGalleryLoaderCallbacks = new GalleryLoaderCallbacks();
}
public static final int GALLERY_MEDIA_LOADER = 1;
/**
* A trampoline clreplaced so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
*/
private clreplaced GalleryLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
final String bindingId = args.getString(BINDING_ID);
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
switch(id) {
case GALLERY_MEDIA_LOADER:
return new GalleryBoundCursorLoader(bindingId, mContext);
default:
replacedert.fail("Unknown loader id for gallery picker!");
break;
}
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Loader created after unbinding the media picker");
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
if (isBound(cursorLoader.getBindingId())) {
switch(loader.getId()) {
case GALLERY_MEDIA_LOADER:
mListener.onMediaPickerDataUpdated(MediaPickerData.this, data, GALLERY_MEDIA_LOADER);
break;
default:
replacedert.fail("Unknown loader id for gallery picker!");
break;
}
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Loader finished after unbinding the media picker");
}
}
/**
* {@inheritDoc}
*/
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
if (isBound(cursorLoader.getBindingId())) {
switch(loader.getId()) {
case GALLERY_MEDIA_LOADER:
mListener.onMediaPickerDataUpdated(MediaPickerData.this, null, GALLERY_MEDIA_LOADER);
break;
default:
replacedert.fail("Unknown loader id for media picker!");
break;
}
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Loader reset after unbinding the media picker");
}
}
}
public void startLoader(final int loaderId, final BindingBase<MediaPickerData> binding, @Nullable Bundle args, final MediaPickerDataListener listener) {
if (args == null) {
args = new Bundle();
}
args.putString(BINDING_ID, binding.getBindingId());
if (loaderId == GALLERY_MEDIA_LOADER) {
mLoaderManager.initLoader(loaderId, args, mGalleryLoaderCallbacks).forceLoad();
} else {
replacedert.fail("Unsupported loader id for media picker!");
}
mListener = listener;
}
public void destroyLoader(final int loaderId) {
mLoaderManager.destroyLoader(loaderId);
}
public void init(final LoaderManager loaderManager) {
mLoaderManager = loaderManager;
}
@Override
protected void unregisterListeners() {
// This could be null if we bind but the caller doesn't init the BindableData
if (mLoaderManager != null) {
mLoaderManager.destroyLoader(GALLERY_MEDIA_LOADER);
mLoaderManager = null;
}
}
/**
* Gets the last selected chooser index, or -1 if no selection has been saved.
*/
public int getSelectedChooserIndex() {
return BuglePrefs.getApplicationPrefs().getInt(BuglePrefsKeys.SELECTED_MEDIA_PICKER_CHOOSER_INDEX, BuglePrefsKeys.SELECTED_MEDIA_PICKER_CHOOSER_INDEX_DEFAULT);
}
/**
* Saves the selected media chooser index.
* @param selectedIndex the selected media chooser index.
*/
public void saveSelectedChooserIndex(final int selectedIndex) {
BuglePrefs.getApplicationPrefs().putInt(BuglePrefsKeys.SELECTED_MEDIA_PICKER_CHOOSER_INDEX, selectedIndex);
}
}
18
Source : ConversationData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
public clreplaced ConversationData extends BindableData {
private static final String TAG = "bugle_datamodel";
private static final String BINDING_ID = "bindingId";
private static final long LAST_MESSAGE_TIMESTAMP_NaN = -1;
private static final int MESSAGE_COUNT_NaN = -1;
/**
* Takes a conversation id and a list of message ids and computes the positions
* for each message.
*/
public List<Integer> getPositions(final String conversationId, final List<Long> ids) {
final ArrayList<Integer> result = new ArrayList<Integer>();
if (ids.isEmpty()) {
return result;
}
final Cursor c = new ConversationData.ReversedCursor(DataModel.get().getDatabase().rawQuery(ConversationMessageData.getConversationMessageIdsQuerySql(), new String[] { conversationId }));
if (c != null) {
try {
final Set<Long> idsSet = new HashSet<Long>(ids);
if (c.moveToLast()) {
do {
final long messageId = c.getLong(0);
if (idsSet.contains(messageId)) {
result.add(c.getPosition());
}
} while (c.moveToPrevious());
}
} finally {
c.close();
}
}
Collections.sort(result);
return result;
}
public interface ConversationDataListener {
public void onConversationMessagesCursorUpdated(ConversationData data, Cursor cursor, @Nullable ConversationMessageData newestMessage, boolean isSync);
public void onConversationMetadataUpdated(ConversationData data);
public void closeConversation(String conversationId);
public void onConversationParticipantDataLoaded(ConversationData data);
public void onSubscriptionListDataLoaded(ConversationData data);
}
private static clreplaced ReversedCursor extends CursorWrapper {
final int mCount;
public ReversedCursor(final Cursor cursor) {
super(cursor);
mCount = cursor.getCount();
}
@Override
public boolean moveToPosition(final int position) {
return super.moveToPosition(mCount - position - 1);
}
@Override
public int getPosition() {
return mCount - super.getPosition() - 1;
}
@Override
public boolean isAfterLast() {
return super.isBeforeFirst();
}
@Override
public boolean isBeforeFirst() {
return super.isAfterLast();
}
@Override
public boolean isFirst() {
return super.isLast();
}
@Override
public boolean isLast() {
return super.isFirst();
}
@Override
public boolean move(final int offset) {
return super.move(-offset);
}
@Override
public boolean moveToFirst() {
return super.moveToLast();
}
@Override
public boolean moveToLast() {
return super.moveToFirst();
}
@Override
public boolean moveToNext() {
return super.moveToPrevious();
}
@Override
public boolean moveToPrevious() {
return super.moveToNext();
}
}
/**
* A trampoline clreplaced so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
*/
private clreplaced MetadataLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
replacedert.equals(CONVERSATION_META_DATA_LOADER, id);
Loader<Cursor> loader = null;
final String bindingId = args.getString(BINDING_ID);
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
final Uri uri = MessagingContentProvider.buildConversationMetadataUri(mConversationId);
loader = new BoundCursorLoader(bindingId, mContext, uri, ConversationLisreplacedemData.PROJECTION, null, null, null);
} else {
LogUtil.w(TAG, "Creating messages loader after unbinding mConversationId = " + mConversationId);
}
return loader;
}
@Override
public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
if (data.moveToNext()) {
replacedert.isTrue(data.getCount() == 1);
mConversationMetadata.bind(data);
mListeners.onConversationMetadataUpdated(ConversationData.this);
} else {
// Close the conversation, no meta data means conversation was deleted
LogUtil.w(TAG, "Meta data loader returned nothing for mConversationId = " + mConversationId);
mListeners.closeConversation(mConversationId);
// Notify the widget the conversation is deleted so it can go into its
// configure state.
WidgetConversationProvider.notifyConversationDeleted(Factory.get().getApplicationContext(), mConversationId);
}
} else {
LogUtil.w(TAG, "Meta data loader finished after unbinding mConversationId = " + mConversationId);
}
}
@Override
public void onLoaderReset(final Loader<Cursor> generic) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
// Clear the conversation meta data
mConversationMetadata = new ConversationLisreplacedemData();
mListeners.onConversationMetadataUpdated(ConversationData.this);
} else {
LogUtil.w(TAG, "Meta data loader reset after unbinding mConversationId = " + mConversationId);
}
}
}
/**
* A trampoline clreplaced so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
*/
private clreplaced MessagesLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
replacedert.equals(CONVERSATION_MESSAGES_LOADER, id);
Loader<Cursor> loader = null;
final String bindingId = args.getString(BINDING_ID);
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
final Uri uri = MessagingContentProvider.buildConversationMessagesUri(mConversationId);
loader = new BoundCursorLoader(bindingId, mContext, uri, ConversationMessageData.getProjection(), null, null, null);
mLastMessageTimestamp = LAST_MESSAGE_TIMESTAMP_NaN;
mMessageCount = MESSAGE_COUNT_NaN;
} else {
LogUtil.w(TAG, "Creating messages loader after unbinding mConversationId = " + mConversationId);
}
return loader;
}
@Override
public void onLoadFinished(final Loader<Cursor> generic, final Cursor rawData) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
// Check if we have a new message, or if we had a message sync.
ConversationMessageData newMessage = null;
boolean isSync = false;
Cursor data = null;
if (rawData != null) {
// Note that the cursor is sorted DESC so here we reverse it.
// This is a performance issue (improvement) for large cursors.
data = new ReversedCursor(rawData);
final int messageCountOld = mMessageCount;
mMessageCount = data.getCount();
final ConversationMessageData lastMessage = getLastMessage(data);
if (lastMessage != null) {
final long lastMessageTimestampOld = mLastMessageTimestamp;
mLastMessageTimestamp = lastMessage.getReceivedTimeStamp();
final String lastMessageIdOld = mLastMessageId;
mLastMessageId = lastMessage.getMessageId();
if (TextUtils.equals(lastMessageIdOld, mLastMessageId) && messageCountOld < mMessageCount) {
// Last message stays the same (no incoming message) but message
// count increased, which means there has been a message sync.
isSync = true;
} else if (// Ignore initial load
messageCountOld != MESSAGE_COUNT_NaN && mLastMessageTimestamp != LAST_MESSAGE_TIMESTAMP_NaN && mLastMessageTimestamp > lastMessageTimestampOld) {
newMessage = lastMessage;
}
} else {
mLastMessageTimestamp = LAST_MESSAGE_TIMESTAMP_NaN;
}
} else {
mMessageCount = MESSAGE_COUNT_NaN;
}
mListeners.onConversationMessagesCursorUpdated(ConversationData.this, data, newMessage, isSync);
} else {
LogUtil.w(TAG, "Messages loader finished after unbinding mConversationId = " + mConversationId);
}
}
@Override
public void onLoaderReset(final Loader<Cursor> generic) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
mListeners.onConversationMessagesCursorUpdated(ConversationData.this, null, null, false);
mLastMessageTimestamp = LAST_MESSAGE_TIMESTAMP_NaN;
mMessageCount = MESSAGE_COUNT_NaN;
} else {
LogUtil.w(TAG, "Messages loader reset after unbinding mConversationId = " + mConversationId);
}
}
private ConversationMessageData getLastMessage(final Cursor cursor) {
if (cursor != null && cursor.getCount() > 0) {
final int position = cursor.getPosition();
if (cursor.moveToLast()) {
final ConversationMessageData messageData = new ConversationMessageData();
messageData.bind(cursor);
cursor.move(position);
return messageData;
}
}
return null;
}
}
/**
* A trampoline clreplaced so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
*/
private clreplaced ParticipantLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
replacedert.equals(PARTICIPANT_LOADER, id);
Loader<Cursor> loader = null;
final String bindingId = args.getString(BINDING_ID);
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
final Uri uri = MessagingContentProvider.buildConversationParticipantsUri(mConversationId);
loader = new BoundCursorLoader(bindingId, mContext, uri, ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
} else {
LogUtil.w(TAG, "Creating participant loader after unbinding mConversationId = " + mConversationId);
}
return loader;
}
@Override
public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
mParticipantData.bind(data);
mListeners.onConversationParticipantDataLoaded(ConversationData.this);
} else {
LogUtil.w(TAG, "Participant loader finished after unbinding mConversationId = " + mConversationId);
}
}
@Override
public void onLoaderReset(final Loader<Cursor> generic) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
mParticipantData.bind(null);
} else {
LogUtil.w(TAG, "Participant loader reset after unbinding mConversationId = " + mConversationId);
}
}
}
/**
* A trampoline clreplaced so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
*/
private clreplaced SelfParticipantLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
replacedert.equals(SELF_PARTICIPANT_LOADER, id);
Loader<Cursor> loader = null;
final String bindingId = args.getString(BINDING_ID);
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
loader = new BoundCursorLoader(bindingId, mContext, MessagingContentProvider.PARTICIPANTS_URI, ParticipantData.ParticipantsQuery.PROJECTION, ParticipantColumns.SUB_ID + " <> ?", new String[] { String.valueOf(ParticipantData.OTHER_THAN_SELF_SUB_ID) }, null);
} else {
LogUtil.w(TAG, "Creating self loader after unbinding mConversationId = " + mConversationId);
}
return loader;
}
@Override
public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
mSelfParticipantsData.bind(data);
mSubscriptionListData.bind(mSelfParticipantsData.getSelfParticipants(true));
mListeners.onSubscriptionListDataLoaded(ConversationData.this);
} else {
LogUtil.w(TAG, "Self loader finished after unbinding mConversationId = " + mConversationId);
}
}
@Override
public void onLoaderReset(final Loader<Cursor> generic) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
// Check if data still bound to the requesting ui element
if (isBound(loader.getBindingId())) {
mSelfParticipantsData.bind(null);
} else {
LogUtil.w(TAG, "Self loader reset after unbinding mConversationId = " + mConversationId);
}
}
}
private final ConversationDataEventDispatcher mListeners;
private final MetadataLoaderCallbacks mMetadataLoaderCallbacks;
private final MessagesLoaderCallbacks mMessagesLoaderCallbacks;
private final ParticipantLoaderCallbacks mParticipantsLoaderCallbacks;
private final SelfParticipantLoaderCallbacks mSelfParticipantLoaderCallbacks;
private final Context mContext;
private final String mConversationId;
private final ConversationParticipantsData mParticipantData;
private final SelfParticipantsData mSelfParticipantsData;
private ConversationLisreplacedemData mConversationMetadata;
private final SubscriptionListData mSubscriptionListData;
private LoaderManager mLoaderManager;
private long mLastMessageTimestamp = LAST_MESSAGE_TIMESTAMP_NaN;
private int mMessageCount = MESSAGE_COUNT_NaN;
private String mLastMessageId;
public ConversationData(final Context context, final ConversationDataListener listener, final String conversationId) {
replacedert.isTrue(conversationId != null);
mContext = context;
mConversationId = conversationId;
mMetadataLoaderCallbacks = new MetadataLoaderCallbacks();
mMessagesLoaderCallbacks = new MessagesLoaderCallbacks();
mParticipantsLoaderCallbacks = new ParticipantLoaderCallbacks();
mSelfParticipantLoaderCallbacks = new SelfParticipantLoaderCallbacks();
mParticipantData = new ConversationParticipantsData();
mConversationMetadata = new ConversationLisreplacedemData();
mSelfParticipantsData = new SelfParticipantsData();
mSubscriptionListData = new SubscriptionListData(context);
mListeners = new ConversationDataEventDispatcher();
mListeners.add(listener);
}
@RunsOnMainThread
public void addConversationDataListener(final ConversationDataListener listener) {
replacedert.isMainThread();
mListeners.add(listener);
}
public String getConversationName() {
return mConversationMetadata.getName();
}
public boolean getIsArchived() {
return mConversationMetadata.getIsArchived();
}
public String getIcon() {
return mConversationMetadata.getIcon();
}
public String getConversationId() {
return mConversationId;
}
public void setFocus() {
DataModel.get().setFocusedConversation(mConversationId);
// As we are loading the conversation replacedume the user has read the messages...
// Do this late though so that it doesn't get in the way of other actions
BugleNotifications.markMessagesAsRead(mConversationId);
}
public void unsetFocus() {
DataModel.get().setFocusedConversation(null);
}
public boolean isFocused() {
return isBound() && DataModel.get().isFocusedConversation(mConversationId);
}
private static final int CONVERSATION_META_DATA_LOADER = 1;
private static final int CONVERSATION_MESSAGES_LOADER = 2;
private static final int PARTICIPANT_LOADER = 3;
private static final int SELF_PARTICIPANT_LOADER = 4;
public void init(final LoaderManager loaderManager, final BindingBase<ConversationData> binding) {
// Remember the binding id so that loader callbacks can check if data is still bound
// to same ui component
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(CONVERSATION_META_DATA_LOADER, args, mMetadataLoaderCallbacks);
mLoaderManager.initLoader(CONVERSATION_MESSAGES_LOADER, args, mMessagesLoaderCallbacks);
mLoaderManager.initLoader(PARTICIPANT_LOADER, args, mParticipantsLoaderCallbacks);
mLoaderManager.initLoader(SELF_PARTICIPANT_LOADER, args, mSelfParticipantLoaderCallbacks);
}
@Override
protected void unregisterListeners() {
mListeners.clear();
// Make sure focus has moved away from this conversation
// TODO: May false trigger if destroy happens after "new" conversation is focused.
// replacedert.isTrue(!DataModel.get().isFocusedConversation(mConversationId));
// This could be null if we bind but the caller doesn't init the BindableData
if (mLoaderManager != null) {
mLoaderManager.destroyLoader(CONVERSATION_META_DATA_LOADER);
mLoaderManager.destroyLoader(CONVERSATION_MESSAGES_LOADER);
mLoaderManager.destroyLoader(PARTICIPANT_LOADER);
mLoaderManager.destroyLoader(SELF_PARTICIPANT_LOADER);
mLoaderManager = null;
}
}
/**
* Gets the default self participant in the participant table (NOT the conversation's self).
* This is available as soon as self participant data is loaded.
*/
public ParticipantData getDefaultSelfParticipant() {
return mSelfParticipantsData.getDefaultSelfParticipant();
}
public List<ParticipantData> getSelfParticipants(final boolean activeOnly) {
return mSelfParticipantsData.getSelfParticipants(activeOnly);
}
public int getSelfParticipantsCountExcludingDefault(final boolean activeOnly) {
return mSelfParticipantsData.getSelfParticipantsCountExcludingDefault(activeOnly);
}
public ParticipantData getSelfParticipantById(final String selfId) {
return mSelfParticipantsData.getSelfParticipantById(selfId);
}
/**
* For a 1:1 conversation return the other (not self) participant (else null)
*/
public ParticipantData getOtherParticipant() {
return mParticipantData.getOtherParticipant();
}
/**
* Return true once the participants are loaded
*/
public boolean getParticipantsLoaded() {
return mParticipantData.isLoaded();
}
public void sendMessage(final BindingBase<ConversationData> binding, final MessageData message) {
replacedert.isTrue(TextUtils.equals(mConversationId, message.getConversationId()));
replacedert.isTrue(binding.getData() == this);
if (!OsUtil.isAtLeastL_MR1() || message.getSelfId() == null) {
InsertNewMessageAction.insertNewMessage(message);
} else {
final int systemDefaultSubId = PhoneUtils.getDefault().getDefaultSmsSubscriptionId();
if (systemDefaultSubId != ParticipantData.DEFAULT_SELF_SUB_ID && mSelfParticipantsData.isDefaultSelf(message.getSelfId())) {
// Lock the sub selection to the system default SIM as soon as the user clicks on
// the send button to avoid races between this and when InsertNewMessageAction is
// actually executed on the data model thread, during which the user can potentially
// change the system default SIM in Settings.
InsertNewMessageAction.insertNewMessage(message, systemDefaultSubId);
} else {
InsertNewMessageAction.insertNewMessage(message);
}
}
// Update contacts so Frequents will reflect messaging activity.
if (!getParticipantsLoaded()) {
// oh well, not critical
return;
}
final ArrayList<String> phones = new ArrayList<>();
final ArrayList<String> emails = new ArrayList<>();
for (final ParticipantData participant : mParticipantData) {
if (!participant.isSelf()) {
if (participant.isEmail()) {
emails.add(participant.getSendDestination());
} else {
phones.add(participant.getSendDestination());
}
}
}
if (ContactUtil.hasReadContactsPermission()) {
SafeAsyncTask.executeOnThreadPool(new Runnable() {
@Override
public void run() {
final DataUsageStatUpdater updater = new DataUsageStatUpdater(Factory.get().getApplicationContext());
try {
if (!phones.isEmpty()) {
updater.updateWithPhoneNumber(phones);
}
if (!emails.isEmpty()) {
updater.updateWithAddress(emails);
}
} catch (final SQLiteFullException ex) {
LogUtil.w(TAG, "Unable to update contact", ex);
}
}
});
}
}
public void downloadMessage(final BindingBase<ConversationData> binding, final String messageId) {
replacedert.isTrue(binding.getData() == this);
replacedert.notNull(messageId);
RedownloadMmsAction.redownloadMessage(messageId);
}
public void resendMessage(final BindingBase<ConversationData> binding, final String messageId) {
replacedert.isTrue(binding.getData() == this);
replacedert.notNull(messageId);
ResendMessageAction.resendMessage(messageId);
}
public void deleteMessage(final BindingBase<ConversationData> binding, final String messageId) {
replacedert.isTrue(binding.getData() == this);
replacedert.notNull(messageId);
DeleteMessageAction.deleteMessage(messageId);
}
public void deleteConversation(final Binding<ConversationData> binding) {
replacedert.isTrue(binding.getData() == this);
// If possible use timestamp of last message shown to delete only messages user is aware of
if (mConversationMetadata == null) {
DeleteConversationAction.deleteConversation(mConversationId, System.currentTimeMillis());
} else {
mConversationMetadata.deleteConversation();
}
}
public void archiveConversation(final BindingBase<ConversationData> binding) {
replacedert.isTrue(binding.getData() == this);
UpdateConversationArchiveStatusAction.archiveConversation(mConversationId);
}
public void unarchiveConversation(final BindingBase<ConversationData> binding) {
replacedert.isTrue(binding.getData() == this);
UpdateConversationArchiveStatusAction.unarchiveConversation(mConversationId);
}
public ConversationParticipantsData getParticipants() {
return mParticipantData;
}
/**
* Returns a dialable phone number for the participant if we are in a 1-1 conversation.
* @return the participant phone number, or null if the phone number is not valid or if there
* are more than one participant.
*/
public String getParticipantPhoneNumber() {
final ParticipantData participant = this.getOtherParticipant();
if (participant != null) {
final String phoneNumber = participant.getSendDestination();
if (!TextUtils.isEmpty(phoneNumber) && MmsSmsUtils.isPhoneNumber(phoneNumber)) {
return phoneNumber;
}
}
return null;
}
/**
* Create a message to be forwarded from an existing message.
*/
public MessageData createForwardedMessage(final ConversationMessageData message) {
final MessageData forwardedMessage = new MessageData();
final String originalSubject = MmsUtils.cleanseMmsSubject(mContext.getResources(), message.getMmsSubject());
if (!TextUtils.isEmpty(originalSubject)) {
forwardedMessage.setMmsSubject(mContext.getResources().getString(R.string.message_fwd, originalSubject));
}
for (final MessagePartData part : message.getParts()) {
MessagePartData forwardedPart;
// Depending on the part type, if it is text, we can directly create a text part;
// if it is attachment, then we need to create a pending attachment data out of it, so
// that we may persist the attachment locally in the scratch folder when the user picks
// a conversation to forward to.
if (part.isText()) {
forwardedPart = MessagePartData.createTextMessagePart(part.getText());
} else {
final PendingAttachmentData pendingAttachmentData = PendingAttachmentData.createPendingAttachmentData(part.getContentType(), part.getContentUri());
forwardedPart = pendingAttachmentData;
}
forwardedMessage.addPart(forwardedPart);
}
return forwardedMessage;
}
public int getNumberOfParticipantsExcludingSelf() {
return mParticipantData.getNumberOfParticipantsExcludingSelf();
}
/**
* Returns {@link com.android.messaging.datamodel.data.SubscriptionListData
* .SubscriptionListEntry} for a given self participant so UI can display SIM-related info
* (icon, name etc.) for multi-SIM.
*/
public SubscriptionListEntry getSubscriptionEntryForSelfParticipant(final String selfParticipantId, final boolean excludeDefault) {
return getSubscriptionEntryForSelfParticipant(selfParticipantId, excludeDefault, mSubscriptionListData, mSelfParticipantsData);
}
/**
* Returns {@link com.android.messaging.datamodel.data.SubscriptionListData
* .SubscriptionListEntry} for a given self participant so UI can display SIM-related info
* (icon, name etc.) for multi-SIM.
*/
public static SubscriptionListEntry getSubscriptionEntryForSelfParticipant(final String selfParticipantId, final boolean excludeDefault, final SubscriptionListData subscriptionListData, final SelfParticipantsData selfParticipantsData) {
// SIM indicators are shown in the UI only if:
// 1. Framework has MSIM support AND
// 2. The device has had multiple *active* subscriptions. AND
// 3. The message's subscription is active.
if (OsUtil.isAtLeastL_MR1() && selfParticipantsData.getSelfParticipantsCountExcludingDefault(true) > 1) {
return subscriptionListData.getActiveSubscriptionEntryBySelfId(selfParticipantId, excludeDefault);
}
return null;
}
public SubscriptionListData getSubscriptionListData() {
return mSubscriptionListData;
}
/**
* A dummy implementation of {@link ConversationDataListener} so that subclreplacedes may opt to
* implement some, but not all, of the interface methods.
*/
public static clreplaced SimpleConversationDataListener implements ConversationDataListener {
@Override
public void onConversationMessagesCursorUpdated(final ConversationData data, final Cursor cursor, @Nullable final ConversationMessageData newestMessage, final boolean isSync) {
}
@Override
public void onConversationMetadataUpdated(final ConversationData data) {
}
@Override
public void closeConversation(final String conversationId) {
}
@Override
public void onConversationParticipantDataLoaded(final ConversationData data) {
}
@Override
public void onSubscriptionListDataLoaded(final ConversationData data) {
}
}
private clreplaced ConversationDataEventDispatcher extends ArrayList<ConversationDataListener> implements ConversationDataListener {
@Override
public void onConversationMessagesCursorUpdated(final ConversationData data, final Cursor cursor, @Nullable final ConversationMessageData newestMessage, final boolean isSync) {
for (final ConversationDataListener listener : this) {
listener.onConversationMessagesCursorUpdated(data, cursor, newestMessage, isSync);
}
}
@Override
public void onConversationMetadataUpdated(final ConversationData data) {
for (final ConversationDataListener listener : this) {
listener.onConversationMetadataUpdated(data);
}
}
@Override
public void closeConversation(final String conversationId) {
for (final ConversationDataListener listener : this) {
listener.closeConversation(conversationId);
}
}
@Override
public void onConversationParticipantDataLoaded(final ConversationData data) {
for (final ConversationDataListener listener : this) {
listener.onConversationParticipantDataLoaded(data);
}
}
@Override
public void onSubscriptionListDataLoaded(final ConversationData data) {
for (final ConversationDataListener listener : this) {
listener.onSubscriptionListDataLoaded(data);
}
}
}
}
18
Source : BlockedParticipantsData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
/**
* Services data needs for BlockedParticipantsFragment
*/
public clreplaced BlockedParticipantsData extends BindableData implements LoaderManager.LoaderCallbacks<Cursor> {
public interface BlockedParticipantsDataListener {
public void onBlockedParticipantsCursorUpdated(final Cursor cursor);
}
private static final String BINDING_ID = "bindingId";
private static final int BLOCKED_PARTICIPANTS_LOADER = 1;
private final Context mContext;
private LoaderManager mLoaderManager;
private BlockedParticipantsDataListener mListener;
public BlockedParticipantsData(final Context context, final BlockedParticipantsDataListener listener) {
mContext = context;
mListener = listener;
}
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
replacedert.isTrue(id == BLOCKED_PARTICIPANTS_LOADER);
final String bindingId = args.getString(BINDING_ID);
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
final Uri uri = MessagingContentProvider.PARTICIPANTS_URI;
return new BoundCursorLoader(bindingId, mContext, uri, ParticipantData.ParticipantsQuery.PROJECTION, ParticipantColumns.BLOCKED + "=1", null, null);
}
return null;
}
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor cursor) {
replacedert.isTrue(loader.getId() == BLOCKED_PARTICIPANTS_LOADER);
final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
replacedert.isTrue(isBound(cursorLoader.getBindingId()));
mListener.onBlockedParticipantsCursorUpdated(cursor);
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
replacedert.isTrue(loader.getId() == BLOCKED_PARTICIPANTS_LOADER);
final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
replacedert.isTrue(isBound(cursorLoader.getBindingId()));
mListener.onBlockedParticipantsCursorUpdated(null);
}
public void init(final LoaderManager loaderManager, final BindingBase<BlockedParticipantsData> binding) {
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(BLOCKED_PARTICIPANTS_LOADER, args, this);
}
@Override
protected void unregisterListeners() {
mListener = null;
if (mLoaderManager != null) {
mLoaderManager.destroyLoader(BLOCKED_PARTICIPANTS_LOADER);
mLoaderManager = null;
}
}
public ParticipantLisreplacedemData createParticipantLisreplacedemData(Cursor cursor) {
return new ParticipantLisreplacedemData(ParticipantData.getFromCursor(cursor));
}
}
18
Source : BaseLoader.java
with Apache License 2.0
from akhasoft
with Apache License 2.0
from akhasoft
/**
* Destroys loaders.
*
* @param loaderManager
* The loader manager
*
* @param loaderIds
* The list of loaders to destroy
*/
@SuppressWarnings("WeakerAccess")
public static void destroyLoaders(final LoaderManager loaderManager, final Collection<Integer> loaderIds) {
if (loaderManager == null) {
CoreLogger.logError("loaderManager == null");
return;
}
if (loaderIds == null) {
CoreLogger.logError("loaderIds == null");
return;
}
CoreLogger.log("loader ids qty " + loaderIds.size());
int qty = 0;
for (final int i : loaderIds) if (destroyLoader(loaderManager, i))
qty++;
CoreLogger.log(qty + " loader" + (qty != 1 ? "s" : "") + " destroyed");
}
17
Source : ImageModel.java
with GNU General Public License v3.0
from VideoOS
with GNU General Public License v3.0
from VideoOS
/**
* Created by mac on 18/2/24.
*/
public clreplaced ImageModel implements LoaderManager.LoaderCallbacks<Cursor> {
private static final int LOADER_ID = 2;
private static final String ARGS_ALBUM = "args_album";
private WeakReference<Context> mContext;
private LoaderManager mLoaderManager;
private IImageMediaCallback mCallbacks;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Context context = mContext.get();
if (context == null) {
return null;
}
ImageFolderBean imageFolderBean = args.getParcelable(ARGS_ALBUM);
if (imageFolderBean == null) {
VenvyLog.i("--imageFolderBean is null--");
return null;
}
return ImageScanner.newInstance(context, imageFolderBean);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
Context context = mContext.get();
if (context == null) {
return;
}
mCallbacks.onImageLoad(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
Context context = mContext.get();
if (context == null) {
return;
}
mCallbacks.onImageReset();
}
public void onCreate(@NonNull Context context, @NonNull IImageMediaCallback callbacks) {
mContext = new WeakReference<Context>(context);
mLoaderManager = ((Activity) context).getLoaderManager();
mCallbacks = callbacks;
}
public void onDestroy() {
mLoaderManager.destroyLoader(LOADER_ID);
mLoaderManager = null;
mCallbacks = null;
}
public void load(@NonNull ImageFolderBean target) {
Bundle args = new Bundle();
args.putParcelable(ARGS_ALBUM, target);
mLoaderManager.initLoader(LOADER_ID, args, this);
}
}
17
Source : ImageFolderModel.java
with GNU General Public License v3.0
from VideoOS
with GNU General Public License v3.0
from VideoOS
/**
* Created by mac on 18/2/24.
*/
public clreplaced ImageFolderModel implements LoaderManager.LoaderCallbacks<Cursor> {
private static final int LOADER_ID = 1;
private WeakReference<Context> mContext;
private LoaderManager mLoaderManager;
private IImageMediaCallback mCallbacks;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Context context = mContext.get();
if (context == null) {
return null;
}
return ImageFolderScanner.newInstance(context);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
Context context = mContext.get();
if (context == null) {
return;
}
mCallbacks.onImageLoad(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
Context context = mContext.get();
if (context == null) {
return;
}
mCallbacks.onImageReset();
}
public void onCreate(@NonNull Context context, @NonNull IImageMediaCallback callbacks) {
mContext = new WeakReference<Context>(context);
mLoaderManager = ((Activity) context).getLoaderManager();
mCallbacks = callbacks;
}
public void onDestroy() {
mLoaderManager.destroyLoader(LOADER_ID);
mCallbacks = null;
}
public void loadImageFolders() {
mLoaderManager.initLoader(LOADER_ID, null, this);
}
}
17
Source : PictureScanner.java
with Apache License 2.0
from sundevin
with Apache License 2.0
from sundevin
/**
* <p> Created by Devin Sun on 2016/10/14.
*/
public clreplaced PictureScanner implements LoaderManager.LoaderCallbacks<Cursor> {
private final int SCANNER_ID = 0;
/**
* 查询图片需要的数据列
*/
private final String[] IMAGE_PROJECTION = { // //图片的显示名称 aaa.jpg
MediaStore.Images.Media.DISPLAY_NAME, // 图片的真实路径 /storage/emulated/0/pp/downloader/wallpaper/aaa.jpg
MediaStore.Images.Media.DATA, // 图片的大小,long型 132492
MediaStore.Images.Media.SIZE, // 图片的宽度,int型 1920
MediaStore.Images.Media.WIDTH, // 图片的高度,int型 1080
MediaStore.Images.Media.HEIGHT, // 图片被添加的时间,long型 1450518608
MediaStore.Images.Media.DATE_ADDED, // 图片的类型 image/jpeg
MediaStore.Images.Media.MIME_TYPE };
/**
* 图片扫描成的回调接口
*/
public interface OnScanFinishListener {
/**
* 扫描完成
*
* @param pictureFolders
*/
void onScanFinish(List<PictureFolder> pictureFolders);
}
/**
* 所有的目录集合
*/
private List<PictureFolder> pictureFolderList = new ArrayList<>();
private LoaderManager loaderManager;
private Context context;
private String scanFolderAbsPath;
private OnScanFinishListener scanFinishListener;
public PictureScanner() {
}
/**
* 扫描指定路径下图片
*
* @param scanFolderAbsPath
*/
public PictureScanner(String scanFolderAbsPath) {
this.scanFolderAbsPath = scanFolderAbsPath;
}
/**
* 开始扫描
*
* @param scanFinishListener 扫描完成监听
*/
public void startScanPicture(Activity activity, OnScanFinishListener scanFinishListener) {
this.context = activity.getApplication();
this.scanFinishListener = scanFinishListener;
// 先停止扫描
stopScanPicture();
loaderManager = activity.getLoaderManager();
loaderManager.initLoader(SCANNER_ID, null, this);
}
/**
* 停止扫描
*/
public void stopScanPicture() {
if (loaderManager != null) {
loaderManager.destroyLoader(SCANNER_ID);
}
}
private Loader<Cursor> createLoader() {
CursorLoader loader = new CursorLoader(context);
loader.setUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// 要查询的数据
loader.setProjection(IMAGE_PROJECTION);
String selection = MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?";
if (TextUtils.isEmpty(scanFolderAbsPath)) {
loader.setSelection(selection);
String[] selectionArgs;
if (PicturePicker.getInstance().getPickPictureOptions().isSelectGif()) {
selectionArgs = new String[] { "image/jpeg", "image/png", "image/jpg", "image/gif" };
} else {
selectionArgs = new String[] { "image/jpeg", "image/png", "image/jpg" };
}
loader.setSelectionArgs(selectionArgs);
} else {
selection = selection + " " + MediaStore.Images.Media.DATA + " like '%" + scanFolderAbsPath + "%'";
loader.setSelection(selection);
String[] selectionArgs;
if (PicturePicker.getInstance().getPickPictureOptions().isSelectGif()) {
selectionArgs = new String[] { "image/jpeg", "image/png", "image/jpg", "image/gif", scanFolderAbsPath };
} else {
selectionArgs = new String[] { "image/jpeg", "image/png", "image/jpg", scanFolderAbsPath };
}
loader.setSelectionArgs(selectionArgs);
}
// 按加入时间降序排列
loader.setSortOrder(MediaStore.Images.Media.DATE_ADDED + " DESC");
return loader;
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return createLoader();
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
pictureFolderList.clear();
if (data != null) {
// new一个集合存储所有图片
List<PictureItem> allPictureList = new ArrayList<>();
// 图片目录路径和图片目录对象的映射
ArrayMap<String, PictureFolder> path2PictureFolderMap = new ArrayMap<>();
while (data.moveToNext()) {
// 得到图片的路径
String picturePath = data.getString(data.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
if (!TextUtils.isEmpty(picturePath)) {
File pictureFile = new File(picturePath);
if (pictureFile.exists() && pictureFile.length() != 0) {
PictureItem pictureItem = new PictureItem();
pictureItem.pictureAbsPath = picturePath;
pictureItem.pictureAddTime = data.getLong(data.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));
pictureItem.pictureHeight = data.getInt(data.getColumnIndexOrThrow(MediaStore.Images.Media.HEIGHT));
pictureItem.pictureWidth = data.getInt(data.getColumnIndexOrThrow(MediaStore.Images.Media.WIDTH));
pictureItem.pictureMimeType = data.getString(data.getColumnIndexOrThrow(MediaStore.Images.Media.MIME_TYPE));
pictureItem.pictureSize = data.getInt(data.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE));
pictureItem.pictureName = data.getString(data.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
// 得到文件的父目录文件
File parentFile = pictureFile.getParentFile();
// 得到父目录的路径并统一转为小写
String parentFilePath = parentFile.getAbsolutePath().toLowerCase();
// 如果图片文件夹已经被存储
if (null != path2PictureFolderMap.get(parentFilePath)) {
path2PictureFolderMap.get(parentFilePath).pictureItemList.add(pictureItem);
} else {
PictureFolder pictureFolder = new PictureFolder();
pictureFolder.folderName = parentFile.getName();
pictureFolder.folderAbsPath = parentFilePath;
pictureFolder.pictureItemList = new ArrayList<>();
pictureFolder.pictureItemList.add(pictureItem);
// 因为扫描时是按照加入时间降序排序,所以第一个图片为最新的,设为封面
pictureFolder.folderCover = pictureItem;
pictureFolderList.add(pictureFolder);
path2PictureFolderMap.put(parentFilePath, pictureFolder);
}
// 把此图片加到“全部图片”里
allPictureList.add(pictureItem);
}
}
}
if (allPictureList.size() > 0) {
PictureFolder folder = new PictureFolder();
folder.folderName = context.getResources().getString(R.string.all_pictures);
folder.pictureItemList = allPictureList;
folder.folderCover = allPictureList.get(0);
pictureFolderList.add(0, folder);
}
if (scanFinishListener != null) {
scanFinishListener.onScanFinish(pictureFolderList);
}
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
loader.stopLoading();
}
}
17
Source : SystemUtil.java
with Apache License 2.0
from HelloChenJinJun
with Apache License 2.0
from HelloChenJinJun
public static void getAllImageFolder(Activity activity, final OnImageLoadListener listener) {
List<ImageFolder> imageFolderList = new ArrayList<>();
LoaderManager loaderManager = activity.getLoaderManager();
loaderManager.initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Loader<Cursor> loader = null;
if (id == 0) {
loader = new CursorLoader(activity, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, null, null, IMAGE_PROJECTION[6] + " DESC");
}
return loader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
CommonLogger.e("加载完成");
imageFolderList.clear();
if (data != null) {
ArrayList<ImageItem> images = new ArrayList<>();
ImageItem imageItem;
while (data.moveToNext()) {
imageItem = new ImageItem();
// imageItem.setName(data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0])));
imageItem.setPath(data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1])));
// imageItem.setSize(data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]))/1024);
// imageItem.setWidth(data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECTION[3])));
// imageItem.setHeight(data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECTION[4])));
// imageItem.setImageType(data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[5])));
// imageItem.setCreatedTime(data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[6])));
images.add(imageItem);
ImageFolder imageFolder = new ImageFolder();
File file = FileUtil.newFile(imageItem.getPath());
imageFolder.setName(file.getParentFile().getName());
imageFolder.setPath(file.getParentFile().getAbsolutePath());
if (!imageFolderList.contains(imageFolder)) {
ArrayList<ImageItem> list = new ArrayList<>();
list.add(imageItem);
imageFolder.setDisplay(imageItem);
imageFolder.setAllImages(list);
imageFolderList.add(imageFolder);
} else {
imageFolderList.get(imageFolderList.indexOf(imageFolder)).getAllImages().add(imageItem);
}
}
if (data.getCount() > 0) {
// 新建一个所有图片的文件夹
ImageFolder allImageFolder = new ImageFolder();
allImageFolder.setName("全部图片");
allImageFolder.setPath("/");
allImageFolder.setAllImages(images);
allImageFolder.setDisplay(images.get(0));
imageFolderList.add(0, allImageFolder);
}
}
listener.onImageLoaded(imageFolderList);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
CommonLogger.e("onLoaderReset:");
}
});
}
17
Source : ConversationListData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
public void init(final LoaderManager loaderManager, final BindingBase<ConversationListData> binding) {
mArgs = new Bundle();
mArgs.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(CONVERSATION_LIST_LOADER, mArgs, this);
mLoaderManager.initLoader(BLOCKED_PARTICIPANTS_AVAILABLE_LOADER, mArgs, this);
}
17
Source : ConversationData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
public void init(final LoaderManager loaderManager, final BindingBase<ConversationData> binding) {
// Remember the binding id so that loader callbacks can check if data is still bound
// to same ui component
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(CONVERSATION_META_DATA_LOADER, args, mMetadataLoaderCallbacks);
mLoaderManager.initLoader(CONVERSATION_MESSAGES_LOADER, args, mMessagesLoaderCallbacks);
mLoaderManager.initLoader(PARTICIPANT_LOADER, args, mParticipantsLoaderCallbacks);
mLoaderManager.initLoader(SELF_PARTICIPANT_LOADER, args, mSelfParticipantLoaderCallbacks);
}
17
Source : ContactPickerData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
/**
* Clreplaced to access phone contacts.
* The caller is responsible for ensuring that the app has READ_CONTACTS permission (see
* {@link ContactUtil#hasReadContactsPermission()}) before instantiating this clreplaced.
*/
public clreplaced ContactPickerData extends BindableData implements LoaderManager.LoaderCallbacks<Cursor> {
public interface ContactPickerDataListener {
void onAllContactsCursorUpdated(Cursor data);
void onFrequentContactsCursorUpdated(Cursor data);
void onContactCustomColorLoaded(ContactPickerData data);
}
private static final String BINDING_ID = "bindingId";
private final Context mContext;
private LoaderManager mLoaderManager;
private ContactPickerDataListener mListener;
private final FrequentContactsCursorBuilder mFrequentContactsCursorBuilder;
public ContactPickerData(final Context context, final ContactPickerDataListener listener) {
mListener = listener;
mContext = context;
mFrequentContactsCursorBuilder = new FrequentContactsCursorBuilder();
}
private static final int ALL_CONTACTS_LOADER = 1;
private static final int FREQUENT_CONTACTS_LOADER = 2;
private static final int PARTICIPANT_LOADER = 3;
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
final String bindingId = args.getString(BINDING_ID);
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
switch(id) {
case ALL_CONTACTS_LOADER:
return ContactUtil.getPhones(mContext).createBoundCursorLoader(bindingId);
case FREQUENT_CONTACTS_LOADER:
return ContactUtil.getFrequentContacts(mContext).createBoundCursorLoader(bindingId);
case PARTICIPANT_LOADER:
return new BoundCursorLoader(bindingId, mContext, MessagingContentProvider.PARTICIPANTS_URI, ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
default:
replacedert.fail("Unknown loader id for contact picker!");
break;
}
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Loader created after unbinding the contacts list");
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
if (isBound(cursorLoader.getBindingId())) {
switch(loader.getId()) {
case ALL_CONTACTS_LOADER:
mListener.onAllContactsCursorUpdated(data);
mFrequentContactsCursorBuilder.setAllContacts(data);
break;
case FREQUENT_CONTACTS_LOADER:
mFrequentContactsCursorBuilder.setFrequents(data);
break;
case PARTICIPANT_LOADER:
mListener.onContactCustomColorLoaded(this);
break;
default:
replacedert.fail("Unknown loader id for contact picker!");
break;
}
if (loader.getId() != PARTICIPANT_LOADER) {
// The frequent contacts cursor to be used in the UI depends on results from both
// all contacts and frequent contacts loader, and we don't know which will finish
// first. Therefore, try to build the cursor and notify the listener if it's
// successfully built.
final Cursor frequentContactsCursor = mFrequentContactsCursorBuilder.build();
if (frequentContactsCursor != null) {
mListener.onFrequentContactsCursorUpdated(frequentContactsCursor);
}
}
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Loader finished after unbinding the contacts list");
}
}
/**
* {@inheritDoc}
*/
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
if (isBound(cursorLoader.getBindingId())) {
switch(loader.getId()) {
case ALL_CONTACTS_LOADER:
mListener.onAllContactsCursorUpdated(null);
mFrequentContactsCursorBuilder.setAllContacts(null);
break;
case FREQUENT_CONTACTS_LOADER:
mListener.onFrequentContactsCursorUpdated(null);
mFrequentContactsCursorBuilder.setFrequents(null);
break;
case PARTICIPANT_LOADER:
mListener.onContactCustomColorLoaded(this);
break;
default:
replacedert.fail("Unknown loader id for contact picker!");
break;
}
} else {
LogUtil.w(LogUtil.BUGLE_TAG, "Loader reset after unbinding the contacts list");
}
}
public void init(final LoaderManager loaderManager, final BindingBase<ContactPickerData> binding) {
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(ALL_CONTACTS_LOADER, args, this);
mLoaderManager.initLoader(FREQUENT_CONTACTS_LOADER, args, this);
mLoaderManager.initLoader(PARTICIPANT_LOADER, args, this);
}
@Override
protected void unregisterListeners() {
mListener = null;
// This could be null if we bind but the caller doesn't init the BindableData
if (mLoaderManager != null) {
mLoaderManager.destroyLoader(ALL_CONTACTS_LOADER);
mLoaderManager.destroyLoader(FREQUENT_CONTACTS_LOADER);
mLoaderManager.destroyLoader(PARTICIPANT_LOADER);
mLoaderManager = null;
}
mFrequentContactsCursorBuilder.resetBuilder();
}
public static boolean isTooManyParticipants(final int participantCount) {
// When creating a conversation, the conversation will be created using the system's
// default SIM, so use the default MmsConfig's recipient limit.
return (participantCount > MmsConfig.get(ParticipantData.DEFAULT_SELF_SUB_ID).getRecipientLimit());
}
public static boolean getCanAddMoreParticipants(final int participantCount) {
// When creating a conversation, the conversation will be created using the system's
// default SIM, so use the default MmsConfig's recipient limit.
return (participantCount < MmsConfig.get(ParticipantData.DEFAULT_SELF_SUB_ID).getRecipientLimit());
}
}
17
Source : BaseLoader.java
with Apache License 2.0
from akhasoft
with Apache License 2.0
from akhasoft
/**
* Destroys loader with the given ID.
*
* @param loaderManager
* The loader manager
*
* @param loaderId
* The loader ID
*
* @return {@code true} if loader was successfully destroyed, {@code false} otherwise
*/
@SuppressWarnings("WeakerAccess")
public static boolean destroyLoader(final LoaderManager loaderManager, final int loaderId) {
final Loader loader = loaderManager.getLoader(loaderId);
if (loader != null && loader.isStarted()) {
CoreLogger.log("about to destroy loader with id " + loader.getId());
loaderManager.destroyLoader(loaderId);
return true;
}
return false;
}
16
Source : SettingsData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
public void init(final LoaderManager loaderManager, final BindingBase<SettingsData> binding) {
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(SELF_PARTICIPANT_LOADER, args, this);
}
16
Source : PeopleAndOptionsData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
public void init(final LoaderManager loaderManager, final BindingBase<PeopleAndOptionsData> binding) {
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(CONVERSATION_OPTIONS_LOADER, args, this);
mLoaderManager.initLoader(PARTICIPANT_LOADER, args, this);
}
16
Source : ConversationListData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
public clreplaced ConversationListData extends BindableData implements LoaderManager.LoaderCallbacks<Cursor> {
private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
private static final String BINDING_ID = "bindingId";
public static final String SORT_ORDER = ConversationListViewColumns.SORT_TIMESTAMP + " DESC";
private static final String WHERE_ARCHIVED = "(" + ConversationListViewColumns.ARCHIVE_STATUS + " = 1)";
public static final String WHERE_NOT_ARCHIVED = "(" + ConversationListViewColumns.ARCHIVE_STATUS + " = 0)";
public interface ConversationListDataListener {
public void onConversationListCursorUpdated(ConversationListData data, Cursor cursor);
public void setBlockedParticipantsAvailable(boolean blockedAvailable);
}
private ConversationListDataListener mListener;
private final Context mContext;
private final boolean mArchivedMode;
private LoaderManager mLoaderManager;
public ConversationListData(final Context context, final ConversationListDataListener listener, final boolean archivedMode) {
mListener = listener;
mContext = context;
mArchivedMode = archivedMode;
}
private static final int CONVERSATION_LIST_LOADER = 1;
private static final int BLOCKED_PARTICIPANTS_AVAILABLE_LOADER = 2;
private static final String[] BLOCKED_PARTICIPANTS_PROJECTION = new String[] { ParticipantColumns._ID, ParticipantColumns.NORMALIZED_DESTINATION };
private static final int INDEX_BLOCKED_PARTICIPANTS_ID = 0;
private static final int INDEX_BLOCKED_PARTICIPANTS_NORMALIZED_DESTINATION = 1;
// all blocked participants
private final HashSet<String> mBlockedParticipants = new HashSet<String>();
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
final String bindingId = args.getString(BINDING_ID);
Loader<Cursor> loader = null;
// Check if data still bound to the requesting ui element
if (isBound(bindingId)) {
switch(id) {
case BLOCKED_PARTICIPANTS_AVAILABLE_LOADER:
loader = new BoundCursorLoader(bindingId, mContext, MessagingContentProvider.PARTICIPANTS_URI, BLOCKED_PARTICIPANTS_PROJECTION, ParticipantColumns.BLOCKED + "=1", null, null);
break;
case CONVERSATION_LIST_LOADER:
loader = new BoundCursorLoader(bindingId, mContext, MessagingContentProvider.CONVERSATIONS_URI, ConversationLisreplacedemData.PROJECTION, mArchivedMode ? WHERE_ARCHIVED : WHERE_NOT_ARCHIVED, // selection args
null, SORT_ORDER);
break;
default:
replacedert.fail("Unknown loader id");
break;
}
} else {
LogUtil.w(TAG, "Creating loader after unbinding list");
}
return loader;
}
/**
* {@inheritDoc}
*/
@Override
public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
if (isBound(loader.getBindingId())) {
switch(loader.getId()) {
case BLOCKED_PARTICIPANTS_AVAILABLE_LOADER:
mBlockedParticipants.clear();
for (int i = 0; i < data.getCount(); i++) {
data.moveToPosition(i);
mBlockedParticipants.add(data.getString(INDEX_BLOCKED_PARTICIPANTS_NORMALIZED_DESTINATION));
}
mListener.setBlockedParticipantsAvailable(data != null && data.getCount() > 0);
break;
case CONVERSATION_LIST_LOADER:
mListener.onConversationListCursorUpdated(this, data);
break;
default:
replacedert.fail("Unknown loader id");
break;
}
} else {
LogUtil.w(TAG, "Loader finished after unbinding list");
}
}
/**
* {@inheritDoc}
*/
@Override
public void onLoaderReset(final Loader<Cursor> generic) {
final BoundCursorLoader loader = (BoundCursorLoader) generic;
if (isBound(loader.getBindingId())) {
switch(loader.getId()) {
case BLOCKED_PARTICIPANTS_AVAILABLE_LOADER:
mListener.setBlockedParticipantsAvailable(false);
break;
case CONVERSATION_LIST_LOADER:
mListener.onConversationListCursorUpdated(this, null);
break;
default:
replacedert.fail("Unknown loader id");
break;
}
} else {
LogUtil.w(TAG, "Loader reset after unbinding list");
}
}
private Bundle mArgs;
public void init(final LoaderManager loaderManager, final BindingBase<ConversationListData> binding) {
mArgs = new Bundle();
mArgs.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(CONVERSATION_LIST_LOADER, mArgs, this);
mLoaderManager.initLoader(BLOCKED_PARTICIPANTS_AVAILABLE_LOADER, mArgs, this);
}
public void handleMessagesSeen() {
BugleNotifications.markAllMessagesreplacedeen();
SmsReceiver.cancelSecondaryUserNotification();
}
@Override
protected void unregisterListeners() {
mListener = null;
// This could be null if we bind but the caller doesn't init the BindableData
if (mLoaderManager != null) {
mLoaderManager.destroyLoader(CONVERSATION_LIST_LOADER);
mLoaderManager.destroyLoader(BLOCKED_PARTICIPANTS_AVAILABLE_LOADER);
mLoaderManager = null;
}
}
public boolean getHasFirstSyncCompleted() {
final SyncManager syncManager = DataModel.get().getSyncManager();
return syncManager.getHasFirstSyncCompleted();
}
public void setScrolledToNewestConversation(boolean scrolledToNewestConversation) {
DataModel.get().setConversationListScrolledToNewestConversation(scrolledToNewestConversation);
if (scrolledToNewestConversation) {
handleMessagesSeen();
}
}
public HashSet<String> getBlockedParticipants() {
return mBlockedParticipants;
}
}
16
Source : ContactPickerData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
public void init(final LoaderManager loaderManager, final BindingBase<ContactPickerData> binding) {
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(ALL_CONTACTS_LOADER, args, this);
mLoaderManager.initLoader(FREQUENT_CONTACTS_LOADER, args, this);
mLoaderManager.initLoader(PARTICIPANT_LOADER, args, this);
}
16
Source : BlockedParticipantsData.java
with Apache License 2.0
from alperali
with Apache License 2.0
from alperali
public void init(final LoaderManager loaderManager, final BindingBase<BlockedParticipantsData> binding) {
final Bundle args = new Bundle();
args.putString(BINDING_ID, binding.getBindingId());
mLoaderManager = loaderManager;
mLoaderManager.initLoader(BLOCKED_PARTICIPANTS_LOADER, args, this);
}
16
Source : BaseLoaderWrapper.java
with Apache License 2.0
from akhasoft
with Apache License 2.0
from akhasoft
@NonNull
private BaseLoaderWrapper<D> startHelper(@NonNull final Bundle bundle) {
mData = null;
mProgress = null;
final Fragment fragment = getFragment();
if (fragment == null)
return this;
final LoaderManager loaderManager = fragment.getLoaderManager();
if (loaderManager == null)
CoreLogger.logError("loaderManager == null");
else {
loaderManager.restartLoader(mLoaderId, bundle, this);
mLoading.set(true);
}
return this;
}
16
Source : WorkerFragment.java
with Apache License 2.0
from akhasoft
with Apache License 2.0
from akhasoft
@SuppressWarnings("unchecked")
private void restoreCallbacks(@NonNull final LoaderManager loaderManager, final int id, @NonNull final BaseLoaderWrapper loader) {
loaderManager.initLoader(id, null, loader);
}
14
Source : LoadPictureUtil.java
with Apache License 2.0
from HelloChenJinJun
with Apache License 2.0
from HelloChenJinJun
public void getAllImageFolder(Activity activity, final OnImageLoadListener listener) {
this.activity = activity;
imageFolderList = new ArrayList<>();
LoaderManager loaderManager = activity.getLoaderManager();
loaderManager.initLoader(LoadPictureUtil.LOAD_ALL, null, new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Loader<Cursor> loader = null;
if (id == LOAD_ALL) {
LogUtil.e("加载系统数据");
loader = new CursorLoader(LoadPictureUtil.this.activity, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, null, null, IMAGE_PROJECTION[6] + " DESC");
}
return loader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
LogUtil.e("加载完成");
imageFolderList.clear();
if (data != null) {
ArrayList<ImageItem> images = new ArrayList<>();
ImageItem imageItem;
while (data.moveToNext()) {
imageItem = new ImageItem();
imageItem.setName(data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0])));
imageItem.setPath(data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1])));
imageItem.setSize(data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2])) / 1024);
imageItem.setWidth(data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECTION[3])));
imageItem.setHeight(data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECTION[4])));
imageItem.setImageType(data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[5])));
imageItem.setCreatedTime(data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[6])));
images.add(imageItem);
ImageFolder imageFolder = new ImageFolder();
File file = FileUtil.newFile(imageItem.getPath());
imageFolder.setName(file.getParentFile().getName());
imageFolder.setPath(file.getParentFile().getAbsolutePath());
if (!imageFolderList.contains(imageFolder)) {
ArrayList<ImageItem> list = new ArrayList<>();
list.add(imageItem);
imageFolder.setDisplay(imageItem);
imageFolder.setAllImages(list);
imageFolderList.add(imageFolder);
} else {
imageFolderList.get(imageFolderList.indexOf(imageFolder)).getAllImages().add(imageItem);
}
}
if (data.getCount() > 0) {
// 新建一个所有图片的文件夹
ImageFolder allImageFolder = new ImageFolder();
allImageFolder.setName("全部图片");
allImageFolder.setPath("/");
allImageFolder.setAllImages(images);
allImageFolder.setDisplay(images.get(0));
LogUtil.e("第一个封面信息\n");
LogUtil.e("name" + images.get(0).getName() + "\n" + "path" + images.get(0).getPath() + "\n" + "size" + images.get(0).getSize() + "\n" + "type" + images.get(0).getImageType() + "\n");
imageFolderList.add(0, allImageFolder);
}
}
listener.onImageLoaded(imageFolderList);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
LogUtil.e("onLoaderReset:");
}
});
}
14
Source : WalletDisclaimerFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public final clreplaced WalletDisclaimerFragment extends Fragment implements OnSharedPreferenceChangeListener {
private AbstractBindServiceActivity activity;
private Configuration config;
private LoaderManager loaderManager;
@Nullable
private BlockchainState blockchainState = null;
private TextView messageView;
private static final int ID_BLOCKCHAIN_STATE_LOADER = 0;
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractBindServiceActivity) activity;
final WalletApplication application = (WalletApplication) activity.getApplication();
this.config = application.getConfiguration();
this.loaderManager = getLoaderManager();
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
messageView = (TextView) inflater.inflate(R.layout.wallet_disclaimer_fragment, container);
messageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
HelpDialogFragment.page(getFragmentManager(), R.string.help_safety);
}
});
return messageView;
}
@Override
public void onResume() {
super.onResume();
config.registerOnSharedPreferenceChangeListener(this);
loaderManager.initLoader(ID_BLOCKCHAIN_STATE_LOADER, null, blockchainStateLoaderCallbacks);
updateView();
}
@Override
public void onPause() {
loaderManager.destroyLoader(ID_BLOCKCHAIN_STATE_LOADER);
config.unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if (Configuration.PREFS_KEY_DISCLAIMER.equals(key))
updateView();
}
private void updateView() {
if (!isResumed())
return;
final boolean showDisclaimer = config.getDisclaimerEnabled();
int progressResId = 0;
if (blockchainState != null) {
final Set<Impediment> impediments = blockchainState.impediments;
if (impediments.contains(Impediment.STORAGE))
progressResId = R.string.blockchain_state_progress_problem_storage;
else if (impediments.contains(Impediment.NETWORK))
progressResId = R.string.blockchain_state_progress_problem_network;
}
final SpannableStringBuilder text = new SpannableStringBuilder();
if (progressResId != 0)
text.append(Html.fromHtml("<b>" + getString(progressResId) + "</b>"));
if (progressResId != 0 && showDisclaimer)
text.append('\n');
if (showDisclaimer)
text.append(Html.fromHtml(getString(R.string.wallet_disclaimer_fragment_remind_safety)));
messageView.setText(text);
final View view = getView();
final ViewParent parent = view.getParent();
final View fragment = parent instanceof FrameLayout ? (FrameLayout) parent : view;
fragment.setVisibility(text.length() > 0 ? View.VISIBLE : View.GONE);
}
private final LoaderCallbacks<BlockchainState> blockchainStateLoaderCallbacks = new LoaderManager.LoaderCallbacks<BlockchainState>() {
@Override
public Loader<BlockchainState> onCreateLoader(final int id, final Bundle args) {
return new BlockchainStateLoader(activity);
}
@Override
public void onLoadFinished(final Loader<BlockchainState> loader, final BlockchainState blockchainState) {
WalletDisclaimerFragment.this.blockchainState = blockchainState;
updateView();
}
@Override
public void onLoaderReset(final Loader<BlockchainState> loader) {
}
};
}
14
Source : SendingAddressesFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public final clreplaced SendingAddressesFragment extends FancyListFragment implements LoaderManager.LoaderCallbacks<Cursor>, OnPrimaryClipChangedListener {
private AbstractWalletActivity activity;
private Wallet wallet;
private ClipboardManager clipboardManager;
private LoaderManager loaderManager;
private SimpleCursorAdapter adapter;
private String walletAddressesSelection;
private final Handler handler = new Handler();
private static final int REQUEST_CODE_SCAN = 0;
private static final Logger log = LoggerFactory.getLogger(SendingAddressesFragment.clreplaced);
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractWalletActivity) activity;
final WalletApplication application = (WalletApplication) activity.getApplication();
this.wallet = application.getWallet();
this.clipboardManager = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
this.loaderManager = getLoaderManager();
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
adapter = new SimpleCursorAdapter(activity, R.layout.address_book_row, null, new String[] { AddressBookProvider.KEY_LABEL, AddressBookProvider.KEY_ADDRESS }, new int[] { R.id.address_book_row_label, R.id.address_book_row_address }, 0);
adapter.setViewBinder(new ViewBinder() {
@Override
public boolean setViewValue(final View view, final Cursor cursor, final int columnIndex) {
if (!AddressBookProvider.KEY_ADDRESS.equals(cursor.getColumnName(columnIndex)))
return false;
((TextView) view).setText(WalletUtils.formatHash(cursor.getString(columnIndex), Constants.ADDRESS_FORMAT_GROUP_SIZE, Constants.ADDRESS_FORMAT_LINE_SIZE));
return true;
}
});
setListAdapter(adapter);
loaderManager.initLoader(0, null, this);
}
@Override
public void onResume() {
super.onResume();
clipboardManager.addPrimaryClipChangedListener(this);
}
@Override
public void onPause() {
clipboardManager.removePrimaryClipChangedListener(this);
super.onPause();
}
@Override
public void onDestroy() {
loaderManager.destroyLoader(0);
super.onDestroy();
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
if (requestCode == REQUEST_CODE_SCAN && resultCode == Activity.RESULT_OK) {
final String input = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT);
new StringInputParser(input) {
@Override
protected void handlePaymentIntent(final PaymentIntent paymentIntent) {
// workaround for "IllegalStateException: Can not perform this action after
// onSaveInstanceState"
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (paymentIntent.hasAddress()) {
final Address address = paymentIntent.getAddress();
if (!wallet.isPubKeyHashMine(address.getHash160()))
EditAddressBookEntryFragment.edit(getFragmentManager(), address);
else
dialog(activity, null, R.string.address_book_options_scan_replacedle, R.string.address_book_options_scan_own_address);
} else {
dialog(activity, null, R.string.address_book_options_scan_replacedle, R.string.address_book_options_scan_invalid);
}
}
}, 500);
}
@Override
protected void handleDirectTransaction(final Transaction transaction) throws VerificationException {
cannotClreplacedify(input);
}
@Override
protected void error(final int messageResId, final Object... messageArgs) {
dialog(activity, null, R.string.address_book_options_scan_replacedle, messageResId, messageArgs);
}
}.parse();
}
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.sending_addresses_fragment_options, menu);
final PackageManager pm = activity.getPackageManager();
menu.findItem(R.id.sending_addresses_options_scan).setVisible(pm.hreplacedystemFeature(PackageManager.FEATURE_CAMERA) || pm.hreplacedystemFeature(PackageManager.FEATURE_CAMERA_FRONT));
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onPrepareOptionsMenu(final Menu menu) {
menu.findItem(R.id.sending_addresses_options_paste).setEnabled(getAddressFromPrimaryClip() != null);
super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch(item.gereplacedemId()) {
case R.id.sending_addresses_options_paste:
handlePasteClipboard();
return true;
case R.id.sending_addresses_options_scan:
handleScan();
return true;
}
return super.onOptionsItemSelected(item);
}
private void handlePasteClipboard() {
final Address address = getAddressFromPrimaryClip();
if (address == null) {
final DialogBuilder dialog = new DialogBuilder(activity);
dialog.setreplacedle(R.string.address_book_options_paste_from_clipboard_replacedle);
dialog.setMessage(R.string.address_book_options_paste_from_clipboard_invalid);
dialog.singleDismissButton(null);
dialog.show();
} else if (!wallet.isPubKeyHashMine(address.getHash160())) {
EditAddressBookEntryFragment.edit(getFragmentManager(), address);
} else {
final DialogBuilder dialog = new DialogBuilder(activity);
dialog.setreplacedle(R.string.address_book_options_paste_from_clipboard_replacedle);
dialog.setMessage(R.string.address_book_options_paste_from_clipboard_own_address);
dialog.singleDismissButton(null);
dialog.show();
}
}
private void handleScan() {
startActivityForResult(new Intent(activity, ScanActivity.clreplaced), REQUEST_CODE_SCAN);
}
@Override
public void onLisreplacedemClick(final ListView l, final View v, final int position, final long id) {
activity.startActionMode(new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(final ActionMode mode, final Menu menu) {
final MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.sending_addresses_context, menu);
return true;
}
@Override
public boolean onPrepareActionMode(final ActionMode mode, final Menu menu) {
final String label = getLabel(position);
mode.setreplacedle(label);
return true;
}
@Override
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
switch(item.gereplacedemId()) {
case R.id.sending_addresses_context_send:
handleSend(getAddress(position));
mode.finish();
return true;
case R.id.sending_addresses_context_edit:
EditAddressBookEntryFragment.edit(getFragmentManager(), getAddress(position));
mode.finish();
return true;
case R.id.sending_addresses_context_remove:
handleRemove(getAddress(position));
mode.finish();
return true;
case R.id.sending_addresses_context_show_qr:
handleShowQr(getAddress(position), getLabel(position));
mode.finish();
return true;
case R.id.sending_addresses_context_copy_to_clipboard:
handleCopyToClipboard(getAddress(position));
mode.finish();
return true;
}
return false;
}
@Override
public void onDestroyActionMode(final ActionMode mode) {
}
private String getAddress(final int position) {
final Cursor cursor = (Cursor) adapter.gereplacedem(position);
return cursor.getString(cursor.getColumnIndexOrThrow(AddressBookProvider.KEY_ADDRESS));
}
private String getLabel(final int position) {
final Cursor cursor = (Cursor) adapter.gereplacedem(position);
return cursor.getString(cursor.getColumnIndexOrThrow(AddressBookProvider.KEY_LABEL));
}
});
}
private void handleSend(final String address) {
SendCoinsActivity.start(activity, PaymentIntent.fromAddress(address, null));
}
private void handleRemove(final String address) {
final Uri uri = AddressBookProvider.contentUri(activity.getPackageName()).buildUpon().appendPath(address).build();
activity.getContentResolver().delete(uri, null, null);
}
private void handleShowQr(final String address, final String label) {
final String uri = BitcoinURI.convertToBitcoinURI(Constants.NETWORK_PARAMETERS, address, null, label, null);
BitmapFragment.show(getFragmentManager(), Qr.bitmap(uri));
}
private void handleCopyToClipboard(final String address) {
clipboardManager.setPrimaryClip(ClipData.newPlainText("Bitcoin address", address));
log.info("sending address copied to clipboard: {}", address.toString());
new Toast(activity).toast(R.string.wallet_address_fragment_clipboard_msg);
}
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
final Uri uri = AddressBookProvider.contentUri(activity.getPackageName());
return new CursorLoader(activity, uri, null, AddressBookProvider.SELECTION_NOTIN, new String[] { walletAddressesSelection != null ? walletAddressesSelection : "" }, AddressBookProvider.KEY_LABEL + " COLLATE LOCALIZED ASC");
}
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
adapter.swapCursor(data);
setEmptyText(WholeStringBuilder.bold(getString(R.string.address_book_empty_text)));
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
adapter.swapCursor(null);
}
public void setWalletAddresses(@Nonnull final ArrayList<Address> addresses) {
final StringBuilder builder = new StringBuilder();
for (final Address address : addresses) builder.append(address.toBase58()).append(",");
if (addresses.size() > 0)
builder.setLength(builder.length() - 1);
walletAddressesSelection = builder.toString();
}
private Address getAddressFromPrimaryClip() {
if (!clipboardManager.hasPrimaryClip())
return null;
final ClipData clip = clipboardManager.getPrimaryClip();
final ClipDescription clipDescription = clip.getDescription();
if (clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
final CharSequence clipText = clip.gereplacedemAt(0).getText();
if (clipText == null)
return null;
try {
return Address.fromBase58(Constants.NETWORK_PARAMETERS, clipText.toString().trim());
} catch (final AddressFormatException x) {
return null;
}
} else if (clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_URILIST)) {
final Uri clipUri = clip.gereplacedemAt(0).getUri();
if (clipUri == null)
return null;
try {
return new BitcoinURI(clipUri.toString()).getAddress();
} catch (final BitcoinURIParseException x) {
return null;
}
} else {
return null;
}
}
@Override
public void onPrimaryClipChanged() {
activity.invalidateOptionsMenu();
}
}
14
Source : EditorActivity.java
with MIT License
from AmrDeveloper
with MIT License
from AmrDeveloper
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_editor);
// Find all relevant views that we will need to read user input from
mNameEditText = (EditText) findViewById(R.id.edit_pet_name);
mBreedEditText = (EditText) findViewById(R.id.edit_pet_breed);
mWeightEditText = (EditText) findViewById(R.id.edit_pet_weight);
mGenderSpinner = (Spinner) findViewById(R.id.spinner_gender);
// Set onTouch Listener
mNameEditText.setOnTouchListener(mTouchListener);
mBreedEditText.setOnTouchListener(mTouchListener);
mWeightEditText.setOnTouchListener(mTouchListener);
mGenderSpinner.setOnTouchListener(mTouchListener);
setupSpinner();
Intent intent = getIntent();
currentUri = intent.getData();
// Editor Mode
if (currentUri != null) {
setreplacedle(R.string.editPet);
// Update ui with Current Information
LoaderManager loaderManager = getLoaderManager();
loaderManager.initLoader(PET_LOADER, null, this);
} else // Insert mode
{
setreplacedle(R.string.addPet);
}
}
11
Source : PeerListFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public final clreplaced PeerListFragment extends Fragment {
private AbstractWalletActivity activity;
private LoaderManager loaderManager;
private BlockchainService service;
private ViewAnimator viewGroup;
private RecyclerView recyclerView;
private PeerViewAdapter adapter;
private final Handler handler = new Handler();
private static final long REFRESH_MS = DateUtils.SECOND_IN_MILLIS;
private static final int ID_PEER_LOADER = 0;
private static final int ID_REVERSE_DNS_LOADER = 1;
private final Map<InetAddress, String> hostnames = new WeakHashMap<InetAddress, String>();
private static final Logger log = LoggerFactory.getLogger(PeerListFragment.clreplaced);
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractWalletActivity) activity;
this.loaderManager = getLoaderManager();
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
activity.bindService(new Intent(activity, BlockchainServiceImpl.clreplaced), serviceConnection, Context.BIND_AUTO_CREATE);
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
adapter = new PeerViewAdapter();
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.peer_list_fragment, container, false);
viewGroup = (ViewAnimator) view.findViewById(R.id.peer_list_group);
recyclerView = (RecyclerView) view.findViewById(R.id.peer_list);
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
return view;
}
@Override
public void onResume() {
super.onResume();
handler.postDelayed(new Runnable() {
@Override
public void run() {
adapter.notifyDataSetChanged();
final Loader<String> loader = loaderManager.getLoader(ID_REVERSE_DNS_LOADER);
final boolean loaderRunning = loader != null && loader.isStarted();
if (!loaderRunning) {
for (int i = 0; i < adapter.gereplacedemCount(); i++) {
final Peer peer = adapter.gereplacedem(i);
final InetAddress address = peer.getAddress().getAddr();
if (!hostnames.containsKey(address)) {
final Bundle args = new Bundle();
args.putSerializable("address", address);
loaderManager.initLoader(ID_REVERSE_DNS_LOADER, args, reverseDnsLoaderCallbacks).forceLoad();
break;
}
}
}
handler.postDelayed(this, REFRESH_MS);
}
}, REFRESH_MS);
}
@Override
public void onPause() {
handler.removeCallbacksAndMessages(null);
super.onPause();
}
@Override
public void onDestroy() {
activity.unbindService(serviceConnection);
loaderManager.destroyLoader(ID_REVERSE_DNS_LOADER);
super.onDestroy();
}
private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(final ComponentName name, final IBinder binder) {
service = ((BlockchainServiceImpl.LocalBinder) binder).getService();
loaderManager.initLoader(ID_PEER_LOADER, null, peerLoaderCallbacks);
}
@Override
public void onServiceDisconnected(final ComponentName name) {
loaderManager.destroyLoader(ID_PEER_LOADER);
service = null;
}
};
private clreplaced PeerViewAdapter extends RecyclerView.Adapter<PeerViewHolder> {
private final LayoutInflater inflater = LayoutInflater.from(activity);
private final List<Peer> peers = new LinkedList<Peer>();
public PeerViewAdapter() {
setHreplacedtableIds(true);
}
public void clear() {
peers.clear();
notifyDataSetChanged();
}
public void replace(final List<Peer> peers) {
this.peers.clear();
this.peers.addAll(peers);
notifyDataSetChanged();
}
public Peer gereplacedem(final int position) {
return peers.get(position);
}
@Override
public int gereplacedemCount() {
return peers.size();
}
@Override
public long gereplacedemId(final int position) {
return peers.get(position).getAddress().hashCode();
}
@Override
public PeerViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
return new PeerViewHolder(inflater.inflate(R.layout.peer_list_row, parent, false));
}
@Override
public void onBindViewHolder(final PeerViewHolder holder, final int position) {
final Peer peer = gereplacedem(position);
final VersionMessage versionMessage = peer.getPeerVersionMessage();
final boolean isDownloading = peer.isDownloadData();
final InetAddress address = peer.getAddress().getAddr();
final String hostname = hostnames.get(address);
holder.ipView.setText(hostname != null ? hostname : address.getHostAddress());
final long bestHeight = peer.getBestHeight();
holder.heightView.setText(bestHeight > 0 ? bestHeight + " blocks" : null);
holder.heightView.setTypeface(isDownloading ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
holder.versionView.setText(versionMessage.subVer);
holder.versionView.setTypeface(isDownloading ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
holder.protocolView.setText("protocol: " + versionMessage.clientVersion);
holder.protocolView.setTypeface(isDownloading ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
final long pingTime = peer.getPingTime();
holder.pingView.setText(pingTime < Long.MAX_VALUE ? getString(R.string.peer_list_row_ping_time, pingTime) : null);
holder.pingView.setTypeface(isDownloading ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
}
}
private static clreplaced PeerViewHolder extends RecyclerView.ViewHolder {
private final TextView ipView;
private final TextView heightView;
private final TextView versionView;
private final TextView protocolView;
private final TextView pingView;
private PeerViewHolder(final View itemView) {
super(itemView);
ipView = (TextView) itemView.findViewById(R.id.peer_list_row_ip);
heightView = (TextView) itemView.findViewById(R.id.peer_list_row_height);
versionView = (TextView) itemView.findViewById(R.id.peer_list_row_version);
protocolView = (TextView) itemView.findViewById(R.id.peer_list_row_protocol);
pingView = (TextView) itemView.findViewById(R.id.peer_list_row_ping);
}
}
private static clreplaced PeerLoader extends AsyncTaskLoader<List<Peer>> {
private LocalBroadcastManager broadcastManager;
private BlockchainService service;
private PeerLoader(final Context context, final BlockchainService service) {
super(context);
this.broadcastManager = LocalBroadcastManager.getInstance(context.getApplicationContext());
this.service = service;
}
@Override
protected void onStartLoading() {
super.onStartLoading();
broadcastManager.registerReceiver(broadcastReceiver, new IntentFilter(BlockchainService.ACTION_PEER_STATE));
forceLoad();
}
@Override
protected void onStopLoading() {
broadcastManager.unregisterReceiver(broadcastReceiver);
super.onStopLoading();
}
@Override
public List<Peer> loadInBackground() {
return service.getConnectedPeers();
}
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
try {
forceLoad();
} catch (final RejectedExecutionException x) {
log.info("rejected execution: " + PeerLoader.this.toString());
}
}
};
}
private final LoaderCallbacks<List<Peer>> peerLoaderCallbacks = new LoaderCallbacks<List<Peer>>() {
@Override
public Loader<List<Peer>> onCreateLoader(final int id, final Bundle args) {
return new PeerLoader(activity, service);
}
@Override
public void onLoadFinished(final Loader<List<Peer>> loader, final List<Peer> peers) {
if (peers == null || peers.isEmpty()) {
viewGroup.setDisplayedChild(1);
adapter.clear();
} else {
viewGroup.setDisplayedChild(2);
adapter.replace(peers);
}
}
@Override
public void onLoaderReset(final Loader<List<Peer>> loader) {
adapter.clear();
}
};
private static clreplaced ReverseDnsLoader extends AsyncTaskLoader<String> {
public final InetAddress address;
public ReverseDnsLoader(final Context context, final InetAddress address) {
super(context);
this.address = address;
}
@Override
public String loadInBackground() {
return address.getCanonicalHostName();
}
}
private final LoaderCallbacks<String> reverseDnsLoaderCallbacks = new LoaderCallbacks<String>() {
@Override
public Loader<String> onCreateLoader(final int id, final Bundle args) {
final InetAddress address = (InetAddress) args.getSerializable("address");
return new ReverseDnsLoader(activity, address);
}
@Override
public void onLoadFinished(final Loader<String> loader, final String hostname) {
final InetAddress address = ((ReverseDnsLoader) loader).address;
hostnames.put(address, hostname);
loaderManager.destroyLoader(ID_REVERSE_DNS_LOADER);
}
@Override
public void onLoaderReset(final Loader<String> loader) {
}
};
}
11
Source : CacheLoader.java
with Apache License 2.0
from akhasoft
with Apache License 2.0
from akhasoft
/**
* Please refer to the base method description.
*/
@CallSuper
@Override
protected void onFailure(@NonNull final BaseResponse<R, E, D> baseResponse) {
CoreLogger.log(addLoaderInfo("about to load from cache"));
final Fragment fragment = mFragment.get();
if (fragment == null) {
CoreLogger.logError("fragment == null");
return;
}
final LoaderManager loaderManager = fragment.getLoaderManager();
if (loaderManager == null)
CoreLogger.logError("loaderManager == null");
else
loaderManager.restartLoader(-mLoaderId, null, new CursorLoaderWrapper(baseResponse.getError()));
}
10
Source : WalletBalanceFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public final clreplaced WalletBalanceFragment extends Fragment {
private WalletApplication application;
private AbstractBindServiceActivity activity;
private Configuration config;
private Wallet wallet;
private LoaderManager loaderManager;
private View viewBalance;
private CurrencyTextView viewBalanceBtc;
private TextView viewBalanceWarning;
private CurrencyTextView viewBalanceLocal;
private TextView viewProgress;
private boolean showLocalBalance;
private boolean installedFromGooglePlay;
@Nullable
private Coin balance = null;
@Nullable
private ExchangeRate exchangeRate = null;
@Nullable
private BlockchainState blockchainState = null;
private static final int ID_BALANCE_LOADER = 0;
private static final int ID_RATE_LOADER = 1;
private static final int ID_BLOCKCHAIN_STATE_LOADER = 2;
private static final long BLOCKCHAIN_UPTODATE_THRESHOLD_MS = DateUtils.HOUR_IN_MILLIS;
private static final Coin SOME_BALANCE_THRESHOLD = Coin.COIN.divide(100);
private static final Coin TOO_MUCH_BALANCE_THRESHOLD = Coin.COIN.divide(2);
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractBindServiceActivity) activity;
this.application = (WalletApplication) activity.getApplication();
this.config = application.getConfiguration();
this.wallet = application.getWallet();
this.loaderManager = getLoaderManager();
showLocalBalance = getResources().getBoolean(R.bool.show_local_balance);
installedFromGooglePlay = "com.android.vending".equals(application.getPackageManager().getInstallerPackageName(application.getPackageName()));
}
@Override
public void onCreate(final Bundle savedInstanceState) {
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
return inflater.inflate(R.layout.wallet_balance_fragment, container, false);
}
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final boolean showExchangeRatesOption = Constants.ENABLE_EXCHANGE_RATES && getResources().getBoolean(R.bool.show_exchange_rates_option);
viewBalance = view.findViewById(R.id.wallet_balance);
if (showExchangeRatesOption) {
viewBalance.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
startActivity(new Intent(getActivity(), ExchangeRatesActivity.clreplaced));
}
});
} else {
viewBalance.setEnabled(false);
}
viewBalanceBtc = (CurrencyTextView) view.findViewById(R.id.wallet_balance_btc);
viewBalanceBtc.setPrefixScaleX(0.9f);
viewBalanceWarning = (TextView) view.findViewById(R.id.wallet_balance_warning);
viewBalanceLocal = (CurrencyTextView) view.findViewById(R.id.wallet_balance_local);
viewBalanceLocal.setInsignificantRelativeSize(1);
viewBalanceLocal.setStrikeThru(Constants.TEST);
viewProgress = (TextView) view.findViewById(R.id.wallet_balance_progress);
}
@Override
public void onResume() {
super.onResume();
loaderManager.initLoader(ID_BALANCE_LOADER, null, balanceLoaderCallbacks);
if (Constants.ENABLE_EXCHANGE_RATES)
loaderManager.initLoader(ID_RATE_LOADER, null, rateLoaderCallbacks);
loaderManager.initLoader(ID_BLOCKCHAIN_STATE_LOADER, null, blockchainStateLoaderCallbacks);
updateView();
}
@Override
public void onPause() {
loaderManager.destroyLoader(ID_BLOCKCHAIN_STATE_LOADER);
if (Constants.ENABLE_EXCHANGE_RATES)
loaderManager.destroyLoader(ID_RATE_LOADER);
loaderManager.destroyLoader(ID_BALANCE_LOADER);
super.onPause();
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.wallet_balance_fragment_options, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onPrepareOptionsMenu(final Menu menu) {
final boolean hreplacedomeBalance = balance != null && !balance.isLessThan(SOME_BALANCE_THRESHOLD);
menu.findItem(R.id.wallet_balance_options_donate).setVisible(Constants.DONATION_ADDRESS != null && (!installedFromGooglePlay || hreplacedomeBalance));
super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch(item.gereplacedemId()) {
case R.id.wallet_balance_options_donate:
handleDonate();
return true;
}
return super.onOptionsItemSelected(item);
}
private void handleDonate() {
SendCoinsActivity.startDonate(activity, null, FeeCategory.ECONOMIC, 0);
}
private void updateView() {
if (!isAdded())
return;
final boolean showProgress;
if (blockchainState != null && blockchainState.bestChainDate != null) {
final long blockchainLag = System.currentTimeMillis() - blockchainState.bestChainDate.getTime();
final boolean blockchainUptodate = blockchainLag < BLOCKCHAIN_UPTODATE_THRESHOLD_MS;
final boolean noImpediments = blockchainState.impediments.isEmpty();
showProgress = !(blockchainUptodate || !blockchainState.replaying);
final String downloading = getString(noImpediments ? R.string.blockchain_state_progress_downloading : R.string.blockchain_state_progress_stalled);
if (blockchainLag < 2 * DateUtils.DAY_IN_MILLIS) {
final long hours = blockchainLag / DateUtils.HOUR_IN_MILLIS;
viewProgress.setText(getString(R.string.blockchain_state_progress_hours, downloading, hours));
} else if (blockchainLag < 2 * DateUtils.WEEK_IN_MILLIS) {
final long days = blockchainLag / DateUtils.DAY_IN_MILLIS;
viewProgress.setText(getString(R.string.blockchain_state_progress_days, downloading, days));
} else if (blockchainLag < 90 * DateUtils.DAY_IN_MILLIS) {
final long weeks = blockchainLag / DateUtils.WEEK_IN_MILLIS;
viewProgress.setText(getString(R.string.blockchain_state_progress_weeks, downloading, weeks));
} else {
final long months = blockchainLag / (30 * DateUtils.DAY_IN_MILLIS);
viewProgress.setText(getString(R.string.blockchain_state_progress_months, downloading, months));
}
} else {
showProgress = false;
}
if (!showProgress) {
viewBalance.setVisibility(View.VISIBLE);
if (!showLocalBalance)
viewBalanceLocal.setVisibility(View.GONE);
if (balance != null) {
viewBalanceBtc.setVisibility(View.VISIBLE);
viewBalanceBtc.setFormat(config.getFormat());
viewBalanceBtc.setAmount(balance);
if (showLocalBalance) {
if (exchangeRate != null) {
final Fiat localValue = exchangeRate.rate.coinToFiat(balance);
viewBalanceLocal.setVisibility(View.VISIBLE);
viewBalanceLocal.setFormat(Constants.LOCAL_FORMAT.code(0, Constants.PREFIX_ALMOST_EQUAL_TO + exchangeRate.getCurrencyCode()));
viewBalanceLocal.setAmount(localValue);
viewBalanceLocal.setTextColor(getResources().getColor(R.color.fg_less_significant));
} else {
viewBalanceLocal.setVisibility(View.INVISIBLE);
}
}
} else {
viewBalanceBtc.setVisibility(View.INVISIBLE);
}
if (balance != null && balance.isGreaterThan(TOO_MUCH_BALANCE_THRESHOLD)) {
viewBalanceWarning.setVisibility(View.VISIBLE);
viewBalanceWarning.setText(R.string.wallet_balance_fragment_too_much);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
viewBalanceWarning.setVisibility(View.VISIBLE);
viewBalanceWarning.setText(R.string.wallet_balance_fragment_insecure_device);
} else {
viewBalanceWarning.setVisibility(View.GONE);
}
viewProgress.setVisibility(View.GONE);
} else {
viewProgress.setVisibility(View.VISIBLE);
viewBalance.setVisibility(View.INVISIBLE);
}
}
private final LoaderCallbacks<BlockchainState> blockchainStateLoaderCallbacks = new LoaderManager.LoaderCallbacks<BlockchainState>() {
@Override
public Loader<BlockchainState> onCreateLoader(final int id, final Bundle args) {
return new BlockchainStateLoader(activity);
}
@Override
public void onLoadFinished(final Loader<BlockchainState> loader, final BlockchainState blockchainState) {
WalletBalanceFragment.this.blockchainState = blockchainState;
updateView();
}
@Override
public void onLoaderReset(final Loader<BlockchainState> loader) {
}
};
private final LoaderCallbacks<Coin> balanceLoaderCallbacks = new LoaderManager.LoaderCallbacks<Coin>() {
@Override
public Loader<Coin> onCreateLoader(final int id, final Bundle args) {
return new WalletBalanceLoader(activity, wallet);
}
@Override
public void onLoadFinished(final Loader<Coin> loader, final Coin balance) {
WalletBalanceFragment.this.balance = balance;
activity.invalidateOptionsMenu();
updateView();
}
@Override
public void onLoaderReset(final Loader<Coin> loader) {
}
};
private final LoaderCallbacks<Cursor> rateLoaderCallbacks = new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
return new ExchangeRatesLoader(activity, config);
}
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
if (data != null && data.getCount() > 0) {
data.moveToFirst();
exchangeRate = ExchangeRatesProvider.getExchangeRate(data);
updateView();
}
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
}
};
}
10
Source : WalletAddressFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public final clreplaced WalletAddressFragment extends Fragment implements NfcAdapter.CreateNdefMessageCallback {
private Activity activity;
private WalletApplication application;
private Configuration config;
private LoaderManager loaderManager;
@Nullable
private NfcAdapter nfcAdapter;
private ImageView currentAddressQrView;
private BitmapDrawable currentAddressQrBitmap = null;
private AddressAndLabel currentAddressQrAddress = null;
private final AtomicReference<String> currentAddressUriRef = new AtomicReference<String>();
private static final int ID_ADDRESS_LOADER = 0;
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = activity;
this.application = (WalletApplication) activity.getApplication();
this.config = application.getConfiguration();
this.loaderManager = getLoaderManager();
this.nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (nfcAdapter != null && nfcAdapter.isEnabled())
nfcAdapter.setNdefPushMessageCallback(this, activity);
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.wallet_address_fragment, container, false);
currentAddressQrView = (ImageView) view.findViewById(R.id.bitcoin_address_qr);
final CardView currentAddressQrCardView = (CardView) view.findViewById(R.id.bitcoin_address_qr_card);
currentAddressQrCardView.setCardBackgroundColor(Color.WHITE);
currentAddressQrCardView.setPreventCornerOverlap(false);
currentAddressQrCardView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
handleShowQRCode();
}
});
return view;
}
@Override
public void onResume() {
super.onResume();
loaderManager.initLoader(ID_ADDRESS_LOADER, null, addressLoaderCallbacks);
updateView();
}
@Override
public void onPause() {
loaderManager.destroyLoader(ID_ADDRESS_LOADER);
super.onPause();
}
private void updateView() {
currentAddressQrView.setImageDrawable(currentAddressQrBitmap);
}
private void handleShowQRCode() {
WalletAddressDialogFragment.show(getFragmentManager(), currentAddressQrAddress.address, currentAddressQrAddress.label);
}
public static clreplaced CurrentAddressLoader extends AsyncTaskLoader<Address> {
private LocalBroadcastManager broadcastManager;
private final Wallet wallet;
private Configuration config;
private static final Logger log = LoggerFactory.getLogger(WalletBalanceLoader.clreplaced);
public CurrentAddressLoader(final Context context, final Wallet wallet, final Configuration config) {
super(context);
this.broadcastManager = LocalBroadcastManager.getInstance(context.getApplicationContext());
this.wallet = wallet;
this.config = config;
}
@Override
protected void onStartLoading() {
super.onStartLoading();
wallet.addCoinsReceivedEventListener(Threading.SAME_THREAD, walletChangeListener);
wallet.addCoinsSentEventListener(Threading.SAME_THREAD, walletChangeListener);
wallet.addChangeEventListener(Threading.SAME_THREAD, walletChangeListener);
broadcastManager.registerReceiver(walletChangeReceiver, new IntentFilter(WalletApplication.ACTION_WALLET_REFERENCE_CHANGED));
config.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
safeForceLoad();
}
@Override
protected void onStopLoading() {
config.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
broadcastManager.unregisterReceiver(walletChangeReceiver);
wallet.removeChangeEventListener(walletChangeListener);
wallet.removeCoinsSentEventListener(walletChangeListener);
wallet.removeCoinsReceivedEventListener(walletChangeListener);
walletChangeListener.removeCallbacks();
super.onStopLoading();
}
@Override
protected void onReset() {
config.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
broadcastManager.unregisterReceiver(walletChangeReceiver);
wallet.removeChangeEventListener(walletChangeListener);
wallet.removeCoinsSentEventListener(walletChangeListener);
wallet.removeCoinsReceivedEventListener(walletChangeListener);
walletChangeListener.removeCallbacks();
super.onReset();
}
@Override
public Address loadInBackground() {
org.bitcoinj.core.Context.propagate(Constants.CONTEXT);
return wallet.currentReceiveAddress();
}
private final ThrottlingWalletChangeListener walletChangeListener = new ThrottlingWalletChangeListener() {
@Override
public void onThrottledWalletChanged() {
safeForceLoad();
}
};
private final BroadcastReceiver walletChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
safeForceLoad();
}
};
private final OnSharedPreferenceChangeListener preferenceChangeListener = new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if (Configuration.PREFS_KEY_OWN_NAME.equals(key))
safeForceLoad();
}
};
private void safeForceLoad() {
try {
forceLoad();
} catch (final RejectedExecutionException x) {
log.info("rejected execution: " + CurrentAddressLoader.this.toString());
}
}
}
private final LoaderCallbacks<Address> addressLoaderCallbacks = new LoaderManager.LoaderCallbacks<Address>() {
@Override
public Loader<Address> onCreateLoader(final int id, final Bundle args) {
return new CurrentAddressLoader(activity, application.getWallet(), config);
}
@Override
public void onLoadFinished(final Loader<Address> loader, final Address currentAddress) {
if (!currentAddress.equals(currentAddressQrAddress)) {
currentAddressQrAddress = new AddressAndLabel(currentAddress, config.getOwnName());
final String addressStr = BitcoinURI.convertToBitcoinURI(currentAddressQrAddress.address, null, currentAddressQrAddress.label, null);
currentAddressQrBitmap = new BitmapDrawable(getResources(), Qr.bitmap(addressStr));
currentAddressQrBitmap.setFilterBitmap(false);
currentAddressUriRef.set(addressStr);
updateView();
}
}
@Override
public void onLoaderReset(final Loader<Address> loader) {
}
};
@Override
public NdefMessage createNdefMessage(final NfcEvent event) {
final String uri = currentAddressUriRef.get();
if (uri != null)
return new NdefMessage(new NdefRecord[] { NdefRecord.createUri(uri) });
else
return null;
}
}
10
Source : ExchangeRatesFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public final clreplaced ExchangeRatesFragment extends Fragment implements OnSharedPreferenceChangeListener {
private AbstractBindServiceActivity activity;
private WalletApplication application;
private Configuration config;
private Wallet wallet;
private Uri contentUri;
private LoaderManager loaderManager;
private ViewAnimator viewGroup;
private RecyclerView recyclerView;
private ExchangeRatesAdapter adapter;
private String query = null;
@Nullable
private BlockchainState blockchainState = null;
private static final int ID_BALANCE_LOADER = 0;
private static final int ID_RATE_LOADER = 1;
private static final int ID_BLOCKCHAIN_STATE_LOADER = 2;
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractBindServiceActivity) activity;
this.application = (WalletApplication) activity.getApplication();
this.config = application.getConfiguration();
this.wallet = application.getWallet();
this.contentUri = ExchangeRatesProvider.contentUri(activity.getPackageName(), false);
this.loaderManager = getLoaderManager();
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
adapter = new ExchangeRatesAdapter();
adapter.setRateBase(config.getBtcBase());
adapter.setDefaultCurrency(config.getExchangeCurrencyCode());
if (Constants.ENABLE_EXCHANGE_RATES)
loaderManager.initLoader(ID_RATE_LOADER, null, rateLoaderCallbacks);
config.registerOnSharedPreferenceChangeListener(this);
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.exchange_rates_fragment, container, false);
viewGroup = (ViewAnimator) view.findViewById(R.id.exchange_rates_list_group);
recyclerView = (RecyclerView) view.findViewById(R.id.exchange_rates_list);
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
return view;
}
@Override
public void onResume() {
super.onResume();
loaderManager.initLoader(ID_BALANCE_LOADER, null, balanceLoaderCallbacks);
loaderManager.initLoader(ID_BLOCKCHAIN_STATE_LOADER, null, blockchainStateLoaderCallbacks);
}
@Override
public void onPause() {
loaderManager.destroyLoader(ID_BALANCE_LOADER);
loaderManager.destroyLoader(ID_BLOCKCHAIN_STATE_LOADER);
super.onPause();
}
@Override
public void onDestroy() {
config.unregisterOnSharedPreferenceChangeListener(this);
if (Constants.ENABLE_EXCHANGE_RATES)
loaderManager.destroyLoader(ID_RATE_LOADER);
super.onDestroy();
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.exchange_rates_fragment_options, menu);
final MenuItem searchMenuItem = menu.findItem(R.id.exchange_rates_options_search);
if (Constants.ENABLE_EXCHANGE_RATES) {
final SearchView searchView = (SearchView) searchMenuItem.getActionView();
searchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextChange(final String newText) {
query = Strings.emptyToNull(newText.trim());
getLoaderManager().restartLoader(ID_RATE_LOADER, null, rateLoaderCallbacks);
return true;
}
@Override
public boolean onQueryTextSubmit(final String query) {
searchView.clearFocus();
return true;
}
});
// Workaround for not being able to style the SearchView
final int id = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
final View searchInput = searchView.findViewById(id);
if (searchInput instanceof EditText)
((EditText) searchInput).setTextColor(Color.WHITE);
} else {
searchMenuItem.setVisible(false);
}
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if (Configuration.PREFS_KEY_EXCHANGE_CURRENCY.equals(key))
adapter.setDefaultCurrency(config.getExchangeCurrencyCode());
else if (Configuration.PREFS_KEY_BTC_PRECISION.equals(key))
adapter.setRateBase(config.getBtcBase());
}
private final LoaderCallbacks<Cursor> rateLoaderCallbacks = new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
if (query == null)
return new CursorLoader(activity, contentUri, null, null, null, null);
else
return new CursorLoader(activity, contentUri, null, ExchangeRatesProvider.QUERY_PARAM_Q, new String[] { query }, null);
}
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
adapter.setCursor(data);
if (adapter.gereplacedemCount() == 0 && query == null) {
viewGroup.setDisplayedChild(1);
} else if (adapter.gereplacedemCount() == 0 && query != null) {
viewGroup.setDisplayedChild(2);
} else {
viewGroup.setDisplayedChild(3);
final int positionToScrollTo = adapter.getDefaultCurrencyPosition();
if (positionToScrollTo != RecyclerView.NO_POSITION)
recyclerView.scrollToPosition(positionToScrollTo);
if (activity instanceof ExchangeRatesActivity) {
data.moveToPosition(0);
final String source = ExchangeRatesProvider.getExchangeRate(data).source;
activity.getActionBar().setSubreplacedle(source != null ? getString(R.string.exchange_rates_fragment_source, source) : null);
}
}
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
}
};
private final LoaderCallbacks<Coin> balanceLoaderCallbacks = new LoaderManager.LoaderCallbacks<Coin>() {
@Override
public Loader<Coin> onCreateLoader(final int id, final Bundle args) {
return new WalletBalanceLoader(activity, wallet);
}
@Override
public void onLoadFinished(final Loader<Coin> loader, final Coin balance) {
adapter.setBalance(balance);
}
@Override
public void onLoaderReset(final Loader<Coin> loader) {
}
};
private final LoaderCallbacks<BlockchainState> blockchainStateLoaderCallbacks = new LoaderManager.LoaderCallbacks<BlockchainState>() {
@Override
public Loader<BlockchainState> onCreateLoader(final int id, final Bundle args) {
return new BlockchainStateLoader(activity);
}
@Override
public void onLoadFinished(final Loader<BlockchainState> loader, final BlockchainState blockchainState) {
adapter.setBlockchainState(blockchainState);
}
@Override
public void onLoaderReset(final Loader<BlockchainState> loader) {
}
};
private final clreplaced ExchangeRatesAdapter extends RecyclerView.Adapter<ExchangeRateViewHolder> {
private final LayoutInflater inflater = LayoutInflater.from(activity);
private Cursor cursor = null;
private Coin rateBase = Coin.COIN;
@Nullable
private String defaultCurrency = null;
@Nullable
private Coin balance = null;
@Nullable
private BlockchainState blockchainState = null;
private ExchangeRatesAdapter() {
setHreplacedtableIds(true);
}
public void setCursor(final Cursor cursor) {
this.cursor = cursor;
notifyDataSetChanged();
}
public void setDefaultCurrency(final String defaultCurrency) {
this.defaultCurrency = defaultCurrency;
notifyDataSetChanged();
}
public void setRateBase(final Coin rateBase) {
this.rateBase = rateBase;
notifyDataSetChanged();
}
public void setBalance(final Coin balance) {
this.balance = balance;
notifyDataSetChanged();
}
public void setBlockchainState(final BlockchainState blockchainState) {
this.blockchainState = blockchainState;
notifyDataSetChanged();
}
public int getDefaultCurrencyPosition() {
if (cursor == null || defaultCurrency == null)
return RecyclerView.NO_POSITION;
cursor.moveToPosition(-1);
while (cursor.moveToNext()) if (cursor.getString(cursor.getColumnIndexOrThrow(ExchangeRatesProvider.KEY_CURRENCY_CODE)).equals(defaultCurrency))
return cursor.getPosition();
return RecyclerView.NO_POSITION;
}
@Override
public int gereplacedemCount() {
return cursor != null ? cursor.getCount() : 0;
}
@Override
public long gereplacedemId(final int position) {
cursor.moveToPosition(position);
return cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID));
}
@Override
public ExchangeRateViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
return new ExchangeRateViewHolder(inflater.inflate(R.layout.exchange_rate_row, parent, false));
}
@Override
public void onBindViewHolder(final ExchangeRateViewHolder holder, final int position) {
cursor.moveToPosition(position);
final ExchangeRate exchangeRate = ExchangeRatesProvider.getExchangeRate(cursor);
final boolean isDefaultCurrency = exchangeRate.getCurrencyCode().equals(defaultCurrency);
holder.itemView.setBackgroundResource(isDefaultCurrency ? R.color.bg_list_selected : R.color.bg_list);
holder.defaultView.setVisibility(isDefaultCurrency ? View.VISIBLE : View.INVISIBLE);
holder.currencyCodeView.setText(exchangeRate.getCurrencyCode());
holder.rateView.setFormat(!rateBase.isLessThan(Coin.COIN) ? Constants.LOCAL_FORMAT.minDecimals(2) : Constants.LOCAL_FORMAT.minDecimals(4));
holder.rateView.setAmount(exchangeRate.rate.coinToFiat(rateBase));
holder.walletView.setFormat(Constants.LOCAL_FORMAT);
if (balance != null && (blockchainState == null || !blockchainState.replaying)) {
holder.walletView.setAmount(exchangeRate.rate.coinToFiat(balance));
holder.walletView.setStrikeThru(Constants.TEST);
} else {
holder.walletView.setText("n/a");
holder.walletView.setStrikeThru(false);
}
holder.menuView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final PopupMenu popupMenu = new PopupMenu(activity, v);
popupMenu.inflate(R.menu.exchange_rates_context);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(final MenuItem item) {
if (item.gereplacedemId() == R.id.exchange_rates_context_set_as_default) {
setDefaultCurrency(exchangeRate.getCurrencyCode());
config.setExchangeCurrencyCode(exchangeRate.getCurrencyCode());
WalletBalanceWidgetProvider.updateWidgets(activity, wallet);
return true;
} else {
return false;
}
}
});
popupMenu.show();
}
});
}
}
private final clreplaced ExchangeRateViewHolder extends RecyclerView.ViewHolder {
private final View defaultView;
private final TextView currencyCodeView;
private final CurrencyTextView rateView;
private final CurrencyTextView walletView;
private final ImageButton menuView;
public ExchangeRateViewHolder(final View itemView) {
super(itemView);
defaultView = itemView.findViewById(R.id.exchange_rate_row_default);
currencyCodeView = (TextView) itemView.findViewById(R.id.exchange_rate_row_currency_code);
rateView = (CurrencyTextView) itemView.findViewById(R.id.exchange_rate_row_rate);
walletView = (CurrencyTextView) itemView.findViewById(R.id.exchange_rate_row_balance);
menuView = (ImageButton) itemView.findViewById(R.id.exchange_rate_row_menu);
}
}
}
9
Source : BlockListFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public final clreplaced BlockListFragment extends Fragment implements BlockListAdapter.OnClickListener {
private AbstractWalletActivity activity;
private WalletApplication application;
private Configuration config;
private Wallet wallet;
private LoaderManager loaderManager;
private BlockchainService service;
private ViewAnimator viewGroup;
private RecyclerView recyclerView;
private BlockListAdapter adapter;
private static final int ID_BLOCK_LOADER = 0;
private static final int ID_TRANSACTION_LOADER = 1;
private static final int MAX_BLOCKS = 64;
private static final Logger log = LoggerFactory.getLogger(BlockListFragment.clreplaced);
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractWalletActivity) activity;
this.application = this.activity.getWalletApplication();
this.config = application.getConfiguration();
this.wallet = application.getWallet();
this.loaderManager = getLoaderManager();
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
activity.bindService(new Intent(activity, BlockchainServiceImpl.clreplaced), serviceConnection, Context.BIND_AUTO_CREATE);
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
adapter = new BlockListAdapter(activity, wallet, this);
adapter.setFormat(config.getFormat());
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.block_list_fragment, container, false);
viewGroup = (ViewAnimator) view.findViewById(R.id.block_list_group);
recyclerView = (RecyclerView) view.findViewById(R.id.block_list);
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
return view;
}
private boolean resumed = false;
@Override
public void onResume() {
super.onResume();
activity.registerReceiver(tickReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));
loaderManager.initLoader(ID_TRANSACTION_LOADER, null, transactionLoaderCallbacks);
adapter.notifyDataSetChanged();
resumed = true;
}
@Override
public void onPause() {
// workaround: under high load, it can happen that onPause() is called twice (recursively via
// destroyLoader)
if (resumed) {
resumed = false;
loaderManager.destroyLoader(ID_TRANSACTION_LOADER);
activity.unregisterReceiver(tickReceiver);
} else {
log.warn("onPause() called without onResume(), appending stack trace", new RuntimeException());
}
super.onPause();
}
@Override
public void onDestroy() {
activity.unbindService(serviceConnection);
super.onDestroy();
}
@Override
public void onBlockMenuClick(final View view, final StoredBlock block) {
final PopupMenu popupMenu = new PopupMenu(activity, view);
popupMenu.inflate(R.menu.blocks_context);
popupMenu.getMenu().findItem(R.id.blocks_context_browse).setVisible(Constants.ENABLE_BROWSE);
popupMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(final MenuItem item) {
switch(item.gereplacedemId()) {
case R.id.blocks_context_browse:
final String blockHash = block.getHeader().getHashreplacedtring();
final Uri blockExplorerUri = config.getBlockExplorer();
log.info("Viewing block {} on {}", blockHash, blockExplorerUri);
startActivity(new Intent(Intent.ACTION_VIEW, Uri.withAppendedPath(blockExplorerUri, "block/" + blockHash)));
return true;
}
return false;
}
});
popupMenu.show();
}
private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(final ComponentName name, final IBinder binder) {
service = ((BlockchainServiceImpl.LocalBinder) binder).getService();
loaderManager.initLoader(ID_BLOCK_LOADER, null, blockLoaderCallbacks);
}
@Override
public void onServiceDisconnected(final ComponentName name) {
loaderManager.destroyLoader(ID_BLOCK_LOADER);
service = null;
}
};
private final BroadcastReceiver tickReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
adapter.notifyDataSetChanged();
}
};
private static clreplaced BlockLoader extends AsyncTaskLoader<List<StoredBlock>> {
private LocalBroadcastManager broadcastManager;
private BlockchainService service;
private BlockLoader(final Context context, final BlockchainService service) {
super(context);
this.broadcastManager = LocalBroadcastManager.getInstance(context.getApplicationContext());
this.service = service;
}
@Override
protected void onStartLoading() {
super.onStartLoading();
broadcastManager.registerReceiver(broadcastReceiver, new IntentFilter(BlockchainService.ACTION_BLOCKCHAIN_STATE));
forceLoad();
}
@Override
protected void onStopLoading() {
broadcastManager.unregisterReceiver(broadcastReceiver);
super.onStopLoading();
}
@Override
public List<StoredBlock> loadInBackground() {
return service.getRecentBlocks(MAX_BLOCKS);
}
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
try {
forceLoad();
} catch (final RejectedExecutionException x) {
log.info("rejected execution: " + BlockLoader.this.toString());
}
}
};
}
private final LoaderCallbacks<List<StoredBlock>> blockLoaderCallbacks = new LoaderCallbacks<List<StoredBlock>>() {
@Override
public Loader<List<StoredBlock>> onCreateLoader(final int id, final Bundle args) {
return new BlockLoader(activity, service);
}
@Override
public void onLoadFinished(final Loader<List<StoredBlock>> loader, final List<StoredBlock> blocks) {
adapter.replace(blocks);
viewGroup.setDisplayedChild(1);
final Loader<Set<Transaction>> transactionLoader = loaderManager.getLoader(ID_TRANSACTION_LOADER);
if (transactionLoader != null && transactionLoader.isStarted())
transactionLoader.forceLoad();
}
@Override
public void onLoaderReset(final Loader<List<StoredBlock>> loader) {
adapter.clear();
}
};
private static clreplaced TransactionsLoader extends AsyncTaskLoader<Set<Transaction>> {
private final Wallet wallet;
private TransactionsLoader(final Context context, final Wallet wallet) {
super(context);
this.wallet = wallet;
}
@Override
public Set<Transaction> loadInBackground() {
org.bitcoinj.core.Context.propagate(Constants.CONTEXT);
final Set<Transaction> transactions = wallet.getTransactions(true);
final Set<Transaction> filteredTransactions = new HashSet<Transaction>(transactions.size());
for (final Transaction tx : transactions) {
final Map<Sha256Hash, Integer> appearsIn = tx.getAppearsInHashes();
if (// TODO filter by updateTime
appearsIn != null && !appearsIn.isEmpty())
filteredTransactions.add(tx);
}
return filteredTransactions;
}
}
private final LoaderCallbacks<Set<Transaction>> transactionLoaderCallbacks = new LoaderCallbacks<Set<Transaction>>() {
@Override
public Loader<Set<Transaction>> onCreateLoader(final int id, final Bundle args) {
return new TransactionsLoader(activity, wallet);
}
@Override
public void onLoadFinished(final Loader<Set<Transaction>> loader, final Set<Transaction> transactions) {
adapter.replaceTransactions(transactions);
}
@Override
public void onLoaderReset(final Loader<Set<Transaction>> loader) {
adapter.clearTransactions();
}
};
}
8
Source : EarthquakeActivity.java
with MIT License
from AmrDeveloper
with MIT License
from AmrDeveloper
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.earthquake_activity);
// State TextView
state = (TextView) findViewById(R.id.state);
// ProgressBar
loadingBar = (ProgressBar) findViewById(R.id.loadingBar);
// Find a reference to the {@link ListView} in the layout
ListView earthquakeListView = (ListView) findViewById(R.id.list);
// set empty view
earthquakeListView.setEmptyView(findViewById(R.id.state));
// Take context and the list of Earth Quakes
adapter = new QuakeReportAdapter(this, new ArrayList<EarthQuake>());
// Set the adapter on the {@link ListView}
// so the list can be populated in the user interface
earthquakeListView.setAdapter(adapter);
// TODO : Check network Connection
// Get a reference to the ConnectivityManager to check state of network connectivity
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
// Get details on the currently active default data network
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
// If there is a network connection, fetch data
if (networkInfo != null && networkInfo.isConnected()) {
// Get a reference to the LoaderManager, in order to interact with loaders.
LoaderManager loaderManager = getLoaderManager();
// InitLoader and Start
Log.v("Loaders", "run");
getLoaderManager().initLoader(0, null, this);
} else {
// Make Loader Gond
loadingBar.setVisibility(View.GONE);
// Show New State
state.setText(R.string.no_internet_connection);
}
}
8
Source : WorkerFragment.java
with Apache License 2.0
from akhasoft
with Apache License 2.0
from akhasoft
/**
* Please refer to the base method description.
*/
@CallSuper
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (mProgressProvider == null)
mProgressProvider = Core.getDagger().getProgress();
if (mLoadersCounterSave.get() <= 0)
return;
final LoaderManager loaderManager = getLoaderManager();
if (loaderManager == null)
CoreLogger.logError("loaderManager == null");
else {
CoreLogger.log("restore loaders callbacks");
for (final BaseLoaderWrapper baseLoaderWrapper : getLoaders()) {
if (!baseLoaderWrapper.isLoading())
return;
final Loader loader = loaderManager.getLoader(baseLoaderWrapper.getLoaderId());
if (loader != null)
restoreCallbacks(loaderManager, loader.getId(), baseLoaderWrapper);
else
CoreLogger.logError("can not find loader, id " + baseLoaderWrapper.getLoaderId());
}
}
showProgress(mTextSave.get());
mProgress.mLoadersCounter.set(mLoadersCounterSave.get());
mLoadersCounterSave.set(0);
}
4
Source : WalletTransactionsFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public clreplaced WalletTransactionsFragment extends Fragment implements LoaderCallbacks<List<Transaction>>, TransactionsAdapter.OnClickListener, OnSharedPreferenceChangeListener {
public enum Direction {
RECEIVED, SENT
}
private AbstractWalletActivity activity;
private WalletApplication application;
private Configuration config;
private Wallet wallet;
private ContentResolver resolver;
private LoaderManager loaderManager;
private DevicePolicyManager devicePolicyManager;
private ViewAnimator viewGroup;
private TextView emptyView;
private RecyclerView recyclerView;
private TransactionsAdapter adapter;
private MenuItem filterMenuItem;
@Nullable
private Direction direction;
private final Handler handler = new Handler();
private static final int ID_TRANSACTION_LOADER = 0;
private static final String ARG_DIRECTION = "direction";
private static final long THROTTLE_MS = DateUtils.SECOND_IN_MILLIS;
private static final Uri KEY_ROTATION_URI = Uri.parse("https://bitcoin.org/en/alert/2013-08-11-android");
private static final int SHOW_QR_THRESHOLD_BYTES = 2500;
private static final Logger log = LoggerFactory.getLogger(WalletTransactionsFragment.clreplaced);
private final ContentObserver addressBookObserver = new ContentObserver(handler) {
@Override
public void onChange(final boolean selfChange) {
adapter.clearCacheAndNotifyDataSetChanged();
}
};
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractWalletActivity) activity;
this.application = (WalletApplication) activity.getApplication();
this.config = application.getConfiguration();
this.wallet = application.getWallet();
this.resolver = activity.getContentResolver();
this.loaderManager = getLoaderManager();
this.devicePolicyManager = (DevicePolicyManager) application.getSystemService(Context.DEVICE_POLICY_SERVICE);
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
adapter = new TransactionsAdapter(activity, wallet, true, application.maxConnectedPeers(), this);
this.direction = null;
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.wallet_transactions_fragment, container, false);
viewGroup = (ViewAnimator) view.findViewById(R.id.wallet_transactions_group);
emptyView = (TextView) view.findViewById(R.id.wallet_transactions_empty);
recyclerView = (RecyclerView) view.findViewById(R.id.wallet_transactions_list);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
private final int PADDING = 2 * activity.getResources().getDimensionPixelOffset(R.dimen.card_padding_vertical);
@Override
public void gereplacedemOffsets(final Rect outRect, final View view, final RecyclerView parent, final RecyclerView.State state) {
super.gereplacedemOffsets(outRect, view, parent, state);
final int position = parent.getChildAdapterPosition(view);
if (position == 0)
outRect.top += PADDING;
else if (position == parent.getAdapter().gereplacedemCount() - 1)
outRect.bottom += PADDING;
}
});
return view;
}
@Override
public void onResume() {
super.onResume();
resolver.registerContentObserver(AddressBookProvider.contentUri(activity.getPackageName()), true, addressBookObserver);
config.registerOnSharedPreferenceChangeListener(this);
final Bundle args = new Bundle();
args.putSerializable(ARG_DIRECTION, direction);
loaderManager.initLoader(ID_TRANSACTION_LOADER, args, this);
wallet.addCoinsReceivedEventListener(Threading.SAME_THREAD, transactionChangeListener);
wallet.addCoinsSentEventListener(Threading.SAME_THREAD, transactionChangeListener);
wallet.addChangeEventListener(Threading.SAME_THREAD, transactionChangeListener);
wallet.addTransactionConfidenceEventListener(Threading.SAME_THREAD, transactionChangeListener);
updateView();
}
@Override
public void onPause() {
wallet.removeTransactionConfidenceEventListener(transactionChangeListener);
wallet.removeChangeEventListener(transactionChangeListener);
wallet.removeCoinsSentEventListener(transactionChangeListener);
wallet.removeCoinsReceivedEventListener(transactionChangeListener);
transactionChangeListener.removeCallbacks();
loaderManager.destroyLoader(ID_TRANSACTION_LOADER);
config.unregisterOnSharedPreferenceChangeListener(this);
resolver.unregisterContentObserver(addressBookObserver);
super.onPause();
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.wallet_transactions_fragment_options, menu);
filterMenuItem = menu.findItem(R.id.wallet_transactions_options_filter);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onPrepareOptionsMenu(final Menu menu) {
if (direction == null) {
menu.findItem(R.id.wallet_transactions_options_filter_all).setChecked(true);
maybeSetFilterMenuItemIcon(R.drawable.ic_filter_list_white_24dp);
} else if (direction == Direction.RECEIVED) {
menu.findItem(R.id.wallet_transactions_options_filter_received).setChecked(true);
maybeSetFilterMenuItemIcon(R.drawable.transactions_list_filter_received);
} else if (direction == Direction.SENT) {
menu.findItem(R.id.wallet_transactions_options_filter_sent).setChecked(true);
maybeSetFilterMenuItemIcon(R.drawable.transactions_list_filter_sent);
}
super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
final int itemId = item.gereplacedemId();
if (itemId == R.id.wallet_transactions_options_filter_all) {
direction = null;
maybeSetFilterMenuItemIcon(R.drawable.ic_filter_list_white_24dp);
} else if (itemId == R.id.wallet_transactions_options_filter_received) {
direction = Direction.RECEIVED;
maybeSetFilterMenuItemIcon(R.drawable.transactions_list_filter_received);
} else if (itemId == R.id.wallet_transactions_options_filter_sent) {
direction = Direction.SENT;
maybeSetFilterMenuItemIcon(R.drawable.transactions_list_filter_sent);
} else {
return false;
}
item.setChecked(true);
final Bundle args = new Bundle();
args.putSerializable(ARG_DIRECTION, direction);
loaderManager.restartLoader(ID_TRANSACTION_LOADER, args, this);
return true;
}
private void maybeSetFilterMenuItemIcon(final int iconResId) {
// Older Android versions can't deal with width and height in XML layer-list items.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
filterMenuItem.setIcon(iconResId);
}
@Override
public void onTransactionMenuClick(final View view, final Transaction tx) {
final boolean txSent = tx.getValue(wallet).signum() < 0;
final Address txAddress = txSent ? WalletUtils.getToAddressOfSent(tx, wallet) : WalletUtils.getWalletAddressOfReceived(tx, wallet);
final byte[] txSerialized = tx.unsafeBitcoinSerialize();
final boolean txRotation = tx.getPurpose() == Purpose.KEY_ROTATION;
final PopupMenu popupMenu = new PopupMenu(activity, view);
popupMenu.inflate(R.menu.wallet_transactions_context);
final MenuItem editAddressMenuItem = popupMenu.getMenu().findItem(R.id.wallet_transactions_context_edit_address);
if (!txRotation && txAddress != null) {
editAddressMenuItem.setVisible(true);
final boolean isAdd = AddressBookProvider.resolveLabel(activity, txAddress.toBase58()) == null;
final boolean isOwn = wallet.isPubKeyHashMine(txAddress.getHash160());
if (isOwn)
editAddressMenuItem.setreplacedle(isAdd ? R.string.edit_address_book_entry_dialog_replacedle_add_receive : R.string.edit_address_book_entry_dialog_replacedle_edit_receive);
else
editAddressMenuItem.setreplacedle(isAdd ? R.string.edit_address_book_entry_dialog_replacedle_add : R.string.edit_address_book_entry_dialog_replacedle_edit);
} else {
editAddressMenuItem.setVisible(false);
}
popupMenu.getMenu().findItem(R.id.wallet_transactions_context_show_qr).setVisible(!txRotation && txSerialized.length < SHOW_QR_THRESHOLD_BYTES);
popupMenu.getMenu().findItem(R.id.wallet_transactions_context_raise_fee).setVisible(RaiseFeeDialogFragment.feeCanLikelyBeRaised(wallet, tx));
popupMenu.getMenu().findItem(R.id.wallet_transactions_context_browse).setVisible(Constants.ENABLE_BROWSE);
popupMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(final MenuItem item) {
switch(item.gereplacedemId()) {
case R.id.wallet_transactions_context_edit_address:
handleEditAddress(tx);
return true;
case R.id.wallet_transactions_context_show_qr:
handleShowQr();
return true;
case R.id.wallet_transactions_context_raise_fee:
RaiseFeeDialogFragment.show(getFragmentManager(), tx);
return true;
case R.id.wallet_transactions_context_report_issue:
handleReportIssue(tx);
return true;
case R.id.wallet_transactions_context_browse:
if (!txRotation) {
final String txHash = tx.getHashreplacedtring();
final Uri blockExplorerUri = config.getBlockExplorer();
log.info("Viewing transaction {} on {}", txHash, blockExplorerUri);
startActivity(new Intent(Intent.ACTION_VIEW, Uri.withAppendedPath(blockExplorerUri, "tx/" + txHash)));
} else {
startActivity(new Intent(Intent.ACTION_VIEW, KEY_ROTATION_URI));
}
return true;
}
return false;
}
private void handleEditAddress(final Transaction tx) {
EditAddressBookEntryFragment.edit(getFragmentManager(), txAddress);
}
private void handleShowQr() {
final Bitmap qrCodeBitmap = Qr.bitmap(Qr.encodeCompressBinary(txSerialized));
BitmapFragment.show(getFragmentManager(), qrCodeBitmap);
}
private void handleReportIssue(final Transaction tx) {
final ReportIssueDialogBuilder dialog = new ReportIssueDialogBuilder(activity, R.string.report_issue_dialog_replacedle_transaction, R.string.report_issue_dialog_message_issue) {
@Override
protected String subject() {
return Constants.REPORT_SUBJECT_ISSUE + ": " + WalletApplication.versionLine(application.packageInfo());
}
@Override
protected CharSequence collectApplicationInfo() throws IOException {
final StringBuilder applicationInfo = new StringBuilder();
CrashReporter.appendApplicationInfo(applicationInfo, application);
return applicationInfo;
}
@Override
protected CharSequence collectDeviceInfo() throws IOException {
final StringBuilder deviceInfo = new StringBuilder();
CrashReporter.appendDeviceInfo(deviceInfo, activity);
return deviceInfo;
}
@Override
protected CharSequence collectContextualData() {
final StringBuilder contextualData = new StringBuilder();
try {
contextualData.append(tx.getValue(wallet).toFriendlyString()).append(" total value");
} catch (final ScriptException x) {
contextualData.append(x.getMessage());
}
contextualData.append('\n');
if (tx.hasConfidence())
contextualData.append(" confidence: ").append(tx.getConfidence()).append('\n');
contextualData.append(tx.toString());
return contextualData;
}
@Override
protected CharSequence collectWalletDump() {
return application.getWallet().toString(false, true, true, null);
}
};
dialog.show();
}
});
popupMenu.show();
}
@Override
public void onWarningClick() {
switch(warning()) {
case BACKUP:
((WalletActivity) activity).handleBackupWallet();
break;
case STORAGE_ENCRYPTION:
startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS));
break;
}
}
@Override
public Loader<List<Transaction>> onCreateLoader(final int id, final Bundle args) {
return new TransactionsLoader(activity, wallet, (Direction) args.getSerializable(ARG_DIRECTION));
}
@Override
public void onLoadFinished(final Loader<List<Transaction>> loader, final List<Transaction> transactions) {
final Direction direction = ((TransactionsLoader) loader).getDirection();
adapter.replace(transactions);
if (transactions.isEmpty()) {
viewGroup.setDisplayedChild(1);
final SpannableStringBuilder emptyText = new SpannableStringBuilder(getString(direction == Direction.SENT ? R.string.wallet_transactions_fragment_empty_text_sent : R.string.wallet_transactions_fragment_empty_text_received));
emptyText.setSpan(new StyleSpan(Typeface.BOLD), 0, emptyText.length(), SpannableStringBuilder.SPAN_POINT_MARK);
if (direction != Direction.SENT)
emptyText.append("\n\n").append(getString(R.string.wallet_transactions_fragment_empty_text_howto));
emptyView.setText(emptyText);
} else {
viewGroup.setDisplayedChild(2);
}
}
@Override
public void onLoaderReset(final Loader<List<Transaction>> loader) {
// don't clear the adapter, because it will confuse users
}
private final ThrottlingWalletChangeListener transactionChangeListener = new ThrottlingWalletChangeListener(THROTTLE_MS) {
@Override
public void onThrottledWalletChanged() {
adapter.notifyDataSetChanged();
}
};
private static clreplaced TransactionsLoader extends AsyncTaskLoader<List<Transaction>> {
private LocalBroadcastManager broadcastManager;
private final Wallet wallet;
@Nullable
private final Direction direction;
private TransactionsLoader(final Context context, final Wallet wallet, @Nullable final Direction direction) {
super(context);
this.broadcastManager = LocalBroadcastManager.getInstance(context.getApplicationContext());
this.wallet = wallet;
this.direction = direction;
}
@Nullable
public Direction getDirection() {
return direction;
}
@Override
protected void onStartLoading() {
super.onStartLoading();
wallet.addCoinsReceivedEventListener(Threading.SAME_THREAD, transactionAddRemoveListener);
wallet.addCoinsSentEventListener(Threading.SAME_THREAD, transactionAddRemoveListener);
wallet.addChangeEventListener(Threading.SAME_THREAD, transactionAddRemoveListener);
broadcastManager.registerReceiver(walletChangeReceiver, new IntentFilter(WalletApplication.ACTION_WALLET_REFERENCE_CHANGED));
// trigger at least one reload
transactionAddRemoveListener.onReorganize(null);
safeForceLoad();
}
@Override
protected void onStopLoading() {
broadcastManager.unregisterReceiver(walletChangeReceiver);
wallet.removeChangeEventListener(transactionAddRemoveListener);
wallet.removeCoinsSentEventListener(transactionAddRemoveListener);
wallet.removeCoinsReceivedEventListener(transactionAddRemoveListener);
transactionAddRemoveListener.removeCallbacks();
super.onStopLoading();
}
@Override
protected void onReset() {
broadcastManager.unregisterReceiver(walletChangeReceiver);
wallet.removeChangeEventListener(transactionAddRemoveListener);
wallet.removeCoinsSentEventListener(transactionAddRemoveListener);
wallet.removeCoinsReceivedEventListener(transactionAddRemoveListener);
transactionAddRemoveListener.removeCallbacks();
super.onReset();
}
@Override
public List<Transaction> loadInBackground() {
org.bitcoinj.core.Context.propagate(Constants.CONTEXT);
final Set<Transaction> transactions = wallet.getTransactions(true);
final List<Transaction> filteredTransactions = new ArrayList<Transaction>(transactions.size());
for (final Transaction tx : transactions) {
final boolean sent = tx.getValue(wallet).signum() < 0;
final boolean isInternal = tx.getPurpose() == Purpose.KEY_ROTATION;
if ((direction == Direction.RECEIVED && !sent && !isInternal) || direction == null || (direction == Direction.SENT && sent && !isInternal))
filteredTransactions.add(tx);
}
Collections.sort(filteredTransactions, TRANSACTION_COMPARATOR);
return filteredTransactions;
}
private final ThrottlingWalletChangeListener transactionAddRemoveListener = new ThrottlingWalletChangeListener(THROTTLE_MS, true, true, false) {
@Override
public void onThrottledWalletChanged() {
safeForceLoad();
}
};
private final BroadcastReceiver walletChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
safeForceLoad();
}
};
private void safeForceLoad() {
try {
forceLoad();
} catch (final RejectedExecutionException x) {
log.info("rejected execution: " + TransactionsLoader.this.toString());
}
}
private static final Comparator<Transaction> TRANSACTION_COMPARATOR = new Comparator<Transaction>() {
@Override
public int compare(final Transaction tx1, final Transaction tx2) {
final boolean pending1 = tx1.getConfidence().getConfidenceType() == ConfidenceType.PENDING;
final boolean pending2 = tx2.getConfidence().getConfidenceType() == ConfidenceType.PENDING;
if (pending1 != pending2)
return pending1 ? -1 : 1;
final Date updateTime1 = tx1.getUpdateTime();
final long time1 = updateTime1 != null ? updateTime1.getTime() : 0;
final Date updateTime2 = tx2.getUpdateTime();
final long time2 = updateTime2 != null ? updateTime2.getTime() : 0;
if (time1 != time2)
return time1 > time2 ? -1 : 1;
return tx1.getHash().compareTo(tx2.getHash());
}
};
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if (Configuration.PREFS_KEY_BTC_PRECISION.equals(key) || Configuration.PREFS_KEY_REMIND_BACKUP.equals(key))
updateView();
}
private void updateView() {
adapter.setFormat(config.getFormat());
adapter.setWarning(warning());
}
private Warning warning() {
final int storageEncryptionStatus = devicePolicyManager.getStorageEncryptionStatus();
if (config.remindBackup())
return Warning.BACKUP;
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && (storageEncryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE || storageEncryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY))
return Warning.STORAGE_ENCRYPTION;
else
return null;
}
}
4
Source : RaiseFeeDialogFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public clreplaced RaiseFeeDialogFragment extends DialogFragment {
private static final String FRAGMENT_TAG = RaiseFeeDialogFragment.clreplaced.getName();
private static final String KEY_TRANSACTION = "transaction";
public static void show(final FragmentManager fm, final Transaction tx) {
final DialogFragment newFragment = instance(tx);
newFragment.show(fm, FRAGMENT_TAG);
}
private static RaiseFeeDialogFragment instance(final Transaction tx) {
final RaiseFeeDialogFragment fragment = new RaiseFeeDialogFragment();
final Bundle args = new Bundle();
args.putSerializable(KEY_TRANSACTION, tx.getHash().getBytes());
fragment.setArguments(args);
return fragment;
}
private AbstractWalletActivity activity;
private WalletApplication application;
private Configuration config;
private Wallet wallet;
private LoaderManager loaderManager;
private Coin feeRaise = null;
private Transaction transaction;
@Nullable
private AlertDialog dialog;
private TextView messageView;
private View preplacedwordGroup;
private EditText preplacedwordView;
private View badPreplacedwordView;
private Button positiveButton, negativeButton;
private HandlerThread backgroundThread;
private Handler backgroundHandler;
private static final int ID_DYNAMIC_FEES_LOADER = 0;
private enum State {
INPUT, DECRYPTING, DONE
}
private State state = State.INPUT;
private static final Logger log = LoggerFactory.getLogger(RaiseFeeDialogFragment.clreplaced);
private final LoaderCallbacks<Map<FeeCategory, Coin>> dynamicFeesLoaderCallbacks = new LoaderManager.LoaderCallbacks<Map<FeeCategory, Coin>>() {
@Override
public Loader<Map<FeeCategory, Coin>> onCreateLoader(final int id, final Bundle args) {
return new DynamicFeeLoader(activity);
}
@Override
public void onLoadFinished(final Loader<Map<FeeCategory, Coin>> loader, final Map<FeeCategory, Coin> data) {
// We basically have to pay fee for two transactions:
// The transaction to raise the fee of and the CPFP transaction we're about to create.
final int size = transaction.getMessageSize() + 192;
feeRaise = data.get(FeeCategory.PRIORITY).multiply(size).divide(1000);
updateView();
}
@Override
public void onLoaderReset(final Loader<Map<FeeCategory, Coin>> loader) {
}
};
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractWalletActivity) activity;
this.application = (WalletApplication) activity.getApplication();
this.config = application.getConfiguration();
this.wallet = application.getWallet();
this.loaderManager = getLoaderManager();
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle args = getArguments();
final byte[] txHash = (byte[]) args.getSerializable(KEY_TRANSACTION);
transaction = checkNotNull(wallet.getTransaction(Sha256Hash.wrap(txHash)));
backgroundThread = new HandlerThread("backgroundThread", Process.THREAD_PRIORITY_BACKGROUND);
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
loaderManager.initLoader(ID_DYNAMIC_FEES_LOADER, null, dynamicFeesLoaderCallbacks);
}
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final View view = LayoutInflater.from(activity).inflate(R.layout.raise_fee_dialog, null);
messageView = (TextView) view.findViewById(R.id.raise_fee_dialog_message);
preplacedwordGroup = view.findViewById(R.id.raise_fee_dialog_preplacedword_group);
preplacedwordView = (EditText) view.findViewById(R.id.raise_fee_dialog_preplacedword);
preplacedwordView.setText(null);
badPreplacedwordView = view.findViewById(R.id.raise_fee_dialog_bad_preplacedword);
final DialogBuilder builder = new DialogBuilder(activity);
builder.setreplacedle(R.string.raise_fee_dialog_replacedle);
builder.setView(view);
// dummy, just to make it
builder.setPositiveButton(R.string.raise_fee_dialog_button_raise, null);
// show
builder.setNegativeButton(R.string.button_dismiss, null);
builder.setCancelable(false);
final AlertDialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
dialog.setOnShowListener(new OnShowListener() {
@Override
public void onShow(final DialogInterface d) {
positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
negativeButton = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
positiveButton.setTypeface(Typeface.DEFAULT_BOLD);
positiveButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
handleGo();
}
});
negativeButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
dismiss();
}
});
preplacedwordView.addTextChangedListener(texreplacedcher);
RaiseFeeDialogFragment.this.dialog = dialog;
updateView();
}
});
log.info("showing raise fee dialog");
return dialog;
}
@Override
public void onDismiss(final DialogInterface dialog) {
this.dialog = null;
wipePreplacedwords();
super.onDismiss(dialog);
}
@Override
public void onDestroy() {
loaderManager.destroyLoader(ID_DYNAMIC_FEES_LOADER);
backgroundThread.getLooper().quit();
super.onDestroy();
}
private void handleGo() {
state = State.DECRYPTING;
updateView();
if (wallet.isEncrypted()) {
new DeriveKeyTask(backgroundHandler, application.scrypreplacederationsTarget()) {
@Override
protected void onSuccess(final KeyParameter encryptionKey, final boolean wasChanged) {
if (wasChanged)
application.backupWallet();
doRaiseFee(encryptionKey);
}
}.deriveKey(wallet, preplacedwordView.getText().toString().trim());
updateView();
} else {
doRaiseFee(null);
}
}
private void doRaiseFee(final KeyParameter encryptionKey) {
// construct child-pays-for-parent
final TransactionOutput outputToSpend = checkNotNull(findSpendableOutput(wallet, transaction, feeRaise));
final Transaction transactionToSend = new Transaction(Constants.NETWORK_PARAMETERS);
transactionToSend.addInput(outputToSpend);
transactionToSend.addOutput(outputToSpend.getValue().subtract(feeRaise), wallet.freshAddress(KeyPurpose.CHANGE));
transactionToSend.setPurpose(Transaction.Purpose.RAISE_FEE);
final SendRequest sendRequest = SendRequest.forTx(transactionToSend);
sendRequest.aesKey = encryptionKey;
try {
wallet.signTransaction(sendRequest);
log.info("raise fee: cpfp {}", transactionToSend);
wallet.commitTx(transactionToSend);
application.broadcastTransaction(transactionToSend);
state = State.DONE;
updateView();
dismiss();
} catch (final KeyCrypterException x) {
badPreplacedwordView.setVisibility(View.VISIBLE);
state = State.INPUT;
updateView();
preplacedwordView.requestFocus();
log.info("raise fee: bad spending preplacedword");
}
}
private void wipePreplacedwords() {
preplacedwordView.setText(null);
}
private void updateView() {
if (dialog == null)
return;
final boolean needsPreplacedword = wallet.isEncrypted();
if (feeRaise == null) {
messageView.setText(R.string.raise_fee_dialog_determining_fee);
preplacedwordGroup.setVisibility(View.GONE);
} else if (findSpendableOutput(wallet, transaction, feeRaise) == null) {
messageView.setText(R.string.raise_fee_dialog_cant_raise);
preplacedwordGroup.setVisibility(View.GONE);
} else {
messageView.setText(getString(R.string.raise_fee_dialog_message, config.getFormat().format(feeRaise)));
preplacedwordGroup.setVisibility(needsPreplacedword ? View.VISIBLE : View.GONE);
}
if (state == State.INPUT) {
positiveButton.setText(R.string.raise_fee_dialog_button_raise);
positiveButton.setEnabled((!needsPreplacedword || preplacedwordView.getText().toString().trim().length() > 0) && feeRaise != null && findSpendableOutput(wallet, transaction, feeRaise) != null);
negativeButton.setEnabled(true);
} else if (state == State.DECRYPTING) {
positiveButton.setText(R.string.raise_fee_dialog_state_decrypting);
positiveButton.setEnabled(false);
negativeButton.setEnabled(false);
} else if (state == State.DONE) {
positiveButton.setText(R.string.raise_fee_dialog_state_done);
positiveButton.setEnabled(false);
negativeButton.setEnabled(false);
}
}
private final Texreplacedcher texreplacedcher = new Texreplacedcher() {
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
badPreplacedwordView.setVisibility(View.INVISIBLE);
updateView();
}
@Override
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
}
@Override
public void afterTextChanged(final Editable s) {
}
};
public static boolean feeCanLikelyBeRaised(final Wallet wallet, final Transaction transaction) {
if (transaction.getConfidence().getDepthInBlocks() > 0)
return false;
if (WalletUtils.isPayToManyTransaction(transaction))
return false;
// We don't know dynamic fees here, so we need to guess.
if (findSpendableOutput(wallet, transaction, Transaction.DEFAULT_TX_FEE) == null)
return false;
return true;
}
@Nullable
private static TransactionOutput findSpendableOutput(final Wallet wallet, final Transaction transaction, final Coin minimumOutputValue) {
for (final TransactionOutput output : transaction.getOutputs()) {
if (output.isMine(wallet) && output.isAvailableForSpending() && output.getValue().isGreaterThan(minimumOutputValue))
return output;
}
return null;
}
}
3
Source : RequestCoinsFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public final clreplaced RequestCoinsFragment extends Fragment implements NfcAdapter.CreateNdefMessageCallback {
private AbstractBindServiceActivity activity;
private WalletApplication application;
private Configuration config;
private Wallet wallet;
private LoaderManager loaderManager;
private ClipboardManager clipboardManager;
@Nullable
private BluetoothAdapter bluetoothAdapter;
@Nullable
private NfcAdapter nfcAdapter;
private ImageView qrView;
private BitmapDrawable qrCodeBitmap;
private CheckBox acceptBluetoothPaymentView;
private TextView initiateRequestView;
@Nullable
private String bluetoothMac;
@Nullable
private Intent bluetoothServiceIntent;
private AtomicReference<byte[]> paymentRequestRef = new AtomicReference<byte[]>();
private static final int REQUEST_CODE_ENABLE_BLUETOOTH = 0;
private Address address;
private CurrencyCalculatorLink amountCalculatorLink;
private static final int ID_RATE_LOADER = 0;
private static final Logger log = LoggerFactory.getLogger(RequestCoinsFragment.clreplaced);
private final LoaderCallbacks<Cursor> rateLoaderCallbacks = new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
return new ExchangeRatesLoader(activity, config);
}
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
if (data != null && data.getCount() > 0) {
data.moveToFirst();
final ExchangeRate exchangeRate = ExchangeRatesProvider.getExchangeRate(data);
amountCalculatorLink.setExchangeRate(exchangeRate.rate);
updateView();
}
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
}
};
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractBindServiceActivity) activity;
this.application = (WalletApplication) activity.getApplication();
this.config = application.getConfiguration();
this.wallet = application.getWallet();
this.loaderManager = getLoaderManager();
this.clipboardManager = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
this.nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
if (nfcAdapter != null && nfcAdapter.isEnabled())
nfcAdapter.setNdefPushMessageCallback(this, activity);
if (savedInstanceState != null) {
restoreInstanceState(savedInstanceState);
} else {
address = wallet.freshReceiveAddress();
log.info("request coins started: {}", address);
}
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.request_coins_fragment, container, false);
qrView = (ImageView) view.findViewById(R.id.request_coins_qr);
final CardView qrCardView = (CardView) view.findViewById(R.id.request_coins_qr_card);
qrCardView.setCardBackgroundColor(Color.WHITE);
qrCardView.setPreventCornerOverlap(false);
qrCardView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
BitmapFragment.show(getFragmentManager(), qrCodeBitmap.getBitmap());
}
});
final CurrencyAmountView btcAmountView = (CurrencyAmountView) view.findViewById(R.id.request_coins_amount_btc);
btcAmountView.setCurrencySymbol(config.getFormat().code());
btcAmountView.setInputFormat(config.getMaxPrecisionFormat());
btcAmountView.setHintFormat(config.getFormat());
final CurrencyAmountView localAmountView = (CurrencyAmountView) view.findViewById(R.id.request_coins_amount_local);
localAmountView.setInputFormat(Constants.LOCAL_FORMAT);
localAmountView.setHintFormat(Constants.LOCAL_FORMAT);
amountCalculatorLink = new CurrencyCalculatorLink(btcAmountView, localAmountView);
acceptBluetoothPaymentView = (CheckBox) view.findViewById(R.id.request_coins_accept_bluetooth_payment);
acceptBluetoothPaymentView.setVisibility(Bluetooth.canListen(bluetoothAdapter) ? View.VISIBLE : View.GONE);
acceptBluetoothPaymentView.setChecked(Bluetooth.canListen(bluetoothAdapter) && bluetoothAdapter.isEnabled());
acceptBluetoothPaymentView.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
if (Bluetooth.canListen(bluetoothAdapter) && isChecked) {
if (bluetoothAdapter.isEnabled()) {
maybeStartBluetoothListening();
} else {
// ask for permission to enable bluetooth
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), REQUEST_CODE_ENABLE_BLUETOOTH);
}
} else {
stopBluetoothListening();
}
updateView();
}
});
initiateRequestView = (TextView) view.findViewById(R.id.request_coins_fragment_initiate_request);
return view;
}
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
amountCalculatorLink.setExchangeDirection(config.getLastExchangeDirection());
amountCalculatorLink.requestFocus();
}
@Override
public void onResume() {
super.onResume();
amountCalculatorLink.setListener(new CurrencyAmountView.Listener() {
@Override
public void changed() {
updateView();
}
@Override
public void focusChanged(final boolean hasFocus) {
}
});
if (Constants.ENABLE_EXCHANGE_RATES)
loaderManager.initLoader(ID_RATE_LOADER, null, rateLoaderCallbacks);
if (Bluetooth.canListen(bluetoothAdapter) && bluetoothAdapter.isEnabled() && acceptBluetoothPaymentView.isChecked())
maybeStartBluetoothListening();
updateView();
}
@Override
public void onDestroyView() {
super.onDestroyView();
config.setLastExchangeDirection(amountCalculatorLink.getExchangeDirection());
}
@Override
public void onPause() {
loaderManager.destroyLoader(ID_RATE_LOADER);
amountCalculatorLink.setListener(null);
super.onPause();
}
@Override
public void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
saveInstanceState(outState);
}
private void saveInstanceState(final Bundle outState) {
outState.putByteArray("receive_address", address.getHash160());
}
private void restoreInstanceState(final Bundle savedInstanceState) {
address = new Address(Constants.NETWORK_PARAMETERS, savedInstanceState.getByteArray("receive_address"));
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if (requestCode == REQUEST_CODE_ENABLE_BLUETOOTH) {
boolean started = false;
if (resultCode == Activity.RESULT_OK && bluetoothAdapter != null)
started = maybeStartBluetoothListening();
acceptBluetoothPaymentView.setChecked(started);
if (isResumed())
updateView();
}
}
private boolean maybeStartBluetoothListening() {
final String bluetoothAddress = Bluetooth.getAddress(bluetoothAdapter);
if (bluetoothAddress != null) {
bluetoothMac = Bluetooth.compressMac(bluetoothAddress);
bluetoothServiceIntent = new Intent(activity, AcceptBluetoothService.clreplaced);
activity.startService(bluetoothServiceIntent);
return true;
} else {
return false;
}
}
private void stopBluetoothListening() {
if (bluetoothServiceIntent != null) {
activity.stopService(bluetoothServiceIntent);
bluetoothServiceIntent = null;
}
bluetoothMac = null;
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.request_coins_fragment_options, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch(item.gereplacedemId()) {
case R.id.request_coins_options_copy:
handleCopy();
return true;
case R.id.request_coins_options_share:
handleShare();
return true;
case R.id.request_coins_options_local_app:
handleLocalApp();
return true;
}
return super.onOptionsItemSelected(item);
}
private void handleCopy() {
final Uri request = Uri.parse(determineBitcoinRequestStr(false));
clipboardManager.setPrimaryClip(ClipData.newRawUri("Bitcoin payment request", request));
log.info("payment request copied to clipboard: {}", request);
new Toast(activity).toast(R.string.request_coins_clipboard_msg);
}
private void handleShare() {
final String request = determineBitcoinRequestStr(false);
final ShareCompat.IntentBuilder builder = ShareCompat.IntentBuilder.from(activity);
builder.setType("text/plain");
builder.setText(request);
builder.setChooserreplacedle(R.string.request_coins_share_dialog_replacedle);
builder.startChooser();
log.info("payment request shared via intent: {}", request);
}
private void handleLocalApp() {
final ComponentName component = new ComponentName(activity, SendCoinsActivity.clreplaced);
final PackageManager pm = activity.getPackageManager();
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(determineBitcoinRequestStr(false)));
try {
// launch intent chooser with ourselves excluded
pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
startActivity(intent);
} catch (final ActivityNotFoundException x) {
new Toast(activity).longToast(R.string.request_coins_no_local_app_msg);
} finally {
pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}
activity.finish();
}
private void updateView() {
if (!isResumed())
return;
final String bitcoinRequest = determineBitcoinRequestStr(true);
final byte[] paymentRequest = determinePaymentRequest(true);
// update qr-code
qrCodeBitmap = new BitmapDrawable(getResources(), Qr.bitmap(bitcoinRequest));
qrCodeBitmap.setFilterBitmap(false);
qrView.setImageDrawable(qrCodeBitmap);
// update initiate request message
final SpannableStringBuilder initiateText = new SpannableStringBuilder(getString(R.string.request_coins_fragment_initiate_request_qr));
if (nfcAdapter != null && nfcAdapter.isEnabled())
initiateText.append(' ').append(getString(R.string.request_coins_fragment_initiate_request_nfc));
initiateRequestView.setText(initiateText);
// focus linking
final int activeAmountViewId = amountCalculatorLink.activeTextView().getId();
acceptBluetoothPaymentView.setNextFocusUpId(activeAmountViewId);
paymentRequestRef.set(paymentRequest);
}
private String determineBitcoinRequestStr(final boolean includeBluetoothMac) {
final Coin amount = amountCalculatorLink.getAmount();
final String ownName = config.getOwnName();
final StringBuilder uri = new StringBuilder(BitcoinURI.convertToBitcoinURI(address, amount, ownName, null));
if (includeBluetoothMac && bluetoothMac != null) {
uri.append(amount == null && ownName == null ? '?' : '&');
uri.append(Bluetooth.MAC_URI_PARAM).append('=').append(bluetoothMac);
}
return uri.toString();
}
private byte[] determinePaymentRequest(final boolean includeBluetoothMac) {
final Coin amount = amountCalculatorLink.getAmount();
final String paymentUrl = includeBluetoothMac && bluetoothMac != null ? "bt:" + bluetoothMac : null;
return PaymentProtocol.createPaymentRequest(Constants.NETWORK_PARAMETERS, amount, address, config.getOwnName(), paymentUrl, null).build().toByteArray();
}
@Override
public NdefMessage createNdefMessage(final NfcEvent event) {
final byte[] paymentRequest = paymentRequestRef.get();
if (paymentRequest != null)
return new NdefMessage(new NdefRecord[] { Nfc.createMime(PaymentProtocol.MIMETYPE_PAYMENTREQUEST, paymentRequest) });
else
return null;
}
}
0
Source : SweepWalletFragment.java
with Apache License 2.0
from guodroid
with Apache License 2.0
from guodroid
/**
* @author Andreas Schildbach
*/
public clreplaced SweepWalletFragment extends Fragment {
private AbstractBindServiceActivity activity;
private WalletApplication application;
private Configuration config;
private LoaderManager loaderManager;
private FragmentManager fragmentManager;
private final Handler handler = new Handler();
private HandlerThread backgroundThread;
private Handler backgroundHandler;
private State state = State.DECODE_KEY;
private VersionedChecksummedBytes privateKeyToSweep = null;
@Nullable
private Map<FeeCategory, Coin> fees = null;
private Wallet walletToSweep = null;
private Transaction sentTransaction = null;
private TextView messageView;
private View preplacedwordViewGroup;
private EditText preplacedwordView;
private View badPreplacedwordView;
private TextView balanceView;
private View hintView;
private FrameLayout sweepTransactionView;
private TransactionsAdapter sweepTransactionAdapter;
private RecyclerView.ViewHolder sweepTransactionViewHolder;
private Button viewGo;
private Button viewCancel;
private MenuItem reloadAction;
private MenuItem scanAction;
private static final int ID_DYNAMIC_FEES_LOADER = 0;
private static final int REQUEST_CODE_SCAN = 0;
private enum State {
// ask for preplacedword
DECODE_KEY,
// displays balance and asks for confirmation
CONFIRM_SWEEP,
// sending states
PREPARATION,
// sending states
SENDING,
// sending states
SENT,
// sending states
FAILED
}
private static final Logger log = LoggerFactory.getLogger(SweepWalletFragment.clreplaced);
private final LoaderCallbacks<Map<FeeCategory, Coin>> dynamicFeesLoaderCallbacks = new LoaderManager.LoaderCallbacks<Map<FeeCategory, Coin>>() {
@Override
public Loader<Map<FeeCategory, Coin>> onCreateLoader(final int id, final Bundle args) {
return new DynamicFeeLoader(activity);
}
@Override
public void onLoadFinished(final Loader<Map<FeeCategory, Coin>> loader, final Map<FeeCategory, Coin> data) {
fees = data;
updateView();
}
@Override
public void onLoaderReset(final Loader<Map<FeeCategory, Coin>> loader) {
}
};
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
this.activity = (AbstractBindServiceActivity) activity;
this.application = (WalletApplication) activity.getApplication();
this.config = application.getConfiguration();
this.loaderManager = getLoaderManager();
this.fragmentManager = getFragmentManager();
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!Constants.ENABLE_SWEEP_WALLET)
throw new IllegalStateException("ENABLE_SWEEP_WALLET is disabled");
setRetainInstance(true);
setHasOptionsMenu(true);
backgroundThread = new HandlerThread("backgroundThread", Process.THREAD_PRIORITY_BACKGROUND);
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
if (savedInstanceState != null) {
restoreInstanceState(savedInstanceState);
} else {
final Intent intent = activity.getIntent();
if (intent.hasExtra(SweepWalletActivity.INTENT_EXTRA_KEY)) {
privateKeyToSweep = (VersionedChecksummedBytes) intent.getSerializableExtra(SweepWalletActivity.INTENT_EXTRA_KEY);
// delay until fragment is resumed
handler.post(maybeDecodeKeyRunnable);
}
}
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.sweep_wallet_fragment, container);
messageView = (TextView) view.findViewById(R.id.sweep_wallet_fragment_message);
preplacedwordViewGroup = view.findViewById(R.id.sweep_wallet_fragment_preplacedword_group);
preplacedwordView = (EditText) view.findViewById(R.id.sweep_wallet_fragment_preplacedword);
badPreplacedwordView = view.findViewById(R.id.sweep_wallet_fragment_bad_preplacedword);
balanceView = (TextView) view.findViewById(R.id.sweep_wallet_fragment_balance);
hintView = view.findViewById(R.id.sweep_wallet_fragment_hint);
sweepTransactionView = (FrameLayout) view.findViewById(R.id.sweep_wallet_fragment_sent_transaction);
sweepTransactionAdapter = new TransactionsAdapter(activity, application.getWallet(), false, application.maxConnectedPeers(), null);
sweepTransactionViewHolder = sweepTransactionAdapter.createTransactionViewHolder(sweepTransactionView);
sweepTransactionView.addView(sweepTransactionViewHolder.itemView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
viewGo = (Button) view.findViewById(R.id.send_coins_go);
viewGo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
if (state == State.DECODE_KEY)
handleDecrypt();
if (state == State.CONFIRM_SWEEP)
handleSweep();
}
});
viewCancel = (Button) view.findViewById(R.id.send_coins_cancel);
viewCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
activity.finish();
}
});
return view;
}
@Override
public void onResume() {
super.onResume();
loaderManager.initLoader(ID_DYNAMIC_FEES_LOADER, null, dynamicFeesLoaderCallbacks);
updateView();
}
@Override
public void onPause() {
loaderManager.destroyLoader(ID_DYNAMIC_FEES_LOADER);
super.onPause();
}
@Override
public void onDestroy() {
backgroundThread.getLooper().quit();
if (sentTransaction != null)
sentTransaction.getConfidence().removeEventListener(sentTransactionConfidenceListener);
super.onDestroy();
}
@Override
public void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
saveInstanceState(outState);
}
private void saveInstanceState(final Bundle outState) {
outState.putSerializable("state", state);
if (walletToSweep != null)
outState.putByteArray("wallet_to_sweep", WalletUtils.walletToByteArray(walletToSweep));
if (sentTransaction != null)
outState.putSerializable("sent_transaction_hash", sentTransaction.getHash());
}
private void restoreInstanceState(final Bundle savedInstanceState) {
state = (State) savedInstanceState.getSerializable("state");
if (savedInstanceState.containsKey("wallet_to_sweep"))
walletToSweep = WalletUtils.walletFromByteArray(savedInstanceState.getByteArray("wallet_to_sweep"));
if (savedInstanceState.containsKey("sent_transaction_hash")) {
sentTransaction = application.getWallet().getTransaction((Sha256Hash) savedInstanceState.getSerializable("sent_transaction_hash"));
sentTransaction.getConfidence().addEventListener(sentTransactionConfidenceListener);
}
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
if (requestCode == REQUEST_CODE_SCAN) {
if (resultCode == Activity.RESULT_OK) {
final String input = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT);
new StringInputParser(input) {
@Override
protected void handlePrivateKey(final VersionedChecksummedBytes key) {
privateKeyToSweep = key;
setState(State.DECODE_KEY);
maybeDecodeKey();
}
@Override
protected void handlePaymentIntent(final PaymentIntent paymentIntent) {
cannotClreplacedify(input);
}
@Override
protected void handleDirectTransaction(final Transaction transaction) throws VerificationException {
cannotClreplacedify(input);
}
@Override
protected void error(final int messageResId, final Object... messageArgs) {
dialog(activity, null, R.string.button_scan, messageResId, messageArgs);
}
}.parse();
}
}
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.sweep_wallet_fragment_options, menu);
reloadAction = menu.findItem(R.id.sweep_wallet_options_reload);
scanAction = menu.findItem(R.id.sweep_wallet_options_scan);
final PackageManager pm = activity.getPackageManager();
scanAction.setVisible(pm.hreplacedystemFeature(PackageManager.FEATURE_CAMERA) || pm.hreplacedystemFeature(PackageManager.FEATURE_CAMERA_FRONT));
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch(item.gereplacedemId()) {
case R.id.sweep_wallet_options_reload:
handleReload();
return true;
case R.id.sweep_wallet_options_scan:
handleScan();
return true;
}
return super.onOptionsItemSelected(item);
}
private void handleReload() {
if (walletToSweep == null)
return;
requestWalletBalance();
}
private void handleScan() {
startActivityForResult(new Intent(activity, ScanActivity.clreplaced), REQUEST_CODE_SCAN);
}
private final TransactionConfidence.Listener sentTransactionConfidenceListener = new TransactionConfidence.Listener() {
@Override
public void onConfidenceChanged(final TransactionConfidence confidence, final TransactionConfidence.Listener.ChangeReason reason) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (!isResumed())
return;
final TransactionConfidence confidence = sentTransaction.getConfidence();
final TransactionConfidence.ConfidenceType confidenceType = confidence.getConfidenceType();
final int numBroadcastPeers = confidence.numBroadcastPeers();
if (state == State.SENDING) {
if (confidenceType == TransactionConfidence.ConfidenceType.DEAD)
setState(State.FAILED);
else if (numBroadcastPeers > 1 || confidenceType == TransactionConfidence.ConfidenceType.BUILDING)
setState(State.SENT);
}
if (reason == ChangeReason.SEEN_PEERS && confidenceType == TransactionConfidence.ConfidenceType.PENDING) {
// play sound effect
final int soundResId = getResources().getIdentifier("send_coins_broadcast_" + numBroadcastPeers, "raw", activity.getPackageName());
if (soundResId > 0)
RingtoneManager.getRingtone(activity, Uri.parse("android.resource://" + activity.getPackageName() + "/" + soundResId)).play();
}
updateView();
}
});
}
};
private final Runnable maybeDecodeKeyRunnable = new Runnable() {
@Override
public void run() {
maybeDecodeKey();
}
};
private void maybeDecodeKey() {
checkState(state == State.DECODE_KEY);
checkState(privateKeyToSweep != null);
if (privateKeyToSweep instanceof DumpedPrivateKey) {
final ECKey key = ((DumpedPrivateKey) privateKeyToSweep).getKey();
askConfirmSweep(key);
} else if (privateKeyToSweep instanceof BIP38PrivateKey) {
badPreplacedwordView.setVisibility(View.INVISIBLE);
final String preplacedword = preplacedwordView.getText().toString().trim();
// get rid of it asap
preplacedwordView.setText(null);
if (!preplacedword.isEmpty()) {
ProgressDialogFragment.showProgress(fragmentManager, getString(R.string.sweep_wallet_fragment_decrypt_progress));
new DecodePrivateKeyTask(backgroundHandler) {
@Override
protected void onSuccess(ECKey decryptedKey) {
log.info("successfully decoded BIP38 private key");
ProgressDialogFragment.dismissProgress(fragmentManager);
askConfirmSweep(decryptedKey);
}
@Override
protected void onBadPreplacedphrase() {
log.info("failed decoding BIP38 private key (bad preplacedword)");
ProgressDialogFragment.dismissProgress(fragmentManager);
badPreplacedwordView.setVisibility(View.VISIBLE);
preplacedwordView.requestFocus();
}
}.decodePrivateKey((BIP38PrivateKey) privateKeyToSweep, preplacedword);
}
} else {
throw new IllegalStateException("cannot handle type: " + privateKeyToSweep.getClreplaced().getName());
}
}
private void askConfirmSweep(final ECKey key) {
// create non-HD wallet
final KeyChainGroup group = new KeyChainGroup(Constants.NETWORK_PARAMETERS);
group.importKeys(key);
walletToSweep = new Wallet(Constants.NETWORK_PARAMETERS, group);
setState(State.CONFIRM_SWEEP);
// delay until fragment is resumed
handler.post(requestWalletBalanceRunnable);
}
private final Runnable requestWalletBalanceRunnable = new Runnable() {
@Override
public void run() {
requestWalletBalance();
}
};
private static final Comparator<UTXO> UTXO_COMPARATOR = new Comparator<UTXO>() {
@Override
public int compare(final UTXO lhs, final UTXO rhs) {
return ComparisonChain.start().compare(lhs.getHash(), rhs.getHash()).compare(lhs.getIndex(), rhs.getIndex()).result();
}
};
private void requestWalletBalance() {
ProgressDialogFragment.showProgress(fragmentManager, getString(R.string.sweep_wallet_fragment_request_wallet_balance_progress));
final RequestWalletBalanceTask.ResultCallback callback = new RequestWalletBalanceTask.ResultCallback() {
@Override
public void onResult(final Set<UTXO> utxos) {
ProgressDialogFragment.dismissProgress(fragmentManager);
// Filter UTXOs we've already spent and sort the rest.
final Set<Transaction> walletTxns = application.getWallet().getTransactions(false);
final Set<UTXO> sortedUtxos = new TreeSet<>(UTXO_COMPARATOR);
for (final UTXO utxo : utxos) if (!utxoSpentBy(walletTxns, utxo))
sortedUtxos.add(utxo);
// Fake transaction funding the wallet to sweep.
final Map<Sha256Hash, Transaction> fakeTxns = new HashMap<>();
for (final UTXO utxo : sortedUtxos) {
Transaction fakeTx = fakeTxns.get(utxo.getHash());
if (fakeTx == null) {
fakeTx = new FakeTransaction(Constants.NETWORK_PARAMETERS, utxo.getHash());
fakeTx.getConfidence().setConfidenceType(ConfidenceType.BUILDING);
fakeTxns.put(fakeTx.getHash(), fakeTx);
}
final TransactionOutput fakeOutput = new TransactionOutput(Constants.NETWORK_PARAMETERS, fakeTx, utxo.getValue(), utxo.getScript().getProgram());
// Fill with output dummies as needed.
while (fakeTx.getOutputs().size() < utxo.getIndex()) fakeTx.addOutput(new TransactionOutput(Constants.NETWORK_PARAMETERS, fakeTx, Coin.NEGATIVE_SATOSHI, new byte[] {}));
// Add the actual output we will spend later.
fakeTx.addOutput(fakeOutput);
}
walletToSweep.clearTransactions(0);
for (final Transaction tx : fakeTxns.values()) walletToSweep.addWalletTransaction(new WalletTransaction(WalletTransaction.Pool.UNSPENT, tx));
log.info("built wallet to sweep:\n{}", walletToSweep.toString(false, true, false, null));
updateView();
}
private boolean utxoSpentBy(final Set<Transaction> transactions, final UTXO utxo) {
for (final Transaction tx : transactions) {
for (final TransactionInput input : tx.getInputs()) {
final TransactionOutPoint outpoint = input.getOutpoint();
if (outpoint.getHash().equals(utxo.getHash()) && outpoint.getIndex() == utxo.getIndex())
return true;
}
}
return false;
}
@Override
public void onFail(final int messageResId, final Object... messageArgs) {
ProgressDialogFragment.dismissProgress(fragmentManager);
final DialogBuilder dialog = DialogBuilder.warn(activity, R.string.sweep_wallet_fragment_request_wallet_balance_failed_replacedle);
dialog.setMessage(getString(messageResId, messageArgs));
dialog.setPositiveButton(R.string.button_retry, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
requestWalletBalance();
}
});
dialog.setNegativeButton(R.string.button_dismiss, null);
dialog.show();
}
};
final Address address = walletToSweep.getImportedKeys().iterator().next().toAddress(Constants.NETWORK_PARAMETERS);
new RequestWalletBalanceTask(backgroundHandler, callback).requestWalletBalance(activity.getreplacedets(), address);
}
private void setState(final State state) {
this.state = state;
updateView();
}
private void updateView() {
final MonetaryFormat btcFormat = config.getFormat();
if (walletToSweep != null) {
balanceView.setVisibility(View.VISIBLE);
final MonetarySpannable balanceSpannable = new MonetarySpannable(btcFormat, walletToSweep.getBalance(BalanceType.ESTIMATED));
balanceSpannable.applyMarkup(null, null);
final SpannableStringBuilder balance = new SpannableStringBuilder(balanceSpannable);
balance.insert(0, ": ");
balance.insert(0, getString(R.string.sweep_wallet_fragment_balance));
balanceView.setText(balance);
} else {
balanceView.setVisibility(View.GONE);
}
if (state == State.DECODE_KEY && privateKeyToSweep == null) {
messageView.setVisibility(View.VISIBLE);
messageView.setText(R.string.sweep_wallet_fragment_wallet_unknown);
} else if (state == State.DECODE_KEY && privateKeyToSweep != null) {
messageView.setVisibility(View.VISIBLE);
messageView.setText(R.string.sweep_wallet_fragment_encrypted);
} else if (privateKeyToSweep != null) {
messageView.setVisibility(View.GONE);
}
preplacedwordViewGroup.setVisibility(state == State.DECODE_KEY && privateKeyToSweep != null ? View.VISIBLE : View.GONE);
hintView.setVisibility(state == State.DECODE_KEY && privateKeyToSweep == null ? View.VISIBLE : View.GONE);
if (sentTransaction != null) {
sweepTransactionView.setVisibility(View.VISIBLE);
sweepTransactionAdapter.setFormat(btcFormat);
sweepTransactionAdapter.replace(sentTransaction);
sweepTransactionAdapter.bindViewHolder(sweepTransactionViewHolder, 0);
} else {
sweepTransactionView.setVisibility(View.GONE);
}
if (state == State.DECODE_KEY) {
viewCancel.setText(R.string.button_cancel);
viewGo.setText(R.string.sweep_wallet_fragment_button_decrypt);
viewGo.setEnabled(privateKeyToSweep != null);
} else if (state == State.CONFIRM_SWEEP) {
viewCancel.setText(R.string.button_cancel);
viewGo.setText(R.string.sweep_wallet_fragment_button_sweep);
viewGo.setEnabled(walletToSweep != null && walletToSweep.getBalance(BalanceType.ESTIMATED).signum() > 0 && fees != null);
} else if (state == State.PREPARATION) {
viewCancel.setText(R.string.button_cancel);
viewGo.setText(R.string.send_coins_preparation_msg);
viewGo.setEnabled(false);
} else if (state == State.SENDING) {
viewCancel.setText(R.string.send_coins_fragment_button_back);
viewGo.setText(R.string.send_coins_sending_msg);
viewGo.setEnabled(false);
} else if (state == State.SENT) {
viewCancel.setText(R.string.send_coins_fragment_button_back);
viewGo.setText(R.string.send_coins_sent_msg);
viewGo.setEnabled(false);
} else if (state == State.FAILED) {
viewCancel.setText(R.string.send_coins_fragment_button_back);
viewGo.setText(R.string.send_coins_failed_msg);
viewGo.setEnabled(false);
}
viewCancel.setEnabled(state != State.PREPARATION);
// enable actions
if (reloadAction != null)
reloadAction.setEnabled(state == State.CONFIRM_SWEEP && walletToSweep != null);
if (scanAction != null)
scanAction.setEnabled(state == State.DECODE_KEY || state == State.CONFIRM_SWEEP);
}
private void handleDecrypt() {
handler.post(maybeDecodeKeyRunnable);
}
private void handleSweep() {
setState(State.PREPARATION);
final SendRequest sendRequest = SendRequest.emptyWallet(application.getWallet().freshReceiveAddress());
sendRequest.feePerKb = fees.get(FeeCategory.NORMAL);
new SendCoinsOfflineTask(walletToSweep, backgroundHandler) {
@Override
protected void onSuccess(final Transaction transaction) {
sentTransaction = transaction;
setState(State.SENDING);
sentTransaction.getConfidence().addEventListener(sentTransactionConfidenceListener);
application.processDirectTransaction(sentTransaction);
}
@Override
protected void onInsufficientMoney(@Nullable final Coin missing) {
setState(State.FAILED);
showInsufficientMoneyDialog();
}
@Override
protected void onEmptyWalletFailed() {
setState(State.FAILED);
showInsufficientMoneyDialog();
}
@Override
protected void onFailure(final Exception exception) {
setState(State.FAILED);
final DialogBuilder dialog = DialogBuilder.warn(activity, R.string.send_coins_error_msg);
dialog.setMessage(exception.toString());
dialog.setNeutralButton(R.string.button_dismiss, null);
dialog.show();
}
@Override
protected void onInvalidEncryptionKey() {
// cannot happen
throw new RuntimeException();
}
private void showInsufficientMoneyDialog() {
final DialogBuilder dialog = DialogBuilder.warn(activity, R.string.sweep_wallet_fragment_insufficient_money_replacedle);
dialog.setMessage(R.string.sweep_wallet_fragment_insufficient_money_msg);
dialog.setNeutralButton(R.string.button_dismiss, null);
dialog.show();
}
}.sendCoinsOffline(// send asynchronously
sendRequest);
}
private static clreplaced FakeTransaction extends Transaction {
private final Sha256Hash hash;
public FakeTransaction(final NetworkParameters params, final Sha256Hash hash) {
super(params);
this.hash = hash;
}
@Override
public Sha256Hash getHash() {
return hash;
}
}
}