Disabled Jack

I'd love to use Java 8 features, but Jack just isn't ready yet.
This commit is contained in:
Christian Basler 2016-11-03 23:04:41 +01:00
parent 9af80f008d
commit b34e678c68
20 changed files with 499 additions and 364 deletions

View File

@ -20,11 +20,11 @@ android {
targetSdkVersion 25
versionCode 9
versionName "1.0-beta9"
jackOptions.enabled = true
jackOptions.enabled = false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
buildTypes {
release {

View File

@ -37,7 +37,12 @@ public abstract class AbstractItemListFragment<T> extends ListFragment implement
* A dummy implementation of the {@link ListSelectionListener} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static final ListSelectionListener<Object> dummyCallbacks = plaintext -> {
private static final ListSelectionListener<Object> dummyCallbacks =
new ListSelectionListener<Object>() {
@Override
public void onItemSelected(Object item) {
// NO OP
}
};
/**
* The fragment's current callback object, which is notified of list item

View File

@ -18,6 +18,7 @@ package ch.dissem.apps.abit;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
@ -31,6 +32,7 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;
@ -137,7 +139,9 @@ public class AddressDetailFragment extends Fragment {
warning = R.string.delete_contact_warning;
new AlertDialog.Builder(ctx)
.setMessage(warning)
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Singleton.getAddressRepository(ctx).remove(item);
MainActivity mainActivity = MainActivity.getInstance();
if (item.getPrivateKey() != null && mainActivity != null) {
@ -145,6 +149,7 @@ public class AddressDetailFragment extends Fragment {
}
item = null;
ctx.onBackPressed();
}
})
.setNegativeButton(android.R.string.no, null)
.show();
@ -153,7 +158,9 @@ public class AddressDetailFragment extends Fragment {
case R.id.export: {
new AlertDialog.Builder(ctx)
.setMessage(R.string.confirm_export)
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TITLE, item +
@ -164,6 +171,7 @@ public class AddressDetailFragment extends Fragment {
shareIntent.putExtra(Intent.EXTRA_TEXT, exporter.toString
());
startActivity(Intent.createChooser(shareIntent, null));
}
})
.setNegativeButton(android.R.string.no, null)
.show();
@ -225,8 +233,12 @@ public class AddressDetailFragment extends Fragment {
if (item.getPrivateKey() == null) {
Switch active = (Switch) rootView.findViewById(R.id.active);
active.setChecked(item.isSubscribed());
active.setOnCheckedChangeListener((buttonView, isChecked) ->
item.setSubscribed(isChecked));
active.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton button, boolean checked) {
item.setSubscribed(checked);
}
});
ImageView pubkeyAvailableImg = (ImageView) rootView.findViewById(R.id
.pubkey_available);

View File

@ -33,6 +33,7 @@ import android.widget.TextView;
import com.google.zxing.integration.android.IntentIntegrator;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import ch.dissem.apps.abit.listener.ActionBarListener;
@ -56,7 +57,9 @@ public class AddressListFragment extends AbstractItemListFragment<BitmessageAddr
public void updateList() {
List<BitmessageAddress> addresses = Singleton.getAddressRepository(getContext())
.getContacts();
Collections.sort(addresses, (lhs, rhs) -> {
Collections.sort(addresses, new Comparator<BitmessageAddress>() {
@Override
public int compare(BitmessageAddress lhs, BitmessageAddress rhs) {
// Yields the following order:
// * Subscribed addresses come first
// * Addresses with Aliases (alphabetically)
@ -79,6 +82,7 @@ public class AddressListFragment extends AbstractItemListFragment<BitmessageAddr
} else {
return 1;
}
}
});
setListAdapter(new ArrayAdapter<BitmessageAddress>(
getActivity(),

View File

@ -96,7 +96,12 @@ public class ComposeMessageFragment extends Fragment {
final ContactAdapter adapter = new ContactAdapter(getContext());
recipientInput.setAdapter(adapter);
recipientInput.setOnItemClickListener(
(parent, view, position, id) -> recipient = adapter.getItem(position)
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
adapter.getItem(pos);
}
}
);
recipientInput.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override

View File

@ -20,6 +20,7 @@ import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Switch;
@ -60,12 +61,17 @@ public class CreateAddressActivity extends AppCompatActivity {
}
final Button cancel = (Button) findViewById(R.id.cancel);
cancel.setOnClickListener(v -> {
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
setResult(Activity.RESULT_CANCELED);
finish();
}
});
final Button ok = (Button) findViewById(R.id.do_import);
ok.setOnClickListener(v -> {
ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String addressText = String.valueOf(address.getText()).trim();
try {
BitmessageAddress bmAddress = new BitmessageAddress(addressText);
@ -83,6 +89,7 @@ public class CreateAddressActivity extends AppCompatActivity {
} catch (RuntimeException e) {
address.setError(getString(R.string.error_illegal_address));
}
}
});
}

View File

@ -67,7 +67,9 @@ public class ImportIdentitiesFragment extends Fragment {
} catch (IOException e) {
return super.onCreateView(inflater, container, savedInstanceState);
}
view.findViewById(R.id.finish).setOnClickListener(v -> {
view.findViewById(R.id.finish).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
importer.importAll(adapter.getSelected());
MainActivity mainActivity = MainActivity.getInstance();
if (mainActivity != null) {
@ -76,6 +78,7 @@ public class ImportIdentitiesFragment extends Fragment {
}
}
getActivity().finish();
}
});
return view;
}

View File

@ -28,6 +28,7 @@ import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.github.angads25.filepicker.controller.DialogSelectionListener;
import com.github.angads25.filepicker.model.DialogConfigs;
import com.github.angads25.filepicker.model.DialogProperties;
import com.github.angads25.filepicker.view.FilePickerDialog;
@ -60,7 +61,9 @@ public class InputWifFragment extends Fragment {
View view = inflater.inflate(R.layout.fragment_import_input, container, false);
wifData = (TextView) view.findViewById(R.id.wif_input);
view.findViewById(R.id.next).setOnClickListener(v -> {
view.findViewById(R.id.next).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putString(WIF_DATA, wifData.getText().toString());
@ -70,6 +73,7 @@ public class InputWifFragment extends Fragment {
getFragmentManager().beginTransaction()
.replace(R.id.content, fragment)
.commit();
}
});
return view;
}
@ -89,7 +93,9 @@ public class InputWifFragment extends Fragment {
properties.extensions = null;
FilePickerDialog dialog = new FilePickerDialog(getActivity(), properties);
dialog.setTitle(getString(R.string.select_file_title));
dialog.setDialogSelectionListener(files -> {
dialog.setDialogSelectionListener(new DialogSelectionListener() {
@Override
public void onSelectedFilePaths(String[] files) {
if (files.length > 0) {
try (InputStream in = new FileInputStream(files[0])) {
ByteArrayOutputStream data = new ByteArrayOutputStream();
@ -108,6 +114,7 @@ public class InputWifFragment extends Fragment {
).show();
}
}
}
});
dialog.show();
return true;

View File

@ -24,10 +24,12 @@ import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.github.amlcurran.showcaseview.ShowcaseView;
import com.github.amlcurran.showcaseview.targets.Target;
import com.mikepenz.community_material_typeface_library.CommunityMaterial;
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import com.mikepenz.iconics.IconicsDrawable;
@ -35,6 +37,7 @@ import com.mikepenz.materialdrawer.AccountHeader;
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.DrawerBuilder;
import com.mikepenz.materialdrawer.interfaces.OnCheckedChangeListener;
import com.mikepenz.materialdrawer.model.DividerDrawerItem;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
@ -182,13 +185,16 @@ public class MainActivity extends AppCompatActivity
.setStyle(R.style.CustomShowcaseTheme)
.setContentTitle(R.string.full_node)
.setContentText(R.string.full_node_description)
.setTarget(() -> {
.setTarget(new Target() {
@Override
public Point getPoint() {
View view = drawer.getStickyFooter();
int[] location = new int[2];
view.getLocationInWindow(location);
int x = location[0] + 7 * view.getWidth() / 8;
int y = location[1] + view.getHeight() / 2;
return new Point(x, y);
}
})
.replaceEndButton(R.layout.showcase_button)
.hideOnTouchOutside()
@ -246,15 +252,18 @@ public class MainActivity extends AppCompatActivity
.withActivity(this)
.withHeaderBackground(R.drawable.header)
.withProfiles(profiles)
.withOnAccountHeaderListener((view, profile, currentProfile) -> {
.withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() {
@Override
public boolean onProfileChanged(View view, IProfile profile, boolean current) {
switch ((int) profile.getIdentifier()) {
case ADD_IDENTITY:
addIdentityDialog();
break;
case MANAGE_IDENTITY:
BitmessageAddress identity = Singleton.getIdentity(this);
BitmessageAddress identity = Singleton.getIdentity(MainActivity.this);
if (identity == null) {
Toast.makeText(this, R.string.no_identity_warning, LENGTH_LONG).show();
Toast.makeText(MainActivity.this,
R.string.no_identity_warning, LENGTH_LONG).show();
} else {
Intent show = new Intent(MainActivity.this,
AddressDetailActivity.class);
@ -272,6 +281,7 @@ public class MainActivity extends AppCompatActivity
}
// false if it should close the drawer
return false;
}
})
.build();
if (profiles.size() > 2) { // There's always the add and manage identity items
@ -333,11 +343,15 @@ public class MainActivity extends AppCompatActivity
.withName(R.string.full_node)
.withIcon(CommunityMaterial.Icon.cmd_cloud_outline)
.withChecked(isRunning())
.withOnCheckedChangeListener((drawerItem, buttonView, isChecked) -> {
.withOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(IDrawerItem drawerItem, CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
checkAndStartNode();
} else {
stopService(new Intent(this, BitmessageService.class));
stopService(new Intent(MainActivity.this, BitmessageService.class));
}
}
});
@ -347,7 +361,9 @@ public class MainActivity extends AppCompatActivity
.withAccountHeader(accountHeader)
.withDrawerItems(drawerItems)
.addStickyDrawerItems(nodeSwitch)
.withOnDrawerItemClickListener((view, position, item) -> {
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
@Override
public boolean onItemClick(View view, int position, IDrawerItem item) {
if (item.getTag() instanceof Label) {
selectedLabel = (Label) item.getTag();
showSelectedLabel();
@ -377,6 +393,7 @@ public class MainActivity extends AppCompatActivity
}
}
return false;
}
})
.withShowDrawerOnFirstLaunch(true)
.build();
@ -461,11 +478,14 @@ public class MainActivity extends AppCompatActivity
}
public static void updateNodeSwitch() {
MainActivity i = getInstance();
final MainActivity i = getInstance();
if (i != null) {
i.runOnUiThread(() -> {
i.runOnUiThread(new Runnable() {
@Override
public void run() {
i.nodeSwitch.withChecked(i.bmc.isRunning());
i.drawer.updateStickyFooterItem(i.nodeSwitch);
}
});
}
}

View File

@ -31,6 +31,7 @@ import android.widget.TextView;
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import java.util.Iterator;
import java.util.regex.Matcher;
import ch.dissem.apps.abit.listener.ActionBarListener;
import ch.dissem.apps.abit.service.Singleton;
@ -110,7 +111,12 @@ public class MessageDetailFragment extends Fragment {
Linkify.addLinks(messageBody, WEB_URLS);
Linkify.addLinks(messageBody, BITMESSAGE_ADDRESS_PATTERN, BITMESSAGE_URL_SCHEMA, null,
(match, url) -> match.group()
new Linkify.TransformFilter() {
@Override
public String transformUrl(Matcher match, String url) {
return match.group();
}
}
);
messageBody.setLinksClickable(true);

View File

@ -46,7 +46,9 @@ public class SettingsFragment
addPreferencesFromResource(R.xml.preferences);
Preference about = findPreference("about");
about.setOnPreferenceClickListener(preference -> {
about.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
new LibsBuilder()
.withActivityTitle(getActivity().getString(R.string.about))
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
@ -55,12 +57,16 @@ public class SettingsFragment
.withAboutDescription(getString(R.string.about_app))
.start(getActivity());
return true;
}
});
Preference status = findPreference("status");
status.setOnPreferenceClickListener(preference -> {
status.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
startActivity(new Intent(getActivity(), StatusActivity.class));
return true;
}
});
}

View File

@ -21,6 +21,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import java.util.ArrayList;
@ -75,10 +76,13 @@ public class AddressSelectorAdapter
super(v);
checkbox = (CheckBox) v.findViewById(R.id.checkbox);
address = (TextView) v.findViewById(R.id.address);
checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if (data != null) {
data.selected = isChecked;
}
}
});
}
}

View File

@ -105,8 +105,18 @@ public class SwipeableMessageAdapter
}
public SwipeableMessageAdapter() {
itemViewOnClickListener = this::onItemViewClick;
swipeableViewContainerOnClickListener = this::onSwipeableViewContainerClick;
itemViewOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemViewClick(view);
}
};
swipeableViewContainerOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onSwipeableViewContainerClick(view);
}
};
// SwipeableItemAdapter requires stable ID, and also
// have to implement the getItemId() method appropriately.

View File

@ -19,6 +19,7 @@ package ch.dissem.apps.abit.dialog;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
@ -60,7 +61,9 @@ public class AddIdentityDialogFragment extends AppCompatDialogFragment {
getDialog().setTitle(R.string.add_identity);
View view = inflater.inflate(R.layout.dialog_add_identity, container, false);
final RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.radioGroup);
view.findViewById(R.id.ok).setOnClickListener(v -> {
view.findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final Context ctx = getActivity().getBaseContext();
switch (radioGroup.getCheckedRadioButtonId()) {
case R.id.create_identity:
@ -99,8 +102,14 @@ public class AddIdentityDialogFragment extends AppCompatDialogFragment {
return;
}
dismiss();
}
});
view.findViewById(R.id.dismiss).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
view.findViewById(R.id.dismiss).setOnClickListener(v -> dismiss());
return view;
}
@ -113,7 +122,9 @@ public class AddIdentityDialogFragment extends AppCompatDialogFragment {
new AlertDialog.Builder(activity)
.setTitle(R.string.add_chan)
.setView(dialogView)
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
TextView passphrase = (TextView) dialogView.findViewById(R.id.passphrase);
Toast.makeText(ctx, R.string.toast_long_running_operation,
Toast.LENGTH_SHORT).show();
@ -138,6 +149,7 @@ public class AddIdentityDialogFragment extends AppCompatDialogFragment {
}
}
}.execute(passphrase.getText().toString());
}
})
.setNegativeButton(R.string.cancel, null)
.show();

View File

@ -56,10 +56,13 @@ public class DeterministicIdentityDialogFragment extends AppCompatDialogFragment
getDialog().setTitle(R.string.add_deterministic_address);
View view = inflater.inflate(R.layout.dialog_add_deterministic_identity, container, false);
view.findViewById(R.id.ok)
.setOnClickListener(v -> {
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
final Context context = getActivity().getBaseContext();
View dialogView = getView();
assert dialogView != null;
TextView label = (TextView) dialogView.findViewById(R.id.label);
TextView passphrase = (TextView) dialogView.findViewById(R.id.passphrase);
TextView numberOfAddresses = (TextView) dialogView.findViewById(R.id
@ -115,9 +118,14 @@ public class DeterministicIdentityDialogFragment extends AppCompatDialogFragment
Integer.valueOf(numberOfAddresses.getText().toString()),
shorter.isChecked()
);
}
});
view.findViewById(R.id.dismiss).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
view.findViewById(R.id.dismiss)
.setOnClickListener(v -> dismiss());
return view;
}

View File

@ -19,6 +19,7 @@ package ch.dissem.apps.abit.dialog;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import ch.dissem.apps.abit.R;
import ch.dissem.apps.abit.service.BitmessageService;
@ -34,11 +35,19 @@ public class FullNodeDialogActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_full_node);
findViewById(R.id.ok).setOnClickListener(v -> {
startService(new Intent(this, BitmessageService.class));
findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(new Intent(FullNodeDialogActivity.this, BitmessageService.class));
updateNodeSwitch();
finish();
}
});
findViewById(R.id.dismiss).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
findViewById(R.id.dismiss).setOnClickListener(v -> finish());
}
}

View File

@ -48,7 +48,9 @@ public class MessageListener implements BitmessageContext.Listener {
@Override
public void receive(final Plaintext plaintext) {
pool.submit(() -> {
pool.submit(new Runnable() {
@Override
public void run() {
unacknowledged.addFirst(plaintext);
numberOfUnacknowledgedMessages++;
if (unacknowledged.size() > 5) {
@ -66,14 +68,18 @@ public class MessageListener implements BitmessageContext.Listener {
if (main != null) {
main.updateUnread();
}
}
});
}
public void resetNotification() {
pool.submit(() -> {
pool.submit(new Runnable() {
@Override
public void run() {
notification.hide();
unacknowledged.clear();
numberOfUnacknowledgedMessages = 0;
}
});
}
}

View File

@ -17,12 +17,14 @@
package ch.dissem.apps.abit.pow;
import android.content.Context;
import android.support.annotation.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.apps.abit.synchronization.SyncAdapter;
@ -50,16 +52,21 @@ public class ServerPowEngine implements ProofOfWorkEngine, InternalContext
public ServerPowEngine(Context ctx) {
this.ctx = ctx;
pool = Executors.newCachedThreadPool(r -> {
pool = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(@NonNull Runnable r) {
Thread thread = Executors.defaultThreadFactory().newThread(r);
thread.setPriority(Thread.MIN_PRIORITY);
return thread;
}
});
}
@Override
public void calculateNonce(final byte[] initialHash, final byte[] target, Callback callback) {
pool.execute(() -> {
pool.execute(new Runnable() {
@Override
public void run() {
BitmessageAddress identity = Singleton.getIdentity(ctx);
if (identity == null) throw new RuntimeException("No Identity for calculating POW");
@ -79,6 +86,7 @@ public class ServerPowEngine implements ProofOfWorkEngine, InternalContext
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
});
}

View File

@ -92,7 +92,9 @@ public class ProofOfWorkService extends Service {
}
private void calculateNonce(final PowItem item) {
engine.calculateNonce(item.initialHash, item.targetValue, (initialHash, nonce) -> {
engine.calculateNonce(item.initialHash, item.targetValue, new ProofOfWorkEngine.Callback() {
@Override
public void onNonceCalculated(byte[] initialHash, byte[] nonce) {
try {
item.callback.onNonceCalculated(initialHash, nonce);
} finally {
@ -111,6 +113,7 @@ public class ProofOfWorkService extends Service {
calculateNonce(next);
}
}
}
});
}
}

View File

@ -110,9 +110,9 @@ public class Singleton {
return powRepo;
}
public static BitmessageAddress getIdentity(Context ctx) {
public static BitmessageAddress getIdentity(final Context ctx) {
if (identity == null) {
BitmessageContext bmc = getBitmessageContext(ctx);
final BitmessageContext bmc = getBitmessageContext(ctx);
synchronized (Singleton.class) {
if (identity == null) {
List<BitmessageAddress> identities = bmc.addresses()