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.28.3",
"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.28.3', 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:
// For Mainland China
bool isSuccess = await TapCommon.UpdateGameAndFailToWebInTapTap(string appId);
// For other countries/regions
bool isSuccess = await TapCommon.UpdateGameAndFailToWebInTapGlobal(string appId);
Open a custom webpage if failed to open the TapTap app:
// For Mainland China
bool isSuccess = await TapCommon.UpdateGameAndFailToWebInTapTap(string appId, string webUrl);
// For other countries/regions
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:
// For Mainland China
TapGameUtil.updateGameAndFailToWebInTapTap(context, "your app id");
// For other countries/regions
TapGameUtil.updateGameAndFailToWebInTapGlobal(context, "your app id");
Open a custom webpage if failed to open the TapTap app:
// For Mainland China
TapGameUtil.updateGameAndFailToWebInTapTap(context, "your app id", "your website url");
// For other countries/regions
TapGameUtil.updateGameAndFailToWebInTapGlobal(context, "your app id", "your website url");
// Due to Apple’s restrictions, TapTap for iOS doesn’t offer the Updates function
If you are not using TapSDK 3.3.0 or later
This section is not applicable for TapSDK 3.3.0 and later. If you are using TapSDK 3.3.0 and later, please use the APIs mentioned earlier on this page.
Check if TapTap is installed:
- Unity
- Android
- iOS
// For Mainland China
TapCommon.IsTapTapInstalled(installed =>
{
if (installed) {
Debug.Log("TapTap is installed");
}
});
// For other countries/regions
TapCommon.IsTapTapGlobalInstalled(installed =>
{
if (installed) {
Debug.Log("TapTap is installed");
}
});
Import TapCommon.aar
and access the interfaces from TapGameUtil
.
import com.tds.common.utils.TapGameUtil;
// For Mainland China
if(TapGameUtil.isTapTapInstalled(this)){
Log.d(TAG, "TapTap is installed");
}
// For other countries/regions
if(TapGameUtil.isTapGlobalInstalled(this)){
Log.d(TAG, "TapTap is installed");
}
Import TapCommon.framework
and add tapsdk
, taptap
and tapiosdk
under LSApplicationQueriesSchemes
in info.plist
.
#import <TapCommonSDK/TapCommonSDK.h>
// For Mainland China
BOOL isInstalled = [TapGameUtil isTapTapInstalled];
// For other countries/regions
BOOL isInstalled = [TapGameUtil isTapGlobalInstalled];
Open TapTap to update the game:
- Unity
- Android
- iOS
TapCommon.UpdateGameInTapTap("appid", callSuccess =>
{
if (callSuccess) {
Debug.Log("TapTap opened");
}
});
if(TapGameUtil.updateGameInTapTap(this,"appid")){
Log.d(TAG, "TapTap opened");
}
// Due to Apple’s restrictions, TapTap for iOS doesn’t offer the Updates function
Open Game Reviews
- Unity
- Android
- iOS
// For Mainland China
TapCommon.OpenReviewInTapTap(appId, openSuccess =>
{
if (openSuccess) {
Debug.Log("Game reviews opened");
}
});
// For other countries/regions
TapCommon.OpenReviewInTapGlobal(appId, openSuccess =>
{
if (openSuccess) {
Debug.Log("Game reviews opened");
}
});
// For Mainland China
if(TapGameUtil.openReviewInTapTap(this,"appid")){
Log.d(TAG, "Game reviews opened");
}
// For other countries/regions
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.cn/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:
- For Mainland China:
https://l.taptap.cn/5d1NGyET?subc1=AppID
- For other countries/regions:
https://l.taptap.io/GNYwFaZr?subc1=AppID
URL for devices with TapTap:
- For Mainland China:
taptap://taptap.cn/app?app_id=AppID&source=outer|update
- For other countries/regions:
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.cn/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
For Mainland China:
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 = "com.taptap";
public static final String CLIENT_URI_TAPTAP = "taptap://taptap.cn";
public static final String DEFAULT_CLIENT_DOWNLOAD_URL_TAPTAP = "https://l.taptap.cn/5d1NGyET";
public static boolean updateGameAndFailToWebInTapTap(Activity activity, String appId) {
return updateGameInTapTap(activity, appId) || openWebDownloadUrlOfTapTap(activity, appId);
}
public static boolean updateGameAndFailToWebInTapTap(Activity activity, String appId, String webUrl) {
if (TextUtils.isEmpty(webUrl)) {
return updateGameAndFailToWebInTapTap(activity, appId);
}
return updateGameInTapTap(activity, appId) || openWebDownloadUrl(activity, webUrl);
}
public static boolean isTapTapInstalled(Context context) {
return isTapClientInstalled(context, PACKAGE_NAME_TAPTAP);
}
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 updateGameInTapTap(Activity activity, String appId) {
return updateGameInTapClient(activity, appId, CLIENT_URI_TAPTAP);
}
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 openReviewInTapTap(Activity activity, String appId) {
return openReviewInTapClient(activity, appId, CLIENT_URI_TAPTAP);
}
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 openWebDownloadUrlOfTapTap(Activity activity, String appId) {
return openWebDownloadUrl(activity, String.format(Locale.US, DEFAULT_CLIENT_DOWNLOAD_URL_TAPTAP + "?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;
}
}
For other countries/regions:
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;
}
}