Updates Integration Guide
When you release a new version of your game and wish the existing players to upgrade to the new version, you may want to display a notification in the game. With TapTap’s Updates function, a pop-up can be triggered when the SDK detects a new version released on the TapTap store. The player can tap a button within the pop-up to quickly jump to the Taptap app to update the game.
Integrating the SDK
- Unity
- Android
- iOS
You can add the SDK either manually or with the Unity Package Manager.
If you choose to use the Unity Package Manager, you should add the following dependencies into Packages/manifest.json
:
"dependencies":{
"com.taptap.tds.common":"https://github.com/TapTap/TapCommon-Unity.git#3.29.4",
"com.leancloud.storage": "https://github.com/leancloud/csharp-sdk-upm.git#storage-2.3.0",
}
If you choose to manually import the SDK, you should:
- In the download page, click
TapSDK Unity
to downloadTapSDK-UnityPackage.zip
. - Go to your Unity project, navigate to Assets > Import Package > Custom Package, select the
TapTap_Common
module from unzipped SDK. - Download LeanCloud-SDK-Storage-Unity.zip, unzip it as a
Plugins
folder, and drag and drop the folder into Unity.
Download the TapSDK and add the TapCommon
module to your game:
repositories{
flatDir {
dirs 'libs'
}
}
dependencies {
...
implementation (name:'TapCommon_3.29.4', ext:'aar')
}
Download the TapSDK and add the TapCommon
module to your game:
TapCommonSDK.framework
Open the TapTap App to Check for Updates
Starting from TapSDK 3.3.0, the logic for updating the game has been optimized. You can have the game open a custom webpage if it fails to open the TapTap app. TapSDK 3.3.0 is still compatible with the APIs introduced in the earlier versions. With TapSDK 3.3.0, you won’t need to check if the TapTap app has been installed before you use the following APIs. We recommend you to use the new APIs if you are using TapSDK 3.3.0 and later.
- Unity
- Android
- iOS
Open the TapTap app to check for updates. If failed, open the game’s page on the web app:
bool isSuccess = await TapCommon.UpdateGameAndFailToWebInTapGlobal(string appId);
Open a custom webpage if failed to open the TapTap app:
bool isSuccess = await TapCommon.UpdateGameAndFailToWebInTapGlobal(string appId, string webUrl);
Open the TapTap app to check for updates. If failed, open the game’s page on the web app:
TapGameUtil.updateGameAndFailToWebInTapGlobal(context, "your app id");
Open a custom webpage if failed to open the TapTap app:
TapGameUtil.updateGameAndFailToWebInTapGlobal(context, "your app id", "your website url");
// Due to Apple’s restrictions, TapTap for iOS doesn’t offer the Updates function
Open Game Reviews
- Unity
- Android
- iOS
TapCommon.OpenReviewInTapGlobal(appId, openSuccess =>
{
if (openSuccess) {
Debug.Log("Game reviews opened");
}
});
if(TapGameUtil.openReviewInTapGlobal(this,"appid")){
Log.d(TAG, "Game reviews opened");
}
// Not supported yet
appid is a game’s unique identifier in the TapTap store.
For example, in https://www.taptap.io/app/187168
, 187168
is the appid
.
FAQ
The TapTap app cannot be launched from the game on Android 11. Why?
Android 11 (API level 30) has ramped up its privacy protection policies resulting in a series of changes and restrictions, one of the key changes being Package Visibility, which prevents third-party apps from launching the TapTap app. This has affected related TapTap services from functioning properly, including but not limited to accessing TapTap for updates and purchase verification.
Solution 1
Compile the game with targetSdkVersion
set to 29 (setting this to 30 or above will lead to the problem).
Solution 2
Change gradle build tools to 4.1.0+:
classpath 'com.android.tools.build:gradle:4.1.0'
Add the following lines to AndroidManifest.xml:
<queries>
<package android:name="com.taptap" />
<package android:name="com.taptap.pad" />
<package android:name="com.taptap.global" />
</queries>
If I’m not using the TapSDK, how can I open the TapTap app to update the game?
Due to Apple’s restrictions, TapTap for iOS doesn’t support the Updates function. The following instructions are for Android only.
If you are not using the TapSDK or using older versions of the TapSDK, you can follow the instructions below to manually open the TapTap app to update the game.
Open the corresponding URL according to whether TapTap is installed on the device:
- If TapTap is installed, open the TapTap app and jump to the game’s page.
- If not, open the game’s page in a web browser. The player will follow the instructions on the page to install the TapTap app, open the app, and update the game within the app.
URL for devices without TapTap:
https://l.taptap.io/GNYwFaZr?subc1=AppID
URL for devices with TapTap:
tapglobal://taptap.tw/app?app_id=AppID&source=outer|update
Make sure to replace the AppID
in the URL. AppID
is a game’s unique identifier in the TapTap store. For example, in https://www.taptap.io/app/187168
, 187168
is the AppID.
Keep in mind that you have to write the logic not only to open the URL but also to check whether TapTap is installed, as well as handle errors.
Take a look at the code example below.
Code example
package com.tds.common.utils;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import java.util.Locale;
public class TapGameUtil {
private static final String TAG = TapGameUtil.class.getName();
public static final String PACKAGE_NAME_TAPTAP_GLOBAL = "com.taptap.global";
public static final String CLIENT_URI_TAPTAP_GLOBAL = "tapglobal://taptap.tw";
public static final String DEFAULT_CLIENT_DOWNLOAD_URL_TAPTAP_GLOBAL = "https://l.taptap.io/GNYwFaZr";
public static boolean updateGameAndFailToWebInTapGlobal(Activity activity, String appId) {
return updateGameInTapGlobal(activity, appId) || openWebDownloadUrlOfTapGlobal(activity, appId);
}
public static boolean updateGameAndFailToWebInTapGlobal(Activity activity, String appId, String webUrl) {
if (TextUtils.isEmpty(webUrl)) {
return updateGameAndFailToWebInTapGlobal(activity, appId);
}
return updateGameInTapGlobal(activity, appId) || openWebDownloadUrl(activity, webUrl);
}
public static boolean isTapGlobalInstalled(Context context) {
return isTapClientInstalled(context, PACKAGE_NAME_TAPTAP_GLOBAL);
}
public static boolean isTapClientInstalled(Context context, String clientPackageName) {
if (context != null && !TextUtils.isEmpty(clientPackageName)) {
boolean TapTapInstalled = false;
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(clientPackageName, 0);
if (null != packageInfo) {
TapTapInstalled = true;
}
} catch (Exception e) {
Log.e(TAG, clientPackageName + " isInstalled=false");
}
return TapTapInstalled;
}
return false;
}
public static boolean updateGameInTapGlobal(Activity activity, String appId) {
return updateGameInTapClient(activity, appId, CLIENT_URI_TAPTAP_GLOBAL);
}
public static boolean updateGameInTapClient(Activity activity, String appId, String clientUri) {
if (activity != null && !TextUtils.isEmpty(appId) && !TextUtils.isEmpty(clientUri)) {
try {
Uri uri = Uri.parse(String.format(Locale.US,
"%s/app?app_id=%s&source=outer|update", clientUri, appId));
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(intent);
} catch (Exception e) {
Log.e(TAG, clientUri + "updateGameInTapTap failed");
return false;
}
return true;
}
Log.e(TAG, clientUri + "updateGameInTapTap failed");
return false;
}
public static boolean openReviewInTapGlobal(Activity activity, String appId) {
return openReviewInTapClient(activity, appId, CLIENT_URI_TAPTAP_GLOBAL);
}
public static boolean openReviewInTapClient(Activity activity, String appId, String clientUri) {
if (activity != null && !TextUtils.isEmpty(appId) && !TextUtils.isEmpty(clientUri)) {
try {
Uri uri = Uri.parse(String.format(Locale.US,
"%s/app?tab_name=review&app_id=%s", clientUri, appId));
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(intent);
} catch (Exception e) {
Log.e(TAG, clientUri + "openTapTapReview failed");
return false;
}
return true;
}
Log.e(TAG, clientUri + "openTapTapReview failed");
return false;
}
public static boolean openWebDownloadUrlOfTapGlobal(Activity activity, String appId) {
return openWebDownloadUrl(activity, String.format(Locale.US, DEFAULT_CLIENT_DOWNLOAD_URL_TAPTAP_GLOBAL + "?subc1=%s", appId));
}
public static boolean openWebDownloadUrl(Activity activity, String url) {
if (activity != null && !TextUtils.isEmpty(url)) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse(url));
activity.startActivity(intent);
} catch (Exception e) {
Log.e(TAG, "openWebUrl fail");
return false;
}
return true;
}
return false;
}
}