Можно ли использовать Uri.Builder и не иметь часть "//"?

Я пытаюсь создать uri mailto: для отправки почты с помощью приложения GMail. Я хотел бы использовать класс android.net.Uri.Builder для этого, но полученный uri находится в форме mailto://[email protected], что заставляет приложение GMail считать получателя //[email protected], а не просто [email protected].

Я закончил это:

String uriStr = uriBuilder.toString();
uriStr = uriStr.replaceAll("//", "");
final Uri uri = Uri.parse(uriStr);

но ясно, что это уродливый взлом...

Нет ли способа построить uri без части //?

Ответ 1

Здесь есть несколько вопросов. Хотя можно избавиться от части //, тогда вы потеряете строки запроса. Основная проблема заключается в том, что Uri.Builder не позволит вам использовать запросы с непрозрачными URI (непрозрачный URI - это абсолютный URI, чья часть, зависящая от схемы, не начинается с косой черты, например, mailto: URI).

Тем не менее, вы должны использовать uriBuilder.opaquePart() вместо uriBuilder.authority(), потому что последний неявно устанавливает ваш URI в иерархический, непрозрачный. Это избавит вас от //, но тогда вам не хватает части запроса, и вы не можете установить его, потому что любой вызов uriBuilder.appendQueryParameter() также подразумевает иерархический URI.

Короче говоря, для создания непрозрачного URI-кода mailto:, который включает запросы, вам нужно будет использовать

Uri uri = Uri.parse("mailto:[email protected]?subject=title&body=text");

вместо.

Ответ 2

Ответ sschuberth - хорошее объяснение того, что происходит, но как более практичный ответ (вы действительно хотите избежать параметров и т.д.), я использовал два сборщика, чтобы обойти это:

Builder builder1 = new Builder();
builder1.scheme("mailto");
builder1.opaquePart(emailAddress);

Builder builder2 = new Builder();
builder2.appendQueryParameter("subject", subject);
builder2.appendQueryParameter("body", body);

Uri uri = Uri.parse(builder1.toString() + builder2.toString());

Вероятно, вы не хотите делать это в жестком цикле с миллионами адресов, но для общего использования я думаю, что это должно быть хорошо.

Ответ 3

sschuberth answer намного более краткий, чем kabuko's, так что здесь вариант, который также охватывает кодировку:

Uri uri = Uri.parse(
    String.format("mailto:%s?subject=%s",
        Uri.encode(recipient),
        Uri.encode(subject)
    )
);