Example usage for android.text TextUtils join

List of usage examples for android.text TextUtils join

Introduction

In this page you can find the example usage for android.text TextUtils join.

Prototype

public static String join(@NonNull CharSequence delimiter, @NonNull Iterable tokens) 

Source Link

Document

Returns a string containing the tokens joined by delimiters.

Usage

From source file:com.facebook.Request.java

private void serializeToBatch(JSONArray batch, Map<String, Attachment> attachments)
        throws JSONException, IOException {
    JSONObject batchEntry = new JSONObject();

    if (this.batchEntryName != null) {
        batchEntry.put(BATCH_ENTRY_NAME_PARAM, this.batchEntryName);
        batchEntry.put(BATCH_ENTRY_OMIT_RESPONSE_ON_SUCCESS_PARAM, this.batchEntryOmitResultOnSuccess);
    }/*from w w w  .  j a va  2  s. c  o m*/
    if (this.batchEntryDependsOn != null) {
        batchEntry.put(BATCH_ENTRY_DEPENDS_ON_PARAM, this.batchEntryDependsOn);
    }

    String relativeURL = getUrlForBatchedRequest();
    batchEntry.put(BATCH_RELATIVE_URL_PARAM, relativeURL);
    batchEntry.put(BATCH_METHOD_PARAM, httpMethod);
    if (this.session != null) {
        String accessToken = this.session.getAccessToken();
        Logger.registerAccessToken(accessToken);
    }

    // Find all of our attachments. Remember their names and put them in the attachment map.
    ArrayList<String> attachmentNames = new ArrayList<String>();
    Set<String> keys = this.parameters.keySet();
    for (String key : keys) {
        Object value = this.parameters.get(key);
        if (isSupportedAttachmentType(value)) {
            // Make the name unique across this entire batch.
            String name = String.format("%s%d", ATTACHMENT_FILENAME_PREFIX, attachments.size());
            attachmentNames.add(name);
            attachments.put(name, new Attachment(this, value));
        }
    }

    if (!attachmentNames.isEmpty()) {
        String attachmentNamesString = TextUtils.join(",", attachmentNames);
        batchEntry.put(ATTACHED_FILES_PARAM, attachmentNamesString);
    }

    if (this.graphObject != null) {
        // Serialize the graph object into the "body" parameter.
        final ArrayList<String> keysAndValues = new ArrayList<String>();
        processGraphObject(this.graphObject, relativeURL, new KeyValueSerializer() {
            @Override
            public void writeString(String key, String value) throws IOException {
                keysAndValues.add(String.format("%s=%s", key, URLEncoder.encode(value, "UTF-8")));
            }
        });
        String bodyValue = TextUtils.join("&", keysAndValues);
        batchEntry.put(BATCH_BODY_PARAM, bodyValue);
    }

    batch.put(batchEntry);
}

From source file:eu.faircode.adblocker.ServiceSinkhole.java

