Code cleanup - most notably BitmessageService was cleaned up and doesn't use messaging anymore
This commit is contained in:
parent
6f6a2e4e6c
commit
c4d76fc8ce
@ -15,7 +15,7 @@
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme">
|
||||
@ -114,7 +114,9 @@
|
||||
android:exported="false"
|
||||
android:syncable="true"/>
|
||||
|
||||
<service android:name=".synchronization.AuthenticatorService">
|
||||
<service
|
||||
android:name=".synchronization.AuthenticatorService"
|
||||
tools:ignore="ExportedService">
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.AccountAuthenticator"/>
|
||||
</intent-filter>
|
||||
@ -125,7 +127,8 @@
|
||||
</service>
|
||||
<service
|
||||
android:name=".synchronization.SyncService"
|
||||
android:exported="true">
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedService">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.SyncAdapter"/>
|
||||
</intent-filter>
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ListFragment;
|
||||
@ -27,7 +26,7 @@ import ch.dissem.apps.abit.listener.ListSelectionListener;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
|
||||
/**
|
||||
* Created by chris on 07.09.15.
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public abstract class AbstractItemListFragment<T> extends ListFragment {
|
||||
/**
|
||||
@ -39,7 +38,8 @@ public abstract class AbstractItemListFragment<T> extends ListFragment {
|
||||
* A dummy implementation of the {@link ListSelectionListener} interface that does
|
||||
* nothing. Used only when this fragment is not attached to an activity.
|
||||
*/
|
||||
private static ListSelectionListener<Object> dummyCallbacks = new ListSelectionListener<Object>() {
|
||||
private static ListSelectionListener<Object> dummyCallbacks = new
|
||||
ListSelectionListener<Object>() {
|
||||
@Override
|
||||
public void onItemSelected(Object plaintext) {
|
||||
}
|
||||
@ -84,11 +84,13 @@ public abstract class AbstractItemListFragment<T> extends ListFragment {
|
||||
super.onAttach(context);
|
||||
|
||||
// Activities containing this fragment must implement its callbacks.
|
||||
if (!(context instanceof ListSelectionListener)) {
|
||||
if (context instanceof ListSelectionListener) {
|
||||
//noinspection unchecked
|
||||
callbacks = (ListSelectionListener) context;
|
||||
} else {
|
||||
throw new IllegalStateException("Activity must implement fragment's callbacks.");
|
||||
}
|
||||
|
||||
callbacks = (ListSelectionListener) context;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,6 +107,7 @@ public abstract class AbstractItemListFragment<T> extends ListFragment {
|
||||
|
||||
// Notify the active callbacks interface (the activity, if the
|
||||
// fragment is attached to one) that an item has been selected.
|
||||
//noinspection unchecked
|
||||
callbacks.onItemSelected((T) listView.getItemAtPosition(position));
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,24 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
/**
|
||||
* Compose a new message.
|
||||
@ -20,6 +35,7 @@ public class ComposeMessageActivity extends AppCompatActivity {
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_action_close);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(false);
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.os.Bundle;
|
||||
@ -8,7 +24,6 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.EditText;
|
||||
|
@ -16,13 +16,12 @@
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
|
||||
import android.graphics.*;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public class Identicon extends Drawable {
|
||||
private static final int SIZE = 9;
|
||||
@ -34,7 +33,6 @@ public class Identicon extends Drawable {
|
||||
|
||||
private float cellWidth;
|
||||
private float cellHeight;
|
||||
private byte[] hash;
|
||||
private int color;
|
||||
private int background;
|
||||
private boolean[][] fields;
|
||||
@ -44,7 +42,7 @@ public class Identicon extends Drawable {
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
hash = input.getRipe();
|
||||
byte[] hash = input.getRipe();
|
||||
|
||||
fields = new boolean[SIZE][SIZE];
|
||||
color = Color.HSVToColor(new float[]{Math.abs(hash[0] * hash[1] + hash[2]) % 360, 0.8f, 1.0f});
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
@ -7,11 +23,7 @@ import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
@ -39,7 +51,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -47,18 +58,16 @@ import java.util.List;
|
||||
import ch.dissem.apps.abit.listener.ActionBarListener;
|
||||
import ch.dissem.apps.abit.listener.ListSelectionListener;
|
||||
import ch.dissem.apps.abit.service.BitmessageService;
|
||||
import ch.dissem.apps.abit.service.BitmessageService.BitmessageBinder;
|
||||
import ch.dissem.apps.abit.service.Singleton;
|
||||
import ch.dissem.apps.abit.synchronization.SyncAdapter;
|
||||
import ch.dissem.apps.abit.util.Preferences;
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import ch.dissem.bitmessage.ports.AddressRepository;
|
||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||
|
||||
import static ch.dissem.apps.abit.service.BitmessageService.DATA_FIELD_IDENTITY;
|
||||
import static ch.dissem.apps.abit.service.BitmessageService.MSG_START_NODE;
|
||||
import static ch.dissem.apps.abit.service.BitmessageService.MSG_STOP_NODE;
|
||||
import static ch.dissem.apps.abit.service.BitmessageService.isRunning;
|
||||
|
||||
|
||||
/**
|
||||
@ -92,14 +101,12 @@ public class MainActivity extends AppCompatActivity
|
||||
*/
|
||||
private boolean twoPane;
|
||||
|
||||
private static IncomingHandler incomingHandler = new IncomingHandler();
|
||||
private static Messenger messenger = new Messenger(incomingHandler);
|
||||
private static Messenger service;
|
||||
private static BitmessageBinder service;
|
||||
private static boolean bound;
|
||||
private static ServiceConnection connection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
MainActivity.service = new Messenger(service);
|
||||
MainActivity.service = (BitmessageBinder) service;
|
||||
MainActivity.bound = true;
|
||||
}
|
||||
|
||||
@ -112,16 +119,15 @@ public class MainActivity extends AppCompatActivity
|
||||
|
||||
private Label selectedLabel;
|
||||
|
||||
private MessageRepository messageRepo;
|
||||
private AddressRepository addressRepo;
|
||||
private BitmessageContext bmc;
|
||||
private BitmessageAddress selectedIdentity;
|
||||
private AccountHeader accountHeader;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
messageRepo = Singleton.getMessageRepository(this);
|
||||
addressRepo = Singleton.getAddressRepository(this);
|
||||
List<Label> labels = messageRepo.getLabels();
|
||||
bmc = Singleton.getBitmessageContext(this);
|
||||
List<Label> labels = bmc.messages().getLabels();
|
||||
if (selectedLabel == null) {
|
||||
selectedLabel = labels.get(0);
|
||||
}
|
||||
@ -179,7 +185,7 @@ public class MainActivity extends AppCompatActivity
|
||||
|
||||
private void createDrawer(Toolbar toolbar, Collection<Label> labels) {
|
||||
final ArrayList<IProfile> profiles = new ArrayList<>();
|
||||
for (BitmessageAddress identity : addressRepo.getIdentities()) {
|
||||
for (BitmessageAddress identity : bmc.addresses().getIdentities()) {
|
||||
LOG.info("Adding identity " + identity.getAddress());
|
||||
profiles.add(new ProfileDrawerItem()
|
||||
.withIcon(new Identicon(identity))
|
||||
@ -212,7 +218,7 @@ public class MainActivity extends AppCompatActivity
|
||||
.withIcon(GoogleMaterial.Icon.gmd_settings)
|
||||
);
|
||||
// Create the AccountHeader
|
||||
AccountHeader accountHeader = new AccountHeaderBuilder()
|
||||
accountHeader = new AccountHeaderBuilder()
|
||||
.withActivity(this)
|
||||
.withHeaderBackground(R.drawable.header)
|
||||
.withProfiles(profiles)
|
||||
@ -221,13 +227,18 @@ public class MainActivity extends AppCompatActivity
|
||||
public boolean onProfileChanged(View view, IProfile profile, boolean
|
||||
currentProfile) {
|
||||
if (profile.getIdentifier() == ADD_IDENTITY) {
|
||||
try {
|
||||
Message message = Message.obtain(null, BitmessageService
|
||||
.MSG_CREATE_IDENTITY);
|
||||
message.replyTo = messenger;
|
||||
service.send(message);
|
||||
} catch (RemoteException e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
BitmessageAddress identity = bmc.createIdentity(false);
|
||||
IProfile newProfile = new ProfileDrawerItem()
|
||||
.withName(identity.toString())
|
||||
.withEmail(identity.getAddress())
|
||||
.withTag(identity);
|
||||
if (accountHeader.getProfiles() != null) {
|
||||
// we know that there are 2 setting elements.
|
||||
// Set the new profile above them ;)
|
||||
accountHeader.addProfile(
|
||||
newProfile, accountHeader.getProfiles().size() - 2);
|
||||
} else {
|
||||
accountHeader.addProfiles(newProfile);
|
||||
}
|
||||
} else if (profile instanceof ProfileDrawerItem) {
|
||||
Object tag = ((ProfileDrawerItem) profile).getTag();
|
||||
@ -243,7 +254,6 @@ public class MainActivity extends AppCompatActivity
|
||||
if (profiles.size() > 2) { // There's always the add and manage identity items
|
||||
accountHeader.setActiveProfile(profiles.get(0), true);
|
||||
}
|
||||
incomingHandler.updateAccountHeader(accountHeader);
|
||||
|
||||
ArrayList<IDrawerItem> drawerItems = new ArrayList<>();
|
||||
for (Label label : labels) {
|
||||
@ -299,23 +309,16 @@ public class MainActivity extends AppCompatActivity
|
||||
new SwitchDrawerItem()
|
||||
.withName(R.string.full_node)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_cloud_outline)
|
||||
.withChecked(BitmessageService.isRunning())
|
||||
.withChecked(isRunning())
|
||||
.withOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(IDrawerItem drawerItem,
|
||||
CompoundButton buttonView,
|
||||
boolean isChecked) {
|
||||
if (messenger != null) {
|
||||
if (isChecked) {
|
||||
checkAndStartNode(buttonView);
|
||||
} else {
|
||||
try {
|
||||
service.send(Message.obtain(null,
|
||||
MSG_STOP_NODE));
|
||||
} catch (RemoteException e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
service.shutdownNode();
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -361,15 +364,17 @@ public class MainActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
private void checkAndStartNode(final CompoundButton buttonView) {
|
||||
if (service == null) return;
|
||||
|
||||
if (Preferences.isConnectionAllowed(MainActivity.this)) {
|
||||
forceStartNode();
|
||||
service.startupNode();
|
||||
} else {
|
||||
new AlertDialog.Builder(MainActivity.this)
|
||||
.setMessage(R.string.full_node_warning)
|
||||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
forceStartNode();
|
||||
service.startupNode();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
|
||||
@ -382,15 +387,6 @@ public class MainActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void forceStartNode() {
|
||||
try {
|
||||
service.send(Message.obtain(null,
|
||||
MSG_START_NODE));
|
||||
} catch (RemoteException e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void showSelectedLabel() {
|
||||
if (getSupportFragmentManager().findFragmentById(R.id.item_list) instanceof
|
||||
MessageListFragment) {
|
||||
@ -476,46 +472,4 @@ public class MainActivity extends AppCompatActivity
|
||||
public BitmessageAddress getSelectedIdentity() {
|
||||
return selectedIdentity;
|
||||
}
|
||||
|
||||
private static class IncomingHandler extends Handler {
|
||||
private WeakReference<AccountHeader> accountHeaderRef;
|
||||
|
||||
private IncomingHandler() {
|
||||
accountHeaderRef = new WeakReference<>(null);
|
||||
}
|
||||
|
||||
public void updateAccountHeader(AccountHeader accountHeader) {
|
||||
accountHeaderRef = new WeakReference<>(accountHeader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case BitmessageService.MSG_CREATE_IDENTITY: {
|
||||
AccountHeader accountHeader = accountHeaderRef.get();
|
||||
if (accountHeader == null) break;
|
||||
|
||||
Serializable data = msg.getData().getSerializable(DATA_FIELD_IDENTITY);
|
||||
if (data instanceof BitmessageAddress) {
|
||||
BitmessageAddress identity = (BitmessageAddress) data;
|
||||
IProfile newProfile = new ProfileDrawerItem()
|
||||
.withName(identity.toString())
|
||||
.withEmail(identity.getAddress())
|
||||
.withTag(identity);
|
||||
if (accountHeader.getProfiles() != null) {
|
||||
//we know that there are 2 setting elements. set the new profile
|
||||
// above them ;)
|
||||
accountHeader.addProfile(newProfile, accountHeader.getProfiles().size
|
||||
() - 2);
|
||||
} else {
|
||||
accountHeader.addProfiles(newProfile);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ public class MessageDetailActivity extends AppCompatActivity {
|
||||
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
// Show the Up button in the action bar.
|
||||
//noinspection ConstantConditions
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// savedInstanceState is non-null when there is fragment state
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.content.Intent;
|
||||
@ -79,7 +95,8 @@ public class MessageDetailFragment extends Fragment {
|
||||
if (item != null) {
|
||||
((TextView) rootView.findViewById(R.id.subject)).setText(item.getSubject());
|
||||
BitmessageAddress sender = item.getFrom();
|
||||
((ImageView) rootView.findViewById(R.id.avatar)).setImageDrawable(new Identicon(sender));
|
||||
((ImageView) rootView.findViewById(R.id.avatar)).setImageDrawable(new Identicon
|
||||
(sender));
|
||||
((TextView) rootView.findViewById(R.id.sender)).setText(sender.toString());
|
||||
if (item.getTo() != null) {
|
||||
((TextView) rootView.findViewById(R.id.recipient)).setText(item.getTo().toString());
|
||||
@ -99,7 +116,6 @@ public class MessageDetailFragment extends Fragment {
|
||||
|
||||
messageBody.setLinksClickable(true);
|
||||
messageBody.setTextIsSelectable(true);
|
||||
}
|
||||
|
||||
boolean removed = false;
|
||||
Iterator<Label> labels = item.getLabels().iterator();
|
||||
@ -112,6 +128,7 @@ public class MessageDetailFragment extends Fragment {
|
||||
if (removed) {
|
||||
Singleton.getMessageRepository(inflater.getContext()).save(item);
|
||||
}
|
||||
}
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@ -121,7 +138,8 @@ public class MessageDetailFragment extends Fragment {
|
||||
|
||||
Drawables.addIcon(getActivity(), menu, R.id.reply, GoogleMaterial.Icon.gmd_reply);
|
||||
Drawables.addIcon(getActivity(), menu, R.id.delete, GoogleMaterial.Icon.gmd_delete);
|
||||
Drawables.addIcon(getActivity(), menu, R.id.mark_unread, GoogleMaterial.Icon.gmd_markunread);
|
||||
Drawables.addIcon(getActivity(), menu, R.id.mark_unread, GoogleMaterial.Icon
|
||||
.gmd_markunread);
|
||||
Drawables.addIcon(getActivity(), menu, R.id.archive, GoogleMaterial.Icon.gmd_archive);
|
||||
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
@ -132,7 +150,8 @@ public class MessageDetailFragment extends Fragment {
|
||||
MessageRepository messageRepo = Singleton.getMessageRepository(getContext());
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.reply:
|
||||
Intent replyIntent = new Intent(getActivity().getApplicationContext(), ComposeMessageActivity.class);
|
||||
Intent replyIntent = new Intent(getActivity().getApplicationContext(),
|
||||
ComposeMessageActivity.class);
|
||||
replyIntent.putExtra(ComposeMessageActivity.EXTRA_RECIPIENT, item.getFrom());
|
||||
replyIntent.putExtra(ComposeMessageActivity.EXTRA_IDENTITY, item.getTo());
|
||||
startActivity(replyIntent);
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.content.Intent;
|
||||
|
@ -17,16 +17,8 @@
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
@ -34,35 +26,11 @@ import android.widget.EditText;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.dissem.apps.abit.service.BitmessageService;
|
||||
import ch.dissem.apps.abit.service.Singleton;
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
import static ch.dissem.apps.abit.service.BitmessageService.DATA_FIELD_ADDRESS;
|
||||
import static ch.dissem.apps.abit.service.BitmessageService.MSG_ADD_CONTACT;
|
||||
import static ch.dissem.apps.abit.service.BitmessageService.MSG_SUBSCRIBE;
|
||||
|
||||
public class OpenBitmessageLinkActivity extends AppCompatActivity {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OpenBitmessageLinkActivity.class);
|
||||
|
||||
private Messenger service;
|
||||
private boolean bound;
|
||||
private ServiceConnection connection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
OpenBitmessageLinkActivity.this.service = new Messenger(service);
|
||||
OpenBitmessageLinkActivity.this.bound = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
service = null;
|
||||
bound = false;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -103,20 +71,11 @@ public class OpenBitmessageLinkActivity extends AppCompatActivity {
|
||||
BitmessageAddress bmAddress = new BitmessageAddress(address);
|
||||
bmAddress.setAlias(label.getText().toString());
|
||||
|
||||
final int what;
|
||||
if (subscribe.isChecked())
|
||||
what = MSG_SUBSCRIBE;
|
||||
else
|
||||
what = MSG_ADD_CONTACT;
|
||||
|
||||
try {
|
||||
Message message = Message.obtain(null, what);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(DATA_FIELD_ADDRESS, bmAddress);
|
||||
message.setData(bundle);
|
||||
service.send(message);
|
||||
} catch (RemoteException e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
BitmessageContext bmc = Singleton.getBitmessageContext(OpenBitmessageLinkActivity
|
||||
.this);
|
||||
bmc.addContact(bmAddress);
|
||||
if (subscribe.isChecked()) {
|
||||
bmc.addSubscribtion(bmAddress);
|
||||
}
|
||||
|
||||
setResult(Activity.RESULT_OK);
|
||||
@ -150,20 +109,4 @@ public class OpenBitmessageLinkActivity extends AppCompatActivity {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
bindService(new Intent(this, BitmessageService.class), connection, Context
|
||||
.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
if (bound) {
|
||||
unbindService(connection);
|
||||
bound = false;
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ public class SettingsActivity extends AppCompatActivity {
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(false);
|
||||
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -1,7 +1,22 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.app.Activity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.widget.TextView;
|
||||
@ -20,6 +35,7 @@ public class StatusActivity extends AppCompatActivity {
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(false);
|
||||
|
||||
|
@ -43,6 +43,7 @@ public class SubscriptionDetailActivity extends AppCompatActivity {
|
||||
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
// Show the Up button in the action bar.
|
||||
//noinspection ConstantConditions
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// savedInstanceState is non-null when there is fragment state
|
||||
|
@ -1,28 +1,23 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import ch.dissem.apps.abit.util.PRNGFixes;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.PlaintextHolder;
|
||||
import ch.dissem.bitmessage.entity.payload.Broadcast;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import ch.dissem.bitmessage.factory.Factory;
|
||||
import ch.dissem.bitmessage.ports.ProofOfWorkEngine;
|
||||
import ch.dissem.bitmessage.cryptography.sc.SpongyCryptography;
|
||||
import ch.dissem.bitmessage.utils.UnixTime;
|
||||
|
||||
import static ch.dissem.apps.abit.util.Constants.PREFERENCE_SERVER_POW;
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Status.SENT;
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.BROADCAST;
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
@ -6,12 +22,9 @@ import android.preference.PreferenceManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import ch.dissem.apps.abit.util.Preferences;
|
||||
import ch.dissem.bitmessage.InternalContext;
|
||||
import ch.dissem.bitmessage.ports.ProofOfWorkEngine;
|
||||
|
||||
import static ch.dissem.apps.abit.util.Constants.PREFERENCE_SERVER_POW;
|
||||
|
||||
/**
|
||||
* Switches between two {@link ProofOfWorkEngine}s depending on the configuration.
|
||||
*
|
||||
|
@ -17,7 +17,7 @@
|
||||
package ch.dissem.apps.abit.listener;
|
||||
|
||||
/**
|
||||
* Created by chris on 06.09.15.
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public interface ActionBarListener {
|
||||
void updateTitle(CharSequence title);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,60 +16,32 @@
|
||||
|
||||
package ch.dissem.apps.abit.listener;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.v7.app.NotificationCompat;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import ch.dissem.apps.abit.notification.NewMessageNotification;
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Listens for decrypted Bitmessage messages. Does show a notification.
|
||||
* <p>
|
||||
* Should show a notification when the app isn't running, but update the message list when it is. Also,
|
||||
* Should show a notification when the app isn't running, but update the message list when it is.
|
||||
* Also,
|
||||
* notifications should be combined.
|
||||
* </p>
|
||||
*/
|
||||
public class MessageListener implements BitmessageContext.Listener {
|
||||
private final Context ctx;
|
||||
private final NotificationManager manager;
|
||||
private final LinkedList<Plaintext> unacknowledged = new LinkedList<>();
|
||||
private final Deque<Plaintext> unacknowledged = new LinkedList<>();
|
||||
private int numberOfUnacknowledgedMessages = 0;
|
||||
private final NewMessageNotification notification;
|
||||
|
||||
public MessageListener(Context ctx) {
|
||||
this.ctx = ctx.getApplicationContext();
|
||||
this.manager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
this.notification = new NewMessageNotification(ctx);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
public static int getMaxContactPhotoSize(final Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
// Note that this URI is safe to call on the UI thread.
|
||||
final Uri uri = ContactsContract.DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI;
|
||||
final String[] projection = new String[]{ContactsContract.DisplayPhoto.DISPLAY_MAX_DIM};
|
||||
final Cursor c = context.getContentResolver().query(uri, projection, null, null, null);
|
||||
try {
|
||||
c.moveToFirst();
|
||||
return c.getInt(0);
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
// fallback: 96x96 is the max contact photo size for pre-ICS versions
|
||||
return 96;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Plaintext plaintext) {
|
||||
synchronized (unacknowledged) {
|
||||
@ -80,7 +52,6 @@ public class MessageListener implements BitmessageContext.Listener {
|
||||
}
|
||||
}
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
|
||||
if (numberOfUnacknowledgedMessages == 1) {
|
||||
notification.singleNotification(plaintext);
|
||||
} else {
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.listener;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.notification;
|
||||
|
||||
import android.app.Notification;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.notification;
|
||||
|
||||
import android.content.Context;
|
||||
@ -7,7 +23,10 @@ import android.support.v7.app.NotificationCompat;
|
||||
import ch.dissem.apps.abit.R;
|
||||
|
||||
/**
|
||||
* Created by chrigu on 29.10.15.
|
||||
* Easily create notifications with error messages. Use carefully, users probably won't like them.
|
||||
* (But they are useful during development/testing)
|
||||
*
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public class ErrorNotification extends AbstractNotification {
|
||||
public static final int ERROR_NOTIFICATION_ID = 4;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.notification;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.notification;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
@ -10,7 +26,7 @@ import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.StyleSpan;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Collection;
|
||||
|
||||
import ch.dissem.apps.abit.Identicon;
|
||||
import ch.dissem.apps.abit.MainActivity;
|
||||
@ -29,8 +45,10 @@ public class NewMessageNotification extends AbstractNotification {
|
||||
|
||||
public NewMessageNotification singleNotification(Plaintext plaintext) {
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
|
||||
Spannable bigText = new SpannableString(plaintext.getSubject() + "\n" + plaintext.getText());
|
||||
bigText.setSpan(SPAN_EMPHASIS, 0, plaintext.getSubject().length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
Spannable bigText = new SpannableString(plaintext.getSubject() + "\n" + plaintext.getText
|
||||
());
|
||||
bigText.setSpan(SPAN_EMPHASIS, 0, plaintext.getSubject().length(), Spanned
|
||||
.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
builder.setSmallIcon(R.drawable.ic_notification_new_message)
|
||||
.setLargeIcon(toBitmap(new Identicon(plaintext.getFrom()), 192))
|
||||
.setContentTitle(plaintext.getFrom().toString())
|
||||
@ -40,27 +58,38 @@ public class NewMessageNotification extends AbstractNotification {
|
||||
|
||||
Intent showMessageIntent = new Intent(ctx, MainActivity.class);
|
||||
showMessageIntent.putExtra(MainActivity.EXTRA_SHOW_MESSAGE, plaintext);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, showMessageIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, showMessageIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setContentIntent(pendingIntent);
|
||||
|
||||
builder.addAction(R.drawable.ic_action_reply, ctx.getString(R.string.reply), pendingIntent);
|
||||
builder.addAction(R.drawable.ic_action_delete, ctx.getString(R.string.delete), pendingIntent);
|
||||
builder.addAction(R.drawable.ic_action_delete, ctx.getString(R.string.delete),
|
||||
pendingIntent);
|
||||
notification = builder.build();
|
||||
return this;
|
||||
}
|
||||
|
||||
public NewMessageNotification multiNotification(LinkedList<Plaintext> unacknowledged, int numberOfUnacknowledgedMessages) {
|
||||
/**
|
||||
* @param unacknowledged will be accessed from different threads, so make sure wherever it's
|
||||
* accessed it will be in a <code>synchronized(unacknowledged)
|
||||
* {}</code> block
|
||||
*/
|
||||
public NewMessageNotification multiNotification(Collection<Plaintext> unacknowledged, int
|
||||
numberOfUnacknowledgedMessages) {
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
|
||||
builder.setSmallIcon(R.drawable.ic_notification_new_message)
|
||||
.setContentTitle(ctx.getString(R.string.n_new_messages, unacknowledged.size()))
|
||||
.setContentText(ctx.getString(R.string.app_name));
|
||||
|
||||
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (unacknowledged) {
|
||||
inboxStyle.setBigContentTitle(ctx.getString(R.string.n_new_messages, numberOfUnacknowledgedMessages));
|
||||
inboxStyle.setBigContentTitle(ctx.getString(R.string.n_new_messages,
|
||||
numberOfUnacknowledgedMessages));
|
||||
for (Plaintext msg : unacknowledged) {
|
||||
Spannable sb = new SpannableString(msg.getFrom() + " " + msg.getSubject());
|
||||
sb.setSpan(SPAN_EMPHASIS, 0, String.valueOf(msg.getFrom()).length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
sb.setSpan(SPAN_EMPHASIS, 0, String.valueOf(msg.getFrom()).length(), Spannable
|
||||
.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
inboxStyle.addLine(sb);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.notification;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.pow;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -21,6 +21,17 @@ import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteConstraintException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.payload.ObjectType;
|
||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||
@ -28,21 +39,6 @@ import ch.dissem.bitmessage.factory.Factory;
|
||||
import ch.dissem.bitmessage.ports.Inventory;
|
||||
import ch.dissem.bitmessage.utils.Encode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static ch.dissem.apps.abit.repository.SqlHelper.join;
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.MINUTE;
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.now;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.repository;
|
||||
|
||||
import android.content.ContentValues;
|
||||
|
@ -1,26 +1,31 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.service;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import ch.dissem.apps.abit.R;
|
||||
import ch.dissem.apps.abit.notification.NetworkNotification;
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
import static ch.dissem.apps.abit.notification.NetworkNotification.ONGOING_NOTIFICATION_ID;
|
||||
|
||||
@ -32,19 +37,6 @@ import static ch.dissem.apps.abit.notification.NetworkNotification.ONGOING_NOTIF
|
||||
public class BitmessageService extends Service {
|
||||
public static final Logger LOG = LoggerFactory.getLogger(BitmessageService.class);
|
||||
|
||||
public static final int MSG_CREATE_IDENTITY = 10;
|
||||
public static final int MSG_SUBSCRIBE = 20;
|
||||
public static final int MSG_ADD_CONTACT = 21;
|
||||
public static final int MSG_SEND_MESSAGE = 30;
|
||||
public static final int MSG_SEND_BROADCAST = 31;
|
||||
public static final int MSG_START_NODE = 100;
|
||||
public static final int MSG_STOP_NODE = 101;
|
||||
|
||||
public static final String DATA_FIELD_IDENTITY = "identity";
|
||||
public static final String DATA_FIELD_ADDRESS = "address";
|
||||
public static final String DATA_FIELD_SUBJECT = "subject";
|
||||
public static final String DATA_FIELD_MESSAGE = "message";
|
||||
|
||||
// Object to use as a thread-safe lock
|
||||
private static final Object lock = new Object();
|
||||
|
||||
@ -53,8 +45,6 @@ public class BitmessageService extends Service {
|
||||
|
||||
private static volatile boolean running = false;
|
||||
|
||||
private static Messenger messenger;
|
||||
|
||||
public static boolean isRunning() {
|
||||
return running && bmc.isRunning();
|
||||
}
|
||||
@ -65,7 +55,6 @@ public class BitmessageService extends Service {
|
||||
if (bmc == null) {
|
||||
bmc = Singleton.getBitmessageContext(this);
|
||||
notification = new NetworkNotification(this, bmc);
|
||||
messenger = new Messenger(new IncomingHandler(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -81,101 +70,34 @@ public class BitmessageService extends Service {
|
||||
running = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an object that allows the system to invoke
|
||||
* the sync adapter.
|
||||
*/
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return messenger.getBinder();
|
||||
return new BitmessageBinder();
|
||||
}
|
||||
|
||||
private static class IncomingHandler extends Handler {
|
||||
private WeakReference<BitmessageService> service;
|
||||
|
||||
private IncomingHandler(BitmessageService service) {
|
||||
this.service = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_CREATE_IDENTITY: {
|
||||
BitmessageAddress identity = bmc.createIdentity(false);
|
||||
if (msg.replyTo != null) {
|
||||
try {
|
||||
Message message = Message.obtain(this, MSG_CREATE_IDENTITY);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(DATA_FIELD_IDENTITY, identity);
|
||||
message.setData(bundle);
|
||||
msg.replyTo.send(message);
|
||||
} catch (RemoteException e) {
|
||||
LOG.debug(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SUBSCRIBE: {
|
||||
Serializable data = msg.getData().getSerializable(DATA_FIELD_ADDRESS);
|
||||
if (data instanceof BitmessageAddress) {
|
||||
bmc.addSubscribtion((BitmessageAddress) data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_ADD_CONTACT: {
|
||||
Serializable data = msg.getData().getSerializable(DATA_FIELD_ADDRESS);
|
||||
if (data instanceof BitmessageAddress) {
|
||||
bmc.addContact((BitmessageAddress) data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SEND_MESSAGE: {
|
||||
Serializable identity = msg.getData().getSerializable(DATA_FIELD_IDENTITY);
|
||||
Serializable address = msg.getData().getSerializable(DATA_FIELD_ADDRESS);
|
||||
if (identity instanceof BitmessageAddress
|
||||
&& address instanceof BitmessageAddress) {
|
||||
String subject = msg.getData().getString(DATA_FIELD_SUBJECT);
|
||||
String message = msg.getData().getString(DATA_FIELD_MESSAGE);
|
||||
bmc.send((BitmessageAddress) identity, (BitmessageAddress) address,
|
||||
subject, message);
|
||||
} else {
|
||||
Context ctx = service.get();
|
||||
Toast.makeText(ctx, "Could not send", Toast.LENGTH_LONG);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SEND_BROADCAST: {
|
||||
Serializable data = msg.getData().getSerializable(DATA_FIELD_IDENTITY);
|
||||
if (data instanceof BitmessageAddress) {
|
||||
String subject = msg.getData().getString(DATA_FIELD_SUBJECT);
|
||||
String message = msg.getData().getString(DATA_FIELD_MESSAGE);
|
||||
bmc.broadcast((BitmessageAddress) data, subject, message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_START_NODE:
|
||||
// TODO: warn user, option to restrict to WiFi
|
||||
// (I'm not quite sure this can be done here, though)
|
||||
service.get().startService(new Intent(service.get(), BitmessageService.class));
|
||||
public class BitmessageBinder extends Binder {
|
||||
public void startupNode() {
|
||||
startService(new Intent(BitmessageService.this, BitmessageService.class));
|
||||
running = true;
|
||||
service.get().startForeground(ONGOING_NOTIFICATION_ID, notification
|
||||
.getNotification());
|
||||
startForeground(ONGOING_NOTIFICATION_ID, notification.getNotification());
|
||||
if (!bmc.isRunning()) {
|
||||
bmc.startup();
|
||||
}
|
||||
notification.show();
|
||||
break;
|
||||
case MSG_STOP_NODE:
|
||||
}
|
||||
|
||||
public void shutdownNode() {
|
||||
if (bmc.isRunning()) {
|
||||
bmc.shutdown();
|
||||
}
|
||||
running = false;
|
||||
service.get().stopForeground(false);
|
||||
service.get().stopSelf();
|
||||
break;
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
stopForeground(false);
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.service;
|
||||
|
||||
import android.app.Service;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.service;
|
||||
|
||||
import android.content.ComponentName;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.service;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.synchronization;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.synchronization;
|
||||
|
||||
import android.app.Service;
|
||||
|
@ -1,9 +1,26 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.synchronization;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/*
|
||||
* Define an implementation of ContentProvider that stubs out
|
||||
@ -25,7 +42,7 @@ public class StubProvider extends ContentProvider {
|
||||
* Return no type for MIME type
|
||||
*/
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
public String getType(@NonNull Uri uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -35,7 +52,7 @@ public class StubProvider extends ContentProvider {
|
||||
*/
|
||||
@Override
|
||||
public Cursor query(
|
||||
Uri uri,
|
||||
@NonNull Uri uri,
|
||||
String[] projection,
|
||||
String selection,
|
||||
String[] selectionArgs,
|
||||
@ -47,7 +64,7 @@ public class StubProvider extends ContentProvider {
|
||||
* insert() always returns null (no URI)
|
||||
*/
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
public Uri insert(@NonNull Uri uri, ContentValues values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -55,7 +72,7 @@ public class StubProvider extends ContentProvider {
|
||||
* delete() always returns "no rows affected" (0)
|
||||
*/
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -63,7 +80,7 @@ public class StubProvider extends ContentProvider {
|
||||
* update() always returns "no rows affected" (0)
|
||||
*/
|
||||
public int update(
|
||||
Uri uri,
|
||||
@NonNull Uri uri,
|
||||
ContentValues values,
|
||||
String selection,
|
||||
String[] selectionArgs) {
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.synchronization;
|
||||
|
||||
import android.accounts.Account;
|
||||
|
@ -1,19 +1,31 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.synchronization;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Define a Service that returns an IBinder for the
|
||||
* sync adapter class, allowing the sync adapter framework to call
|
||||
* onPerformSync().
|
||||
*/
|
||||
public class SyncService extends Service {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SyncService.class);
|
||||
// Storage for an instance of the sync adapter
|
||||
private static SyncAdapter syncAdapter = null;
|
||||
// Object to use as a thread-safe lock
|
||||
|
@ -28,15 +28,6 @@ import java.util.Scanner;
|
||||
* Helper class to work with Assets.
|
||||
*/
|
||||
public class Assets {
|
||||
public static String readToString(Context ctx, String name) {
|
||||
try {
|
||||
InputStream in = ctx.getAssets().open(name);
|
||||
return new Scanner(in, "UTF-8").useDelimiter("\\A").next();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> readSqlStatements(Context ctx, String name) {
|
||||
try {
|
||||
InputStream in = ctx.getAssets().open(name);
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.util;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -32,7 +32,7 @@ import com.mikepenz.iconics.IconicsDrawable;
|
||||
*/
|
||||
public class Drawables {
|
||||
public static void addIcon(Context ctx, Menu menu, int menuItem, GoogleMaterial.Icon icon) {
|
||||
menu.findItem(menuItem).setIcon(new IconicsDrawable(ctx, icon).colorRes(R.color.primary_text_default_material_dark).actionBar());
|
||||
menu.findItem(menuItem).setIcon(new IconicsDrawable(ctx, icon).colorRes(R.color.colorPrimaryDarkText).actionBar());
|
||||
}
|
||||
|
||||
public static Bitmap toBitmap(Identicon identicon, int size) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
package ch.dissem.apps.abit.util;
|
||||
/*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will Google be held liable for any damages
|
||||
@ -9,6 +8,8 @@ package ch.dissem.apps.abit.util;
|
||||
* freely, as long as the origin is not misrepresented.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.util;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
@ -78,7 +79,7 @@ public final class PRNGFixes {
|
||||
// Mix in the device- and invocation-specific seed.
|
||||
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
||||
.getMethod("RAND_seed", byte[].class)
|
||||
.invoke(null, generateSeed());
|
||||
.invoke(null, (Object) generateSeed());
|
||||
|
||||
// Mix output of Linux PRNG into OpenSSL's PRNG
|
||||
int bytesRead = (Integer) Class.forName(
|
||||
@ -169,6 +170,7 @@ public final class PRNGFixes {
|
||||
* {@link SecureRandomSpi} which passes all requests to the Linux PRNG
|
||||
* ({@code /dev/urandom}).
|
||||
*/
|
||||
@SuppressWarnings("JavaDoc")
|
||||
public static class LinuxPRNGSecureRandom extends SecureRandomSpi {
|
||||
|
||||
/*
|
||||
@ -241,6 +243,7 @@ public final class PRNGFixes {
|
||||
synchronized (sLock) {
|
||||
in = getUrandomInputStream();
|
||||
}
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (in) {
|
||||
in.readFully(bytes);
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -1,5 +1,6 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@ -11,7 +12,8 @@
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
android:elevation="4dp" />
|
||||
android:elevation="4dp"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
|
@ -1,5 +1,6 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@ -11,7 +12,8 @@
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
android:elevation="4dp" />
|
||||
android:elevation="4dp"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
|
@ -9,9 +9,8 @@
|
||||
android:id="@+id/address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:text="BM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
tools:text="BM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
android:textSize="10dp"
|
||||
tools:ignore="SpUsage" />
|
||||
|
||||
@ -19,7 +18,6 @@
|
||||
android:id="@+id/label_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@+id/address"
|
||||
android:layout_alignStart="@+id/address"
|
||||
android:layout_below="@+id/address"
|
||||
android:layout_marginTop="16dp">
|
||||
@ -37,7 +35,6 @@
|
||||
android:id="@+id/subscribe"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@+id/address"
|
||||
android:layout_alignStart="@+id/address"
|
||||
android:layout_below="@+id/label_wrapper"
|
||||
android:layout_marginBottom="8dp"
|
||||
@ -50,7 +47,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/subscribe"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:layout_marginTop="12dp"
|
||||
@ -62,7 +58,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@+id/do_import"
|
||||
android:layout_toLeftOf="@+id/do_import"
|
||||
android:layout_toStartOf="@+id/do_import"
|
||||
android:text="@string/cancel" />
|
||||
|
||||
|
@ -33,7 +33,8 @@
|
||||
android:title="@string/status"
|
||||
app:title="@string/status"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
@ -25,41 +25,38 @@
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:src="@color/colorAccent"
|
||||
android:layout_margin="16dp"/>
|
||||
android:layout_margin="16dp"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Name"
|
||||
tools:text="Name"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_alignTop="@+id/avatar"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:paddingTop="0dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingBottom="0dp"
|
||||
android:textStyle="bold"
|
||||
/>
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/address"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="BM-2cW0000000000000000000000000000000"
|
||||
tools:text="BM-2cW0000000000000000000000000000000"
|
||||
android:lines="1"
|
||||
android:ellipsize="marquee"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:layout_alignBottom="@+id/avatar"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"/>
|
||||
|
||||
</RelativeLayout>
|
@ -50,10 +50,9 @@
|
||||
android:lines="1"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:text="BM-XyYxXyYxXyYxXyYxXyYx"
|
||||
tools:text="BM-XyYxXyYxXyYxXyYxXyYx"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="HardcodedText"/>
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stream_number"
|
||||
@ -64,9 +63,8 @@
|
||||
android:lines="1"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:text="Stream #"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
tools:ignore="HardcodedText"/>
|
||||
tools:text="Stream #"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/active"
|
||||
|
@ -14,7 +14,6 @@
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentBottom="true"/>
|
||||
|
||||
@ -26,6 +25,5 @@
|
||||
app:elevation="8dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_margin="16dp"/>
|
||||
</RelativeLayout>
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@ -13,15 +14,15 @@
|
||||
android:id="@+id/subject"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:elegantTextHeight="false"
|
||||
android:enabled="false"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="16dp"
|
||||
android:text="Subject"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
tools:text="Subject"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
@ -34,11 +35,11 @@
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/divider"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@color/colorAccent" />
|
||||
android:src="@color/colorAccent"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sender"
|
||||
@ -46,11 +47,10 @@
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignTop="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:text="Sender"
|
||||
tools:text="Sender"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
@ -59,17 +59,15 @@
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignBottom="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:text="Recipient" />
|
||||
tools:text="Recipient" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/avatar"
|
||||
android:layout_marginLeft="16dp"
|
||||
|
@ -14,7 +14,6 @@
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentBottom="true"/>
|
||||
|
||||
@ -26,6 +25,5 @@
|
||||
app:elevation="8dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_margin="16dp"/>
|
||||
</RelativeLayout>
|
@ -16,6 +16,7 @@
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
@ -23,21 +24,20 @@
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:src="@color/colorAccent"
|
||||
android:layout_margin="16dp"/>
|
||||
android:layout_margin="16dp"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sender"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sender"
|
||||
tools:text="Sender"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_alignTop="@+id/avatar"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:layout_marginTop="-5dp"
|
||||
android:paddingTop="0dp"
|
||||
@ -51,21 +51,20 @@
|
||||
android:id="@+id/subject"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Subject"
|
||||
tools:text="Subject"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:layout_below="@+id/sender"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Text"
|
||||
tools:text="Text"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
@ -74,7 +73,6 @@
|
||||
android:paddingRight="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:layout_below="@+id/subject"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"/>
|
||||
|
||||
</RelativeLayout>
|
@ -17,6 +17,7 @@
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
@ -25,21 +26,20 @@
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:src="@color/colorAccent"
|
||||
android:layout_margin="16dp"/>
|
||||
android:layout_margin="16dp"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Name"
|
||||
tools:text="Name"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_alignTop="@+id/avatar"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:paddingTop="0dp"
|
||||
android:paddingLeft="8dp"
|
||||
@ -52,14 +52,13 @@
|
||||
android:id="@+id/stream_number"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Stream #"
|
||||
tools:text="Stream #"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:layout_alignBottom="@+id/avatar"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"/>
|
||||
|
||||
<com.mikepenz.iconics.view.IconicsImageView
|
||||
@ -69,8 +68,7 @@
|
||||
app:iiv_color="@android:color/black"
|
||||
app:iiv_icon="cmd-rss"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="16dp"/>
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
</RelativeLayout>
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
@ -27,7 +28,8 @@
|
||||
android:elevation="4dp"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
|
@ -5,5 +5,5 @@
|
||||
android:id="@+id/send"
|
||||
app:showAsAction="always"
|
||||
android:icon="@drawable/ic_action_send"
|
||||
android:title="@string/send"/>`
|
||||
android:title="@string/send"/>
|
||||
</menu>
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
</menu>
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="define_jabit" translatable="false"></string>
|
||||
<string name="define_jabit" translatable="false"/>
|
||||
<!-- Author section -->
|
||||
<string name="library_jabit_author" translatable="false">Christian Basler</string>
|
||||
<string name="library_jabit_authorWebsite" translatable="false">dissem.ch</string>
|
||||
|
Loading…
Reference in New Issue
Block a user