Skip to content

Programmer's reference

Miro Kropacek edited this page Oct 14, 2016 · 10 revisions

CPT went through countless of changes, so the API looks how it looks. And be assured, this is the nicer version, our UI developers had to go through hell (all the time changing APIs, functions, parameters, ...).

There are two main channels when communicating with CPT: commands and notifications. Commands are located in class com.croconaut.cpt.data.Communication while notifications are handled via com.croconaut.cpt.ui.CptReceiver which you must inherit from and put this instance into AndroidManifest.xml. See WiFON mini as an example of implementation. And then there's com.croconaut.cpt.ui.CptController which handles various low-level CPT settings and the mode it operates in. Very inconsistent, yes.

Before looking at each function, let's summarise what CPT can do for you:

  • reporting nearby peers (ID + name)
  • sending messages with a Serializable payload (text for instance) to specific recipient and getting an ACK for successful delivery
  • sending so called local messages which can contain one or more attachments to specific recipient and getting an ACK for successful delivery
  • sending so called broadcast messages (these must be non-local for the time being) to everyone nearby with the possibility to update its content with newer version (think of a message with peer's profile information)
  • handling peer's trust -- you can decide from which peers you want to download big files, which peers to ignore (block) etc
  • handling data exchange based on connectivity conditions, i.e. not to send big files to the application server if you're only on a mobile data plan
  • using our CPT Server (the application server) as a middle man to deliver messages into other cities/countries where P2P doesn't stand a chance (and to invite your friends to use your app!)

Official javadoc can be found here but it's so poorly documented that it's worth to mention at least basic stuff. I don't expect anyone wanting 100% covered docs right now, if someone interested, fill in an issue.

Croco ID

This is the basic term for nearly every part of CPT. Obviously, it stands for something as "Croconaut ID" and it serves as basic identification for every user. Trivia fact: it's your device's Wi-Fi Direct MAC address and yes, it should be changed to something else. There's a few advantages of using it, though:

  • you can tell which peer is nearby even if CPT is not installed because the MAC address is usually visible for other peers all the time
  • it's quite short and relatively unique
  • it can be used for all compatible devices (TVs, tables, phones, ...)
  • it speeds up the discovery/connection process in the case when a peer has all needed information and polls only for the group owner flag which indicates that group is created and ready to accept connections
  • it's not hidden on Android >= 6.0

But most likely it's going to be replaced by an UUID or something like that. Right now, the client app using CPT is not supposed to know its own Croco ID, another deprecated "feature" which needs to be reworked.

Nearby peers

This is easy. CptReceiver.onNearbyPeers listener will give you a list of peer tuples (Croco ID, username) at least every 15s (if there are any). You shall use these Croco IDs as the recipient addresses. If you don't use P2P (Link Layer), you can still send an invitation via Communication.inviteFriend using the traditional ACTION_SEND intent (the message may contain an app specific link that you can use to reveal your name and Croco ID to the other peer).

Messages

You can send three kinds of messages:

You can specify whether you're interested in 'sent' or 'delivered' notifications, expiration time (in minutes), and the payload. Broadcast messages ignore the 'delivered' flag. The message instance shall be then passed into Communication.newMessage.

OutgoingMessage

This is the basic message. Usually you are happy just to send a text over the air but it can specify any custom Serializable class. Also you can add one or more attachments (specified by an Uri).

OutgoingPersistentMessage

Like OutgoingMessage but it overwrites its previous version on the target device. Every persistent message has its own ID (unique within the client app) used to identify it, so if a persistent message with newer creation date is received, this ID is used to determine what should be replaced.

OutgoingPersistentBroadcastMessage

Like OutgoingPersistentMessage but sent to every nearby peer (and via the Internet to some others, too -- like your trusted peers or the peers with which you've exchanged some data before).

On the other hand, you will receive only one type of message:

From its payload you can access the Serializable client app specific payload as well as the attachments.

Attachments

Attachments can be used in all of the message types however if the message is a persistent one, there's a limit of 128 KB per message. Otherwise, presence of an attachment changes normal message to a local one. That means that the message wont be spread to anyone else except the recipient (imagine a 5 MB picture copying to every device nearby...) and the CPT Server (if enabled). P2P transfer is extremely fast, it's normal to get 5-6 MB/s between two devices.

CPT notifies the user about every attachment which is currently uploaded or downloaded. Action which should be triggered after tapping on the notification is completely up to the developer of the client app.

When creating attachments, you can use the following properties:

  • Uri: this is clear, it points to the file to transfer
  • storage directory: public directory name, one of the Environment.DIRECTORY_* values. It specifies to which directory should be the file copied on the target device. In other words, the parameter you would use for Environment.getExternalStoragePublicDirectory. If null, the internal files directory for given app is used.
  • wifi only flag: if set to true, the attachment will be uploaded only in case of being connected to a Wi-Fi network (that includes P2P connection as well). Can be changed later.

When looking at the javadoc you might notice there's plenty of attachment-related classes and functions. Again, a sign of bad API but also it means that CPT is quite flexible in fulfilling any needs the client app might have.

The interface for every attachment instance. It offers basic properties about each attachment. Please note that MessageAttachment.getUri isn't available in all cases -- it's the Uri of the attachment stored on the device so if it's an attachment preview, you can't ask for it (more on this later). It's essential that the client app always use something like this when handing incoming messages with one or more attachments:

if (attachment instanceof DownloadedAttachmentPreview) {
    ...
} else if (attachment instanceof DownloadedAttachment) {
    ...
} else {
    ...
}

This class is used as an input for OutgoingPayload.addAttachment. You must specify its source Uri and optionally the destination storage directory and the Wi-Fi flag. As soon as the attachment is processed by CPT, you'll get a notification via CptReceiver.onMessageAttachmentDownloadConfirmed

By default, attachments are not directly uploaded / downloaded to another peers. CPT calls so called previews -- they offer a glimpse of what the final file is like to the recipient.

Full featured (and locally stored) attachment.

Trust

CPT can manage the peers your device communicates with. By default, every connectable device is considered as an equally good peer. No attachment is downloaded or uploaded automatically. Using Communication.changeUserTrustLevel you can change that. For every peer you can define one of the following trust levels:

CPT Server

CPT Server is a quick hack to make the client apps much more useful. Before that you had to personally meet with everyone you wanted to chat with and rely on a strong mesh network to deliver messages even across single city. Right now you can write something on one device, use other device as a carrier and wait until the other one gets connected to the Internet and hopefully delivers the message from the first device to its recipient.

CPT Server basically does:

  • receiving all messages from the device (incl. attachments)
  • sending recipient's messages to the device
  • sending broadcasts and messages for the devices which are in recipient's so called "community" (i.e. the server has an information that there was a P2P communication between those devices)
  • sending broadcasts from the trusted peers for given recipient

Controlling CPT

"Controlling" means telling CPT how to operate. CptController class is exactly for that although it should be unified with Communication's methods in the future. Basically you can:

  • get/set whether to use CPT Server as a middle man
  • get/set whether to publish your name and GPS coordinates so other can see the route the message has travelled
  • check whether the CPT is allowed to change the sleep policy and battery optimisations
  • get (and possibly set) the sleep policy
  • get (and possible set) the battery optimisations
  • get/set and check whether is recommended the dim screen workaround
  • get an intent for opening Wi-Fi settings (if CPT can't set the sleep policy and battery optimisations directly)
  • and most importantly, set the CPT mode of operation: disabled (Link Layer off, no P2P possible), background (Link Layer active only when screen is off) and foreground (Link Layer active until switched off)

All settings are persistent.

Clone this wiki locally