private void showAccessNotification(int uid) {
    String name = TextUtils.join(", ", Util.getApplicationNames(uid, ServiceSinkhole.this));

    Intent main = new Intent(ServiceSinkhole.this, ActivityMain.class);
    main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
    PendingIntent pi = PendingIntent.getActivity(ServiceSinkhole.this, uid + 10000, main,
            PendingIntent.FLAG_UPDATE_CURRENT);

    TypedValue tv = new TypedValue();
    getTheme().resolveAttribute(R.attr.colorOn, tv, true);
    int colorOn = tv.data;
    getTheme().resolveAttribute(R.attr.colorOff, tv, true);
    int colorOff = tv.data;

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_cloud_upload_white_24dp).setGroup("AccessAttempt")
            .setContentTitle(getString(R.string.app_name)).setContentText(getString(R.string.msg_access, name))
            .setContentIntent(pi).setColor(colorOff).setOngoing(false).setAutoCancel(true);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        builder.setCategory(Notification.CATEGORY_STATUS).setVisibility(Notification.VISIBILITY_SECRET);
    }//from  ww w.  j ava  2 s.  co m

    DateFormat df = new SimpleDateFormat("dd HH:mm");

    NotificationCompat.InboxStyle notification = new NotificationCompat.InboxStyle(builder);
    String sname = getString(R.string.msg_access, name);
    int pos = sname.indexOf(name);
    Spannable sp = new SpannableString(sname);
    sp.setSpan(new StyleSpan(Typeface.BOLD), pos, pos + name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    notification.addLine(sp);

    Cursor cursor = DatabaseHelper.getInstance(ServiceSinkhole.this).getAccessUnset(uid, 7);
    int colDAddr = cursor.getColumnIndex("daddr");
    int colTime = cursor.getColumnIndex("time");
    int colAllowed = cursor.getColumnIndex("allowed");
    while (cursor.moveToNext()) {
        StringBuilder sb = new StringBuilder();
        sb.append(df.format(cursor.getLong(colTime))).append(' ');

        String daddr = cursor.getString(colDAddr);
        if (Util.isNumericAddress(daddr))
            try {
                daddr = InetAddress.getByName(daddr).getHostName();
            } catch (UnknownHostException ignored) {
            }
        sb.append(daddr);

        int allowed = cursor.getInt(colAllowed);
        if (allowed >= 0) {
            pos = sb.indexOf(daddr);
            sp = new SpannableString(sb);
            ForegroundColorSpan fgsp = new ForegroundColorSpan(allowed > 0 ? colorOn : colorOff);
            sp.setSpan(fgsp, pos, pos + daddr.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        notification.addLine(sp);
    }
    cursor.close();

    NotificationManagerCompat.from(this).notify(uid + 10000, notification.build());
}

From source file:eu.faircode.netguard.ServiceSinkhole.java

public void notifyNewApplication(int uid) {
    if (uid < 0)
        return;/*from   w  ww.  j av  a 2 s  .c  o m*/

    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
    try {
        // Get application name
        String name = TextUtils.join(", ", Util.getApplicationNames(uid, this));

        // Get application info
        PackageManager pm = getPackageManager();
        String[] packages = pm.getPackagesForUid(uid);
        if (packages == null || packages.length < 1)
            throw new PackageManager.NameNotFoundException(Integer.toString(uid));
        boolean internet = Util.hasInternet(uid, this);

        // Build notification
        Intent main = new Intent(this, ActivityMain.class);
        main.putExtra(ActivityMain.EXTRA_REFRESH, true);
        main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
        PendingIntent pi = PendingIntent.getActivity(this, uid, main, PendingIntent.FLAG_UPDATE_CURRENT);

        TypedValue tv = new TypedValue();
        getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_security_white_24dp).setContentIntent(pi).setColor(tv.data)
                .setAutoCancel(true);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
            builder.setContentTitle(name).setContentText(getString(R.string.msg_installed_n));
        else
            builder.setContentTitle(getString(R.string.app_name))
                    .setContentText(getString(R.string.msg_installed, name));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            builder.setCategory(Notification.CATEGORY_STATUS).setVisibility(Notification.VISIBILITY_SECRET);

        // Get defaults
        SharedPreferences prefs_wifi = getSharedPreferences("wifi", Context.MODE_PRIVATE);
        SharedPreferences prefs_other = getSharedPreferences("other", Context.MODE_PRIVATE);
        boolean wifi = prefs_wifi.getBoolean(packages[0], prefs.getBoolean("whitelist_wifi", true));
        boolean other = prefs_other.getBoolean(packages[0], prefs.getBoolean("whitelist_other", true));

        // Build Wi-Fi action
        Intent riWifi = new Intent(this, ServiceSinkhole.class);
        riWifi.putExtra(ServiceSinkhole.EXTRA_COMMAND, ServiceSinkhole.Command.set);
        riWifi.putExtra(ServiceSinkhole.EXTRA_NETWORK, "wifi");
        riWifi.putExtra(ServiceSinkhole.EXTRA_UID, uid);
        riWifi.putExtra(ServiceSinkhole.EXTRA_PACKAGE, packages[0]);
        riWifi.putExtra(ServiceSinkhole.EXTRA_BLOCKED, !wifi);

        PendingIntent piWifi = PendingIntent.getService(this, uid, riWifi, PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Action wAction = new NotificationCompat.Action.Builder(
                wifi ? R.drawable.wifi_on : R.drawable.wifi_off,
                getString(wifi ? R.string.title_allow_wifi : R.string.title_block_wifi), piWifi).build();
        builder.addAction(wAction);

        // Build mobile action
        Intent riOther = new Intent(this, ServiceSinkhole.class);
        riOther.putExtra(ServiceSinkhole.EXTRA_COMMAND, ServiceSinkhole.Command.set);
        riOther.putExtra(ServiceSinkhole.EXTRA_NETWORK, "other");
        riOther.putExtra(ServiceSinkhole.EXTRA_UID, uid);
        riOther.putExtra(ServiceSinkhole.EXTRA_PACKAGE, packages[0]);
        riOther.putExtra(ServiceSinkhole.EXTRA_BLOCKED, !other);
        PendingIntent piOther = PendingIntent.getService(this, uid + 10000, riOther,
                PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Action oAction = new NotificationCompat.Action.Builder(
                other ? R.drawable.other_on : R.drawable.other_off,
                getString(other ? R.string.title_allow_other : R.string.title_block_other), piOther).build();
        builder.addAction(oAction);

        // Show notification
        if (internet)
            NotificationManagerCompat.from(this).notify(uid, builder.build());
        else {
            NotificationCompat.BigTextStyle expanded = new NotificationCompat.BigTextStyle(builder);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
                expanded.bigText(getString(R.string.msg_installed_n));
            else
                expanded.bigText(getString(R.string.msg_installed, name));
            expanded.setSummaryText(getString(R.string.title_internet));
            NotificationManagerCompat.from(this).notify(uid, expanded.build());
        }

    } catch (PackageManager.NameNotFoundException ex) {
        Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
    }
}

From source file:com.waz.zclient.pages.main.conversation.ConversationFragment.java

private void onErrorCanNotSentMessageToUnverifiedConversation(
        final ErrorsList.ErrorDescription errorDescription) {
    if (getControllerFactory().getNavigationController().getCurrentPage() != Page.MESSAGE_STREAM) {
        return;/*from   ww  w.  j  a va2  s . c  o m*/
    }

    errorDescription.dismiss();
    KeyboardUtils.hideKeyboard(getActivity());

    final IConversation currentConversation = errorDescription.getConversation();
    final Iterable<? extends User> users = currentConversation.getUsers();
    final Map<User, String> userNameMap = new HashMap<>();
    int tmpUnverifiedDevices = 0;
    int userCount = 0;
    for (User user : users) {
        userCount++;
        if (user.getVerified() == Verification.VERIFIED) {
            continue;
        }
        userNameMap.put(user, user.getDisplayName());
        for (OtrClient client : user.getOtrClients()) {
            if (client.getVerified() == Verification.VERIFIED) {
                continue;
            }
            tmpUnverifiedDevices++;
        }
    }
    final List<String> userNameList = new ArrayList<>(userNameMap.values());
    final int userNameCount = userNameList.size();

    final String header;
    if (userNameCount == 0) {
        header = getResources().getString(R.string.conversation__degraded_confirmation__header__someone);
    } else if (userNameCount == 1) {
        final int unverifiedDevices = Math.max(1, tmpUnverifiedDevices);
        header = getResources().getQuantityString(
                R.plurals.conversation__degraded_confirmation__header__single_user, unverifiedDevices,
                userNameList.get(0));
    } else {
        header = getString(R.string.conversation__degraded_confirmation__header__multiple_user,
                TextUtils.join(", ", userNameList.subList(0, userNameCount - 1)),
                userNameList.get(userNameCount - 1));
    }
    int tmpMessageCount = 0;
    for (Message m : errorDescription.getMessages()) {
        tmpMessageCount++;
    }
    final int messageCount = Math.max(1, tmpMessageCount);
    final String message = getResources()
            .getQuantityString(R.plurals.conversation__degraded_confirmation__message, messageCount);

    final ConfirmationCallback callback = new ConfirmationCallback() {
        @Override
        public void positiveButtonClicked(boolean checkboxIsSelected) {
            final Iterable<? extends Message> messages = errorDescription.getMessages();
            for (Message message : messages) {
                message.retry();
            }
        }

        @Override
        public void negativeButtonClicked() {
        }

        @Override
        public void canceled() {
        }

        @Override
        public void onHideAnimationEnd(boolean confirmed, boolean canceled, boolean checkboxIsSelected) {
            if (confirmed || canceled) {
                return;
            }
            final View anchorView = ViewUtils.getView(getActivity(), R.id.cursor_menu_item_participant);
            getControllerFactory().getConversationScreenController().showParticipants(anchorView, true);
        }
    };
    final String positiveButton = getString(R.string.conversation__degraded_confirmation__positive_action);
    final String negativeButton = getResources()
            .getQuantityString(R.plurals.conversation__degraded_confirmation__negative_action, userCount);
    final ConfirmationRequest request = new ConfirmationRequest.Builder(
            IConfirmationController.SEND_MESSAGES_TO_DEGRADED_CONVERSATION).withHeader(header)
                    .withMessage(message).withPositiveButton(positiveButton).withNegativeButton(negativeButton)
                    .withConfirmationCallback(callback).withCancelButton()
                    .withHeaderIcon(R.drawable.shield_half)
                    .withWireTheme(getControllerFactory().getThemeController().getThemeDependentOptionsTheme())
                    .build();

    getControllerFactory().getConfirmationController().requestConfirmation(request,
            IConfirmationController.CONVERSATION);

}

From source file:org.thoughtland.xlocation.ActivityApp.java

@SuppressLint("InflateParams")
public static void showHelp(ActivityBase context, View parent, Hook hook) {
    // Build dialog
    Dialog dlgHelp = new Dialog(context);
    dlgHelp.requestWindowFeature(Window.FEATURE_LEFT_ICON);
    dlgHelp.setTitle(R.string.app_name);
    dlgHelp.setContentView(R.layout.helpfunc);
    dlgHelp.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, context.getThemed(R.attr.icon_launcher));
    dlgHelp.setCancelable(true);/*from   w  w w .  j a  v  a 2 s  .c  om*/

    // Set title
    TextView tvTitle = (TextView) dlgHelp.findViewById(R.id.tvTitle);
    tvTitle.setText(hook.getName());

    // Set info
    TextView tvInfo = (TextView) dlgHelp.findViewById(R.id.tvInfo);
    tvInfo.setText(Html.fromHtml(hook.getAnnotation()));
    tvInfo.setMovementMethod(LinkMovementMethod.getInstance());

    // Set permissions
    String[] permissions = hook.getPermissions();
    if (permissions != null && permissions.length > 0)
        if (!permissions[0].equals("")) {
            TextView tvPermissions = (TextView) dlgHelp.findViewById(R.id.tvPermissions);
            tvPermissions.setText(Html.fromHtml(TextUtils.join("<br />", permissions)));
        }

    dlgHelp.show();
}

From source file:com.android.mms.ui.MessageUtils.java

public static Intent createIntentByThreadId(Context context, long threadId, int type) {
    Intent intent = null;// w  ww . j av a2  s  .co m
    if (Telephony.Threads.CELL_BROADCAST_THREAD == type) {
        intent = CbMessageListActivity.createIntent(context, threadId);
        intent.putExtra("bFromLaunch", true);
    } else {
        intent = new Intent(context, ComposeMessageActivity.class);
        intent.putExtra("finish", true);
        if (threadId > 0) {
            intent.setAction(Intent.ACTION_SENDTO);
            intent.setData(Uri.parse("smsto:" + TextUtils.join(",",
                    Conversation.get(context, threadId, true).getRecipients().getNumbers())));
        }
    }
    return intent;
}

From source file:android_network.hetnet.vpn_service.ServiceSinkhole.java

private void showAccessNotification(int uid) {
    String name = TextUtils.join(", ", Util.getApplicationNames(uid, ServiceSinkhole.this));

    Intent main = new Intent(ServiceSinkhole.this, MainActivity.class);
    main.putExtra(MainActivity.EXTRA_SEARCH, Integer.toString(uid));
    PendingIntent pi = PendingIntent.getActivity(ServiceSinkhole.this, uid + 10000, main,
            PendingIntent.FLAG_UPDATE_CURRENT);

    TypedValue tv = new TypedValue();
    getTheme().resolveAttribute(R.attr.colorOn, tv, true);
    int colorOn = tv.data;
    getTheme().resolveAttribute(R.attr.colorOff, tv, true);
    int colorOff = tv.data;

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_cloud_upload_white_24dp).setGroup("AccessAttempt").setContentIntent(pi)
            .setColor(colorOff).setOngoing(false).setAutoCancel(true);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
        builder.setContentTitle(name).setContentText(getString(R.string.msg_access_n));
    else//from   w w  w  . j a v a 2 s  .  c  om
        builder.setContentTitle(getString(R.string.app_name))
                .setContentText(getString(R.string.msg_access, name));

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        builder.setCategory(Notification.CATEGORY_STATUS).setVisibility(Notification.VISIBILITY_SECRET);
    }

    DateFormat df = new SimpleDateFormat("dd HH:mm");

    NotificationCompat.InboxStyle notification = new NotificationCompat.InboxStyle(builder);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
        notification.addLine(getString(R.string.msg_access_n));
    else {
        String sname = getString(R.string.msg_access, name);
        int pos = sname.indexOf(name);
        Spannable sp = new SpannableString(sname);
        sp.setSpan(new StyleSpan(Typeface.BOLD), pos, pos + name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        notification.addLine(sp);
    }

    Cursor cursor = DatabaseHelper.getInstance(ServiceSinkhole.this).getAccessUnset(uid, 7);
    int colDAddr = cursor.getColumnIndex("daddr");
    int colTime = cursor.getColumnIndex("time");
    int colAllowed = cursor.getColumnIndex("allowed");
    while (cursor.moveToNext()) {
        StringBuilder sb = new StringBuilder();
        sb.append(df.format(cursor.getLong(colTime))).append(' ');

        String daddr = cursor.getString(colDAddr);
        if (Util.isNumericAddress(daddr))
            try {
                daddr = InetAddress.getByName(daddr).getHostName();
            } catch (UnknownHostException ignored) {
            }
        sb.append(daddr);

        int allowed = cursor.getInt(colAllowed);
        if (allowed >= 0) {
            int pos = sb.indexOf(daddr);
            Spannable sp = new SpannableString(sb);
            ForegroundColorSpan fgsp = new ForegroundColorSpan(allowed > 0 ? colorOn : colorOff);
            sp.setSpan(fgsp, pos, pos + daddr.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            notification.addLine(sp);
        } else
            notification.addLine(sb);
    }
    cursor.close();

    NotificationManagerCompat.from(this).notify(uid + 10000, notification.build());
}

From source file:illab.nabal.proxy.FacebookProxy.java

/**
 * Get fields parameter for Facebook profile data fields.
 * /*from   w w  w . jav  a  2  s. c o m*/
 * @param additionalFields
 * @return fields CSV
 */
private String getProfileFields(String[] additionalFields) {

    String[] fieldsParams = DEFAULT_PROFILE_FIELDS_;

    if (additionalFields != null && additionalFields.length > 0) {
        fieldsParams = Util.concatArrays(fieldsParams, additionalFields);
    }

    return TextUtils.join(",", fieldsParams);
}

From source file:com.tct.mail.ui.ConversationViewFragment.java

private boolean processInPlaceUpdates(MessageCursor newCursor, MessageCursor oldCursor) {
    final Set<String> idsOfChangedBodies = Sets.newHashSet();
    final List<Integer> changedOverlayPositions = Lists.newArrayList();

    boolean changed = false;

    int pos = 0;//from w w  w . j a v  a 2s.c  o m
    while (true) {
        if (!newCursor.moveToPosition(pos) || !oldCursor.moveToPosition(pos)) {
            break;
        }

        final ConversationMessage newMsg = newCursor.getMessage();
        final ConversationMessage oldMsg = oldCursor.getMessage();

        // We are going to update the data in the adapter whenever any input fields change.
        // This ensures that the Message object that ComposeActivity uses will be correctly
        // aligned with the most up-to-date data.
        if (!newMsg.isEqual(oldMsg)) {
            mAdapter.updateItemsForMessage(newMsg, changedOverlayPositions);
            LogUtils.i(LOG_TAG, "msg #%d (%d): detected field(s) change. sendingState=%s", pos, newMsg.id,
                    newMsg.sendingState);
        }

        // update changed message bodies in-place
        if (!TextUtils.equals(newMsg.bodyHtml, oldMsg.bodyHtml)
                || !TextUtils.equals(newMsg.bodyText, oldMsg.bodyText)) {
            // maybe just set a flag to notify JS to re-request changed bodies
            idsOfChangedBodies.add('"' + mTemplates.getMessageDomId(newMsg) + '"');
            LogUtils.i(LOG_TAG, "msg #%d (%d): detected body change", pos, newMsg.id);
        }

        pos++;
    }

    if (!changedOverlayPositions.isEmpty()) {
        // notify once after the entire adapter is updated
        mConversationContainer.onOverlayModelUpdate(changedOverlayPositions);
        changed = true;
    }

    final ConversationFooterItem footerItem = mAdapter.getFooterItem();
    if (footerItem != null) {
        footerItem.invalidateMeasurement();
    }
    if (!idsOfChangedBodies.isEmpty()) {
        mWebView.loadUrl(String.format("javascript:replaceMessageBodies([%s]);",
                TextUtils.join(",", idsOfChangedBodies)));
        changed = true;
    }

    // TS: Gantao 2015-06-02 EMAIL BUGFIX-998526 ADD_S
    if (mMessageHeaderView != null) {
        mMessageHeaderView.updateHeight();
    }
    // TS: Gantao 2015-06-02 EMAIL BUGFIX-998526 ADD_E
    return changed;
}

From source file:eu.faircode.netguard.ServiceSinkhole.java

private void showAccessNotification(int uid) {
    String name = TextUtils.join(", ", Util.getApplicationNames(uid, ServiceSinkhole.this));

    Intent main = new Intent(ServiceSinkhole.this, ActivityMain.class);
    main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
    PendingIntent pi = PendingIntent.getActivity(ServiceSinkhole.this, uid + 10000, main,
            PendingIntent.FLAG_UPDATE_CURRENT);

    TypedValue tv = new TypedValue();
    getTheme().resolveAttribute(R.attr.colorOn, tv, true);
    int colorOn = tv.data;
    getTheme().resolveAttribute(R.attr.colorOff, tv, true);
    int colorOff = tv.data;

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_cloud_upload_white_24dp).setGroup("AccessAttempt").setContentIntent(pi)
            .setColor(colorOff).setOngoing(false).setAutoCancel(true);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
        builder.setContentTitle(name).setContentText(getString(R.string.msg_access_n));
    else/*w w  w  .  j  a  v  a 2s.c  o m*/
        builder.setContentTitle(getString(R.string.app_name))
                .setContentText(getString(R.string.msg_access, name));

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        builder.setCategory(Notification.CATEGORY_STATUS).setVisibility(Notification.VISIBILITY_SECRET);
    }

    DateFormat df = new SimpleDateFormat("dd HH:mm");

    NotificationCompat.InboxStyle notification = new NotificationCompat.InboxStyle(builder);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
        notification.addLine(getString(R.string.msg_access_n));
    else {
        String sname = getString(R.string.msg_access, name);
        int pos = sname.indexOf(name);
        Spannable sp = new SpannableString(sname);
        sp.setSpan(new StyleSpan(Typeface.BOLD), pos, pos + name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        notification.addLine(sp);
    }

    Cursor cursor = DatabaseHelper.getInstance(ServiceSinkhole.this).getAccessUnset(uid, 7);
    int colDAddr = cursor.getColumnIndex("daddr");
    int colTime = cursor.getColumnIndex("time");
    int colAllowed = cursor.getColumnIndex("allowed");
    while (cursor.moveToNext()) {
        StringBuilder sb = new StringBuilder();
        sb.append(df.format(cursor.getLong(colTime))).append(' ');

        String daddr = cursor.getString(colDAddr);
        if (Util.isNumericAddress(daddr))
            try {
                daddr = InetAddress.getByName(daddr).getHostName();
            } catch (UnknownHostException ignored) {
            }
        sb.append(daddr);

        int allowed = cursor.getInt(colAllowed);
        if (allowed >= 0) {
            int pos = sb.indexOf(daddr);
            Spannable sp = new SpannableString(sb);
            ForegroundColorSpan fgsp = new ForegroundColorSpan(allowed > 0 ? colorOn : colorOff);
            sp.setSpan(fgsp, pos, pos + daddr.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            notification.addLine(sp);
        } else
            notification.addLine(sb);
    }
    cursor.close();

    NotificationManagerCompat.from(this).notify(uid + 10000, notification.build());
}