Version 4.0 of the SDK brings many improvements to internal functionality and APIs. While you won't need to worry about most of the internal changes, we have outlined the improvements which affect the public API in this document in order to make the transition easier.
If you are including the SDK an an AAR in your Android project, and using
Gradle, then you no longer need to add anything SDK-related to your
AndroidManifest.xml
, as we have made sure that the SDK contains all the
required properties which will be merged into your application's manifest
file with the help of the manifest merger during the build process.
Likewise, if you're enabling ProGuard for your builds and using Gradle then the SDK contains its own ProGuard configuration file which will take care of everything. You will no longer need to add anything yourself.
If you have had to previously add the apache-mime4j-core
and httpmime
JARs to your project then you can remove them, as the SDK no longer depends
on them.
We have removed the NotStartedException
from all of the calls, which should
simplify your code. The SDK will log a warning instead and not process the
event or engagement as before.
Some of the method names have changed slightly, such as stopSDK()
is now
stopSdk()
to improve readability, and userID()
has changed to getUserId()
to make the method's purpose clearer. These are just a couple examples, but
they should give an indication of what to look out for.
Overall we have made the SDK stricter in terms of what input it accepts, as such instead of as swallowing up bad input it will now throw exceptions or log warnings. These changes should result in your application sending events more reliably and making sure that their content is sensible.
The SDK should now be initialised in the onCreate()
method of your
Application
subclass instead of inside of an Activity
public void onCreate() {
super.onCreate()
DDNA.initialise(new DDNA.Configuration(
this,
"your environment key",
"your collect url",
"your engage url")
.clientVersion(BuildConfig.VERSION_NAME));
}
Remember to register your class in the manifest file if you don't have one already, otherwise it will not get used by Android.
After the previous step the SDK will be available to grab through
[DDNA.instance()
] at any stage during the lifecycle of your application.
Since we have moved some of the constant values, which are not going to change
during the runtime of your application, into the initialisation step there is
no longer the need to supply them when starting the SDK. Instead you may just
call startSdk()
, or startSdk(String)
if you would like to handler user
identification yourself.
If you're sending events by providing the event's name then you won't need to change anything. However for creating more complex events and adding parameters into events we have provided a new API.
You can now send events by crating an instance of an
Event
,
add any parameters as required, and pass it to recordEvent(Event)
.
If you often record a particular type of event then extending the
Event
class may prove useful, for example
public class AchievementUnlockedEvent extends Event<AchievementUnlockedEvent> {
public AchievementUnlockedEvent(
String name,
int level,
int playerXp) {
super("achievementUnlocked");
putParam("name", name);
putParam("level", level);
putParam("playerXp", playerXp);
}
addParam
has been changed to putParam
, to better match the operation being
performed on the parameters.
Transactions have been changed to closer resemble events. They can be created
by instantiating a
Transaction
instance and sent by passing them to recordEvent(Transaction)
.
When creating a Transaction
received and spent products must be supplied by
creating
Product
s.
Previously this used to be known as the ProductBuilder
, as such the APIs
between the two classes will be equivalent, with the exception of
addRealCurrency(String, int)
having changed to setRealCurrency(String, int)
.
Just as with the Event
class, a Transaction
can be subclassed for ease of
use.
When performing an Engage request in your game you would have to do something similar to
DDNA.inst().requestEngagement("outOfCredits", null, new DDNANetReqCB() {
@Override
public void done(DDNANetReq req) {
JSONObject result = req.jsonObject();
// do something with result
}
@Override
public void progress(DDNANetReq req) {}
@Override
public void failed(DDNANetReq req) {
// act on failure
}
});
With version 4 we have made it simpler with the new
EngageListener
class!
DDNA.inst().requestEngagement("outOfCredits", new EngageListener() {
@Override
public void onSuccess(JSONObject result) {
// do something with result
}
@Override
public void onFailure(Throwable t) {
// act on failure
}
});
There is no longer the need to know what you would like to get from the request, whether a JSON array or an object, as now it gets passed into the callback directly. Likewise, in the case of a failure the reason why the request has failed gets passed into the callback method. Finally, we have removed the progress callback as an Engage request will come back quickly enough that doing anything in-between should not be necessary.
In case that you would like to add additional event parameters for
the Engage request we provide a second method which takes an
Engagement
and works similarly to Event
s in terms of instance creation and addition of
parameters.
We have also made sure that the callback methods on the listener get invoked on the main UI thread, which will make interacting with the UI easier.
When requesting an Image Message you would need to write something similar
as if you were performing an Engage request, with the biggest difference
being that in the done()
callback method you would do something similar to
Intent intent = new Intent(this, DDNAPopupActivity.class);
intent.putExtra(DDNA.EXTRA_IMGMESSAGE, req.responseData().toString());
DDNAExampleActivity.this.startActivityForResult(intent, DDNA.RESULTCODE_IMGMESSAGE);
and then you would need to override your Activity
's onActivityResult()
method to check the request and result codes, and finally extract the result
from the data if all the required conditions are met.
With version 4 you can use the
ImageMessageListener
with the request, for example like
DDNA.inst().requestImageMessage(
"missionDifficulty",
new ImageMessageListener(this, MY_REQUEST_CODE));
where this
refers to the instance of the Activity
from which you
are performing the request, and MY_REQUEST_CODE
is a code constant
which you will need to define as it will be needed later on.
Following this request the SDK will invoke the onPrepared(ImageMessage)
method on your listener. At this point the ImageMessage
has been
created and prepared so it is ready to be shown by calling
show(ImageMessage)
. This will result in the ImageMessageActivity
opening up. If your application is no longer in a state where it is
appropriate to show the Image Message then you may opt for not calling
show(ImageMessage)
.
In order to perform an action based on the user's interaction on the Image
Message you will still need to override onActivityResult()
, however in we
have added two new utilities to help you with this which will require you to
know less about how the SDK works internally;
ImageMessageResultListener
which contains callback methods that will be invoked when the user performs an action on the Image Message or cancels ithandleResult()
inImageMessageActivity
into which you will pass theresultCode
anddata
from theonActivityResult
method, and an instance of theImageMessageResultListener
class
Putting all of the above together, you should end up with something similar to
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_REQUEST_CODE) {
ImageMessageActivity.handleResult(
resultCode,
data,
new ImageMessageResultListener() {
@Override
public void onAction(String value, String params) {
// act on value/params
}
@Override
public void onCancelled() {
// act on cancellation
}
});
}
}
Push notifications with Google Cloud Messaging have been split into a separate add-on project that can be found here. In addition to modularising the project we have migrated the implementation away from using legacy APIs, which will result in more consistent and efficient notifications.
And that is everything that should be required for updating your project to work with version 4 of the SDK!