Message Persistence API for Android SDK
Message Persistence gives you real-time access to the history of messages published to PubNub. Each message is timestamped to the nearest 10 nanoseconds and stored across multiple availability zones in several geographic locations. You can encrypt stored messages with AES-256 so they are not readable on PubNub’s network. For details, see Message Persistence.
You control how long messages are stored through your account’s retention policy. Options include: 1 day, 7 days, 30 days, 3 months, 6 months, 1 year, or Unlimited.
You can retrieve the following:
- Messages
- Message reactions
- Files (using the File Sharing API)
Fetch history
Requires Message Persistence
Enable Message Persistence for your key in the Admin Portal. See how to enable add-on features.
Fetch historical messages from one or multiple channels. Use includeMessageActions
to include message reactions along with the messages.
You can control how messages are returned and in what order:
- If you specify only the
start
parameter (withoutend
), you receive messages older than thestart
timetoken. - If you specify only the
end
parameter (withoutstart
), you receive messages from thatend
timetoken and newer. - If you specify both
start
andend
, you retrieve messages between those timetokens (inclusive of theend
value).
You can receive up to 100 messages for a single channel, or 25 messages per channel when querying multiple channels (up to 500 channels). If more messages match the time range, make iterative calls and adjust the start
timetoken to page through the results.
Method(s)
To run Fetch History
, you can use the following method(s) in the Android SDK:
this.pubnub.fetchMessages()
.channels(List<String>)
.start(Long)
.end(Long)
.maximumPerChannel(Integer)
.includeMeta(Boolean)
.includeMessageActions(Boolean)
.includeMessageType(Boolean)
.includeUUID(Boolean)
Parameter | Description |
---|---|
channels *Type: List <String> Default: n/a | Channels to fetch history messages from (up to 500). |
start Type: Long Default: n/a | Timetoken delimiting the start of the time slice (exclusive) to pull messages from. |
end Type: Long Default: n/a | Timetoken delimiting the end of the time slice (inclusive) to pull messages from. |
maximumPerChannel Type: Integer Default: 100 or 25 | Number of historical messages to return per channel. Maximum is 100 for a single channel or 25 for multiple channels. |
includeMeta Type: Boolean Default: false | Whether to include message metadata in the response. |
includeMessageActions Type: Boolean Default: false | Retrieve history messages with message reactions. If true , limited to one channel only. |
includeMessageType Type: Boolean Default: true | Whether to include message type. If includeMessageActions is true , then 25 is the default and maximum. |
includeUUID Type: Boolean Default: true | Whether to include the publisher UUID. |
async *Type: PNCallback Default: n/a | PNCallback of type PNFetchMessagesResult . |
Truncated response
If you fetch messages with message actions, the response may be truncated when internal limits are reached. If truncated, a more
property is returned with additional parameters. Make iterative calls to history, adjusting the parameters to fetch more messages.
Sample code
Retrieve the last message on a channel:
pubnub.fetchMessages()
.channels(Arrays.asList("my_channel"))
.maximumPerChannel(25)
.includeMessageActions(true)
.includeMeta(true)
.includeMessageType(true)
.includeUUID(true)
.async(new PNCallback<PNFetchMessagesResult>() {
@Override
public void onResponse(PNFetchMessagesResult result, PNStatus status) {
if (!status.isError()) {
Map<String, List<PNFetchMessageItem>> channels = result.getChannels();
for (PNFetchMessageItem messageItem : channels.get("my_channel")) {
System.out.println(messageItem.getMessage());
System.out.println(messageItem.getMeta());
show all 36 linesReturns
The fetchMessages()
operation returns a list of PNFetchMessagesResult
objects, each containing the following operations:
Method | Description |
---|---|
getMessage() Type: JsonElement | Message content. |
getMeta() Type: JsonElement | Message metadata if any, and if requested via includeMeta(true) . |
getTimetoken() Type: Long | Publish timetoken. |
getActionTimetoken() Type: Long | Timestamp when the message reaction was created. |
getActions() Type: HashMap | Actions data of the message, if any, and if requested via includeMessageActions(true) . |
getMessageType() Type: Integer | Message type 0 - message, 1 - signal, 2 - object, 3 - message reaction, 4 - files |
getUuid() Type: String | UUID of the publisher |
Other examples
Paging history responses
package com.we.pubnubtest.utils;
import com.pubnub.api.models.consumer.history.PNFetchMessagesResult;
public abstract class CallbackSkeleton {
public CallbackSkeleton() {
}
public abstract void handleResponse(PNFetchMessagesResult result);
public abstract void finish();
}
package com.we.pubnubtest.utils;
import com.pubnub.api.PubNub;
import com.pubnub.api.callbacks.PNCallback;
import com.pubnub.api.models.consumer.PNStatus;
import com.pubnub.api.models.consumer.history.PNFetchMessagesResult;
import com.pubnub.api.models.consumer.pubsub.PNMessageResult;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class PubnubRecursiveHistoryFetcher {
private PubNub pubNub;
private String channels;
show all 66 linesFetch messages from multiple channels
pubNub.fetchMessages()
.channels(Arrays.asList("ch1", "ch2", "ch3"))
.async(new PNCallback<PNFetchMessagesResult>() {
@Override
public void onResponse(@Nullable final PNFetchMessagesResult result, @NotNull final PNStatus status) {
if (!status.isError()) {
final Map<String, List<PNFetchMessageItem>> channelToMessageItemsMap = result.getChannels();
final Set<String> channels = channelToMessageItemsMap.keySet();
for (final String channel : channels) {
List<PNFetchMessageItem> pnFetchMessageItems = channelToMessageItemsMap.get(channel);
for (final PNFetchMessageItem fetchMessageItem: pnFetchMessageItems) {
System.out.println(fetchMessageItem.getMessage());
System.out.println(fetchMessageItem.getMeta());
System.out.println(fetchMessageItem.getTimetoken());
}
show all 22 linesDelete messages from history
Requires Message Persistence
Enable Message Persistence for your key in the Admin Portal. See how to enable add-on features.
Remove messages from the history of a specific channel.
Required setting
To accept delete-from-history requests, enable the Delete-From-History
setting for your key in the Admin Portal and initialize the SDK with a secret key.
Method(s)
To Delete Messages from History
you can use the following method(s) in the Android SDK.
this.pubnub.deleteMessages()
.channels(Array)
.start(Long)
.end(Long)
Parameter | Description |
---|---|
channels *Type: Array Default: n/a | Channels to delete messages from. |
start Type: Long Default: n/a | Timetoken delimiting the start of the time slice (inclusive) to delete messages from. |
end Type: Long Default: n/a | Timetoken delimiting the end of the time slice (exclusive) to delete messages from. |
async *Type: PNCallback Default: n/a | PNCallback of type PNDeleteMessagesResult . |
Sample code
pubnub.deleteMessages()
.channels(Arrays.asList("channel_1", "channel_2"))
.start(1460693607379L)
.end(1460893617271L)
.async(new PNCallback<PNDeleteMessagesResult>() {
@Override
public void onResponse(PNDeleteMessagesResult result, PNStatus status) {
// The deleteMessages() method does not return actionable data, be sure to check the status
// object on the outcome of the operation by checking the status.isError().
}
});
Other examples
Delete specific message from history
To delete a specific message, pass the publish timetoken
(received from a successful publish) in the End
parameter and timetoken +/- 1
in the Start
parameter. For example, if 15526611838554310
is the publish timetoken
, pass 15526611838554309
in Start
and 15526611838554310
in End
parameters respectively as shown in the following code snippet.
pubnub.deleteMessages()
.channels(Arrays.asList("channel_1"))
.start(15526611838554309L)
.end(15526611838554310L)
.async(new PNCallback<PNDeleteMessagesResult>() {
@Override
public void onResponse(PNDeleteMessagesResult result, PNStatus status) {
// The deleteMessages() method does not return actionable data, be sure to check the status
// object on the outcome of the operation by checking the status.isError().
}
});
Message counts
Requires Message Persistence
Enable Message Persistence for your key in the Admin Portal. See how to enable add-on features.
Return the number of messages published on one or more channels since a given time. The count
is the number of messages in history with a timetoken greater than or equal to the value passed in channelsTimetoken
.
Unlimited message retention
For keys with unlimited message retention enabled, this method considers only messages published in the last 30 days.
Method(s)
You can use the following method(s) in the Android SDK:
this.pubnub.messageCounts()
.channels(Array)
.channelsTimetoken(Array)
Parameter | Description |
---|---|
channels *Type: Array Default: n/a | Channels to fetch the message count for. |
channelsTimetoken *Type: Array Default: n/a | List of timetokens , in the same order as the channels list. Specify a single timetoken to apply it to all channels. Otherwise, the list of timetokens must match the number of channels, or the function returns a PNStatus error. |
async *Type: PNCallback Default: n/a | PNCallback of type PNMessageCountResult . |
Sample code
Long lastHourTimetoken = (Calendar.getInstance().getTimeInMillis() - TimeUnit.HOURS.toMillis(1)) * 10000L;
pubnub.messageCounts()
.channels(Arrays.asList("news"))
.channelsTimetoken(Arrays.asList(lastHourTimetoken))
.async(new PNCallback<PNMessageCountResult>() {
@Override
public void onResponse(PNMessageCountResult result, PNStatus status) {
if (!status.isError()) {
for (Map.Entry<String, Long> messageCountEntry : result.getChannels().entrySet()) {
messageCountEntry.getKey(); // the channel name
messageCountEntry.getValue(); // number of messages for that channel
}
} else {
// Handle error accordingly.
show all 19 linesReturns
The operation returns a PNMessageCountResult
which contains the following properties:
Method | Description |
---|---|
getChannels() Type: Map <String, Long> | A map with values of Long for each channel. Channels without messages have a count of 0. Channels with 10,000 messages or more have a count of 10000. |
Other examples
Retrieve count of messages using different timetokens for each channel
Long lastHourTimetoken = (Calendar.getInstance().getTimeInMillis() - TimeUnit.HOURS.toMillis(1)) * 10000L;
Long lastDayTimetoken = (Calendar.getInstance().getTimeInMillis() - TimeUnit.DAYS.toMillis(1)) * 10000L;
pubnub.messageCounts()
.channels(Arrays.asList("news", "info"))
.channelsTimetoken(Arrays.asList(lastHourTimetoken, lastDayTimetoken))
.async(new PNCallback<PNMessageCountResult>() {
@Override
public void onResponse(PNMessageCountResult result, PNStatus status) {
if (!status.isError()) {
for (Map.Entry<String, Long> messageCountEntry : result.getChannels().entrySet()) {
messageCountEntry.getKey(); // the channel name
messageCountEntry.getValue(); // number of messages for that channel
}
} else {
show all 20 linesHistory (deprecated)
Requires Message Persistence
Enable Message Persistence for your key in the Admin Portal. See how to enable add-on features.
Alternative method
This method is deprecated. Use fetch history instead.
Fetch historical messages for a channel.
You can control how messages are returned and in what order. For example, you can:
- Search from the newest end of the timeline (default:
reverse
=false
). - Search from the oldest end of the timeline by setting
reverse
totrue
. - Page through results by providing a
start
orend
timetoken. - Retrieve a slice of the timeline by providing both a
start
andend
timetoken. - Limit the number of messages using the
count
parameter.
Start & End parameter usage clarity
If you specify only start
(without end
), you receive messages older than and up to that start
timetoken. If you specify only end
(without start
), you receive messages that match that end
timetoken and newer. If you specify both start
and end
, you receive messages between those timetokens (inclusive of end
). You still receive up to 100 messages even if more match. Make iterative calls to history, adjusting start
, to page through the full result set.
Method(s)
To run History
you can use the following method(s) in the Android SDK:
this.pubnub.history()
.channel(String)
.reverse(Boolean)
.includeTimetoken(Boolean)
.includeMeta(Boolean)
.start(Long)
.end(Long)
.count(Integer);
Parameter | Description |
---|---|
channel *Type: String Default: n/a | Channel to return history messages from. |
reverse Type: Boolean Default: false | Whether to traverse the timeline in reverse (oldest to newest) when set to true . |
includeTimetoken Type: Boolean Default: false | Whether event dates timetokens should be included in the response. |
includeMeta Type: Boolean Default: false | Whether to include message metadata within the response. |
start Type: Long Default: n/a | Timetoken delimiting the start of time slice (exclusive) to pull messages from. |
end Type: Long Default: n/a | Timetoken delimiting the end of time slice (inclusive) to pull messages from. |
count Type: Int Default: 100 | Number of historical messages to return. |
async *Type: PNCallback Default: n/a | PNCallback of type PNHistoryResult . |
Using the reverse parameter
Messages are always returned sorted in ascending time direction from history regardless of reverse
. The reverse
direction matters when you have more than 100 (or count
, if it's set) messages in the time interval, in which case reverse
determines the end of the time interval from which it should start retrieving the messages.
Sample code
Retrieve the last 100 messages on a channel:
pubnub.history()
.channel("history_channel") // where to fetch history from
.count(100) // how many items to fetch
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {
}
});
Returns
The history()
operation returns a PNHistoryResult
which contains the following properties:
Method | Description |
---|---|
getMessages() Type: List <PNHistoryItemResult> | List of messages. See PNHistoryItemResult for more details. |
getStartTimetoken() Type: Long | Start timetoken . |
getEndTimetoken() Type: Long | End timetoken . |
PNHistoryItemResult
Method | Description |
---|---|
getTimetoken() Type: Long | Timetoken of the message. |
getEntry() Type: JsonElement | Message. |
Other examples
Use history() to retrieve the three oldest messages by retrieving from the time line in reverse
pubnub.history()
.channel("my_channel") // where to fetch history from
.count(3) // how many items to fetch
.reverse(true) // should go in reverse?
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {
}
});
Response
if (!status.isError()) {
for (PNHistoryItemResult pnHistoryItemResult: result.getMessages()) {
pnHistoryItemResult.getEntry(); // custom JSON structure for message
}
}
Use history() to retrieve messages newer than a given timetoken by paging from oldest message to newest message starting at a single point in time (exclusive)
pubnub.history()
.channel("my_channel") // where to fetch history from
.start(13847168620721752L) // first timestamp
.reverse(true) // should go in reverse?
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {
}
});
Response
if (!status.isError()) {
for (PNHistoryItemResult pnHistoryItemResult: result.getMessages()) {
pnHistoryItemResult.getEntry(); // custom JSON structure for message
}
}
Use history() to retrieve messages until a given timetoken by paging from newest message to oldest message until a specific end point in time (inclusive)
pubnub.history()
.channel("my_channel") // where to fetch history from
.count(100) // how many items to fetch
.start(-1) // first timestamp
.end(13847168819178600L) // last timestamp
.reverse(true) // should go in reverse?
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {
}
});
Response
[
["Pub3","Pub4","Pub5"],
13406746780720711,
13406746845892666
]
History paging example
Usage
You can call the method by passing 0 or a valid timetoken as the argument.
package com.pubnub.api;
import com.pubnub.api.v2.PNConfiguration;
import com.pubnub.api.PubNub;
import com.pubnub.api.callbacks.PNCallback;
import com.pubnub.api.models.consumer.PNStatus;
import com.pubnub.api.models.consumer.history.PNHistoryItemResult;
import com.pubnub.api.models.consumer.history.PNHistoryResult;
public class PubNubRecursiveHistoryFetcher {
private PubNub pubnub;
private static abstract class CallbackSkeleton {
public abstract void handleResponse(PNHistoryResult result);
show all 63 linesInclude timetoken in history response
pubnub.history()
.channel("history_channel") // where to fetch history from
.count(100) // how many items to fetch
.includeTimetoken(true) // include timetoken with each entry
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {
}
});