porridgechen890的笔记

梦里不知身是客

打包的时候遇到问题:

proj.ios_mac/ios/LaunchScreen.storyboard: Failed to find or create execution context for description ‘<IBCocoaTouchPlatformToolDescription: 0x600003af2d80> System content for IBVisionIdiom-EightAndLater <IBScaleFactorDeviceTypeDescription: 0x600003af33a0> scaleFactor=2x, renderMode.identifier=(null)’.

解决办法:

In my case, the XIB related deployment target is 7.0 higher, which is very old. Changing it to 10.0 or higher works.

参考博客:

https://stackoverflow.com/questions/76535257/xcode-15-beta-2-build-error-failed-to-find-or-create-execution-context-for-d

Adjust的文档

https://help.adjust.com/zh/article/privacy-features-ios-sdk#provide-consent-data-to-google-digital-markets-act-compliance

pod

pod 'Adjust'
pod 'Google-Mobile-Ads-SDK'

code

#import <Adjust/Adjust.h>
#import <UserMessagingPlatform/UserMessagingPlatform.h>

//在Max广告SDK初始化完成的回调里写adjust到初始化和DMA的处理
[sdk initializeSdkWithCompletionHandler:^(ALSdkConfiguration * _Nonnull configuration) {
    //加载广告的代码省略

    //初始化Adjust
    NSString* adjustToken = @"xxx";
    NSString *adjustEnvironment = ADJEnvironmentProduction;
    ADJConfig* adjustConfig = [ADJConfig configWithAppToken:adjustToken environment:adjustEnvironment];
    [Adjust appDidLaunch:adjustConfig];
    
    //DMA
    ADJThirdPartySharing *adjustThirdPartySharing = [[ADJThirdPartySharing alloc] initWithIsEnabledNumberBool:nil];
    if ([configuration consentFlowUserGeography] == ALConsentFlowUserGeographyGDPR) {
        [adjustThirdPartySharing addGranularOption:@"google_dma" key:@"eea" value:@"1"];
    } else {
        [adjustThirdPartySharing addGranularOption:@"google_dma" key:@"eea" value:@"0"];
    }
    if (UMPConsentInformation.sharedInstance.canRequestAds) {
        [adjustThirdPartySharing addGranularOption:@"google_dma" key:@"ad_personalization" value:@"1"];
        [adjustThirdPartySharing addGranularOption:@"google_dma" key:@"ad_user_data" value:@"1"];
    } else {
        [adjustThirdPartySharing addGranularOption:@"google_dma" key:@"ad_personalization" value:@"0"];
        [adjustThirdPartySharing addGranularOption:@"google_dma" key:@"ad_user_data" value:@"0"];
    }
    [Adjust trackThirdPartySharing:adjustThirdPartySharing];
}];

我的疑惑

经过测试发现:

如果不是GDPR地区,UMPConsentInformation.sharedInstance.canRequestAds始终为假。

如果是GDPR地区,UMPConsentInformation.sharedInstance.canRequestAds始终为真。

如果是GDPR地区,会弹出特定的弹窗,在那个页面不管选择直接同意,还是去权限列表把每个权限挨个关掉,都不影响UMPConsentInformation.sharedInstance.canRequestAds的结果。

注册小程序推荐使用公众号来关联,所以我来看看公众号的文档。

公众号里订阅号和服务号有啥区别?

一、推送次数不同

服务号:一个月内可以推送四次,每次可以发1~8篇公众号文章。如果你想在一天之内直接推送完4次,也是可以的;

订阅号:每天可以推送一次,每次可以发1~8篇公众号文章。

二、展开形式不同

服务号:推送的消息会直接显示在个人微信号的聊天界面。一旦服务号给用户发送消息,用户就能及时即时收到消息提醒;

订阅号:给用户推送时,消息不会直接显示在聊天界面,而是会显示在订阅号文件夹,消息将会折叠,与其他订阅号消息放在一起,用户不会即刻收到消息提醒,需要点击阅读订阅号才可以看到消息。

三、功能定位不同

订阅号的定位是消息内容资讯的发布与传播,主要偏于为用户传达资讯;

而服务号主要是用于用户管理和提供业务服务,集讯息推送和提供服务为一体的服务交互型公众号。

四、主体不同

服务号针对的是“企业”,而订阅号针对的是“个人”,两种账号并不互通,主体在注册之初就必须选择,确定之后无法进行更改;

服务号不支持个人注册的,所以订阅号的运营主体既可以是企业也可以是个人,服务号的运营主体只能是企业或其他机构。

FGUI介绍

官网

fgui关于cocos2dx的教程

git仓库地址

运行demo

  1. 克隆仓库

  2. 下载3.x版本cocos2dx命名成cocos2d放在Examples根目录。cocos2dx源码需要改动一处地方才能通过编译,打开2d/CCLabel.h,大约在672行,为updateBMFontScale函数打上virtual修饰符。即virtual void updateBMFontScale();

    注:我用的3.17.2。

  3. 报错处理:box2d项目卸载掉。

  4. 报错处理:void GLoader3D::onChangeSpine()函数的函数体全注释掉。

  5. 报错处理:每个项目都检查一下平台工具集,我用的vs2015,所以用的平台工具集是v140_xp。

  6. 报错处理:运行exe的时候报错,需要把Resources文件夹拷贝到Debug.win32下面去。

  7. 修改gitignore:

    Examples/proj.win32/Debug.win32
    Examples/proj.win32/Examples.VC.db
    Examples/proj.win32/Examples.VC.VC.opendb
    Examples/proj.win32/ipch
    libfairygui/proj.win32/Debug.win32

引入其他工程

  1. 拷贝代码文件,并添加头文件搜索路径

  2. 拷贝库文件,并添加依赖项。(WIN32的话可以直接拷贝到exe执行目录,就可以省去添加库文件搜索路径这一步骤)

  3. 修改updateBMFontScale。

  4. 报错:写入程序数据库.pdb时出错;请检查是否是磁盘空间不足、路径无效或权限不够。

    调试信息格式可改为无。

cpp->PF

#pragma region server

cpp->DialogPub

DialogGameAccount

cpp->LayerMenu

on_account

of_refresh_server_button

cpp->CandyManager

of_server_get_level

of_server_save_level

java->delete PubServer

java->build.gradle

com.fineboost.sdk:storage

com.fineboost.sdk:auth

java->AppActivity

_server初始化

YFStorageAgent.exitApp();

java->PubApplication

YFStorageAgent.onApploctionCreated(this);

java->DreamPub

import com.fineboost.auth.YFAuthAgent;

public static PubServer _server = null;到of_server_bind_new_userid

MaxAdHelper

public static Activity _activity;
public static int ii_state_init = 0;
public static void init_max_ad(Activity act) {
    _activity = act;
    ii_state_init = 2;
}

PubApplication

AppLovinSdkSettings settings = new AppLovinSdkSettings(this);
settings.getTermsAndPrivacyPolicyFlowSettings().setEnabled(true);
settings.getTermsAndPrivacyPolicyFlowSettings().setPrivacyPolicyUri(Uri.parse(""));
AppLovinSdk sdk = AppLovinSdk.getInstance(settings, this);
sdk.setMediationProvider("max");
sdk.initializeSdk(new AppLovinSdk.SdkInitializationListener() {
    @Override
    public void onSdkInitialized(AppLovinSdkConfiguration appLovinSdkConfiguration) {
        Log.d("maxadlog", appLovinSdkConfiguration.toString());
        MaxAdHelper.ii_state_init = 1;
        if (DreamPub._activity != null) {
            MaxAdHelper.init_max_ad(DreamPub._activity);
        }
    }
});

AppActivity

//delete old
if (MaxAdHelper.ii_state_init == 1) {
    MaxAdHelper.init_max_ad(this);
}

问题

一台电脑上生成的exe放到另一台电脑上运行不了,提示缺少动态库。

解决办法

把动态编译改为静态编译。

【项目】-【属性】-【C/C++】-【代码生成】-【运行库】-【多线程调试(/MTd)】

文档

项目参数

https://ehu9lcwtyd.feishu.cn/sheets/TZjfs9a0jhTJpStjWyNc76benHb

}a.[230S

ios工程编译

获得p12和pp file

其中dev的pp file需要增加对应的测试设备。

00008101-00084C320208001E

用对应的包名新建一个空工程,把proj.ios_mac文件夹拷贝过去

可能还需要拷贝cocos2d目录下其他文件,如build文件夹,external文件夹。

修改webview相关

https://www.jianshu.com/p/a83848e500b8

修改Minmum Deployments到12.0

修改Requires full screen、iPhone Orientation和iPad Orientation

重新添加Classes和Resources

添加代码后,可以按名称排序一下

添加代码搜索路径

如果报错找不到pub/PF.h,Build Settings->Search Paths->Header Search Paths

添加$(SRCROOT)/../Classes

pod

  1. 在proj.ios_mac文件夹下打开终端,输入pod init

  2. 编辑Podfile中的内容,如:

    platform :ios, '12.0'
    
    use_frameworks!
    target 'PET_CANDY_PUZZLE-mobile' do
    
        pod 'AppLovinSDK'
        pod 'AppLovinMediationAdColonyAdapter'
        pod 'AppLovinMediationChartboostAdapter'
        pod 'AppLovinMediationGoogleAdManagerAdapter'
        pod 'AppLovinMediationGoogleAdapter'
        pod 'AppLovinMediationInMobiAdapter'
        pod 'AppLovinMediationIronSourceAdapter'
        pod 'AppLovinMediationVungleAdapter'
        pod 'AppLovinMediationFacebookAdapter'
        pod 'AppLovinMediationMintegralAdapter'
        pod 'AppLovinMediationByteDanceAdapter'
        pod 'AppLovinMediationTapjoyAdapter'
        pod 'AppLovinMediationUnityAdsAdapter'
    
        pod 'Adjust'
    
        #Facebook自动记录事件(安装,启动,内购),如有使用Fb的登录、分享等组件,也需要升级9.0.1及以上
        # pod 'FBSDKCoreKit', '~> 9.0.1'
    
        pod 'YF_IAP'
    
        pod 'YF_DataAcqu', '5.0.5'
    
        pod 'FBAEMKit', '16.1.3'
        pod 'FBSDKCoreKit', '16.1.3'
        pod 'FBSDKLoginKit', '16.1.3'
        pod 'FBSDKShareKit', '16.1.3'
        pod 'FBSDKGamingServicesKit', '16.1.3'
    
        post_install do |installer|
            xcode_base_version = `xcodebuild -version | grep 'Xcode' | awk '{print $2}' | cut -d . -f 1`
            installer.pods_project.targets.each do |target|
            target.build_configurations.each do |config|
                # For xcode 15+ only
                if config.base_configuration_reference && Integer(xcode_base_version) >= 15
                xcconfig_path = config.base_configuration_reference.real_path
                xcconfig = File.read(xcconfig_path)
                xcconfig_mod = xcconfig.gsub(/DT_TOOLCHAIN_DIR/, "TOOLCHAIN_DIR")
                File.open(xcconfig_path, "w") { |file| file << xcconfig_mod }
                end
            end
            end
        end
    
    end
  3. 输入export all_proxy=socks5://127.0.0.1:1081

  4. 输入pod install --repo-update

Info.plist修改

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

商店评分

Google UMP

代码修改->iOS平台相关函数

代码修改->ATT

  1. 添加依赖AppTrackingTransparency.framework

  2. 在AppController.mm里包含头文件

    #import <AppTrackingTransparency/AppTrackingTransparency.h>

  3. 在applicationDidBecomeActive函数里增加如下代码

    //att
    if (@available(iOS 14, *)) {
        NSUInteger status = ATTrackingManager.trackingAuthorizationStatus;
        if (status == ATTrackingManagerAuthorizationStatusNotDetermined) {
            NSLog(@"[ios att log] 未决定");
            [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
                if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
                    NSLog(@"[ios att log] 用户同意");
                } else {
                    NSLog(@"[ios att log] 用户不同意");
                }
            }];
        } else if (status == ATTrackingManagerAuthorizationStatusRestricted) {
            NSLog(@"[ios att log] 限制");
        } else if (status == ATTrackingManagerAuthorizationStatusDenied) {
            NSLog(@"[ios att log] 拒绝");
        } else if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
            NSLog(@"[ios att log] 同意");
        }
    }
  4. 在Info.plist里增加如下代码:

    <key>NSUserTrackingUsageDescription</key>
    <string>Your data will be used to avoid random ads and get better game experiences!</string>

代码修改->广告

  1. 根据需要集成的广告平台,在官网勾选后拷贝到Podfile里并pod。

  2. 在Info.plist里增加如下代码:

    <key>AppLovinSdkKey</key>
    <string>SpT1TmLovSn4vQJxPipKB1xbGpB-4pEXciZASvyMMkQF8lBTR-td0pEHcPFhDUDrBo_egy_2fQHp9TLaSDCS0Q</string>
    <key>SKAdNetworkItems</key>
    <array>
        //balabala
    </array>
  3. 初始化:#import <AppLovinSDK/AppLovinSDK.h>

    //1. ad
    [ALSdk shared].mediationProvider = @"max";
    [[ALSdk shared] initializeSdkWithCompletionHandler:^(ALSdkConfiguration *configuration) {
        NSLog(@"[ios gdpr log] country code=%@", configuration);
        PFIOS::of_maxad_inter_init();
        PFIOS::of_maxad_reward_init();
    }];
    [[ALSdk shared] showMediationDebugger];
  4. 拷贝视频和插屏的两个类文件

代码修改->adjust

  1. #import <Adjust.h>

    NSString* adjustToken = @"rw5l7ub4y48w";
    NSString *adjustEnvironment = ADJEnvironmentProduction;
    ADJConfig* adjustConfig = [ADJConfig configWithAppToken:adjustToken environment:adjustEnvironment];
    [Adjust appDidLaunch:adjustConfig];
  2. 添加依赖AdSupport.framework、AdServices.framework、StoreKit.framework、AppTrackingTransparency.framework、WebKit.framework

    https://help.adjust.com/zh/article/get-started-ios-sdk

代码修改->EAS

  1. 在Info.plist里增加如下代码:

    <key>EAS_APP_ID</key>
    <string>8429kznyiqu0mpg9twsoclgy</string>
  2. #import <YFData/YFData.h>

    YFDataCommon.common.app_reg = YFREGION_CHINA;
    [YFDataHelper start:^(NSError * _Nullable error) {
      if (error) {
        //初始化错误不影响数据的打点及上传
        YFDataLogInfo(@"初始化错误:%@", error.localizedDescription);
      } else {
        YFDataLogInfo(@"初始化成功");
      }
    }];

代码修改->内购

  1. 共享密钥

代码修改->

解决报错->Undefined symbol: _ADJEnvironmentProduction

  1. 添加一个swift文件,并添加桥接文件。

  2. 在Build Settings->Linking->Other Linker Flags添加$(inherited)-ObjC

  3. 在Build Settings->Search Paths->Library Search Paths添加$(inherited)

解决报错->Undefined symbol: OBJC_CLASS$_GCController

  1. 添加框架GameController.frameworkMediaPlayer.framework

解决报错->运行崩溃:The Google Mobile Ads SDK was initialized without an application ID

  1. 在Info.plist里增加如下代码:

    <key>GADApplicationIdentifier</key>
    <string>ca-app-pub-xxx</string>

步骤

  1. 打开要比较的两个文件夹。

  2. 打开一个有差异的文件。

  3. 【会话】->【会话设置】->【重要】

    取消勾选【比较行终止符】

    选择【用于父会话中的所有文件】

  4. 关闭文件比较窗口,回到文件夹比较窗口。

  5. 【会话】->【会话设置】->【比较】

    勾选【比较内容】,选择【基于规则的比较】

  6. 【编辑】->【完全刷新】

cpp

所有视频能否播放和播放都路由到CandyManager

bool CandyManager::of_video_can_play(const string& as_page) {
	cocos2d::log("maxadlog call func CandyManager::of_video_can_play(%s). game_level=%d", as_page.c_str(), g.game_level);
	if (g.game_level < 5 && "n_video_finish_ad_play" == as_page)
	{
		return false;
	}
	return PFJava::cpp_func_of_can_play_ad_video(as_page, g.game_level);
}
void CandyManager::of_video_play(const string& as_page) {
	PFJava::cpp_func_of_play_ad_video(as_page, g.game_level);
	g.cm->of_play_video_set_state();

	// 数据统计与追踪
	of_track_function(as_page);
	of_track_function("n_video_all");
	of_adjust_event_time("n_video_time");

	// 成就统计
	candy_achievement->of_add_key(_bbb_ccc_ffff_lll_pub_achieve_count_ad);
}
// PF.cpp
bool PFJava::cpp_func_of_can_play_ad_video(const string & as_page, long al_level)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	JniMethodInfo t;
	if (JniHelper::getStaticMethodInfo(t, "org/cocos2dx/help/plugin/DreamPub", "of_vedio_can_play", "(Ljava/lang/String;J)J"))
	{
		jstring k1 = t.env->NewStringUTF(as_page.c_str());
		jlong j1(al_level);
		long ret = t.env->CallStaticLongMethod(t.classID, t.methodID, k1, j1);
		if (ret == 1) {
			return true;
		}
	}
	return false;
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
	return PFIOS::ios_func_is_video_can_play(as_page);
#endif
	// windows下
	auto s1 = PF::read_asset_string("config/app_config");
	s1 = PF::key_format(s1, "exe_have_video");
	if (s1 == "true") {
		return true;
	}
	return false;
}
void PFJava::cpp_func_of_play_ad_video(const string & as_page, long al_level)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) 
	JniMethodInfo t;
	if (JniHelper::getStaticMethodInfo(t, "org/cocos2dx/help/plugin/DreamPub", "of_vedio_play", "(Ljava/lang/String;J)V"))
	{
		jstring k1 = t.env->NewStringUTF(as_page.c_str());
		jlong j1(al_level);
		t.env->CallStaticVoidMethod(t.classID, t.methodID, k1, j1);
	}
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
	PFIOS::ios_func_play_video();
#endif
}
//DreamPub.java
public static long of_vedio_can_play(String as_page, long al_level){
    if (al_level < 5) return 0;
    if (as_page == null) as_page = "";
    if (MaxAdHelper.of_can_show_video(as_page)) {
        Log.d("maxadlog" , "of can show video(" + as_page + ") = true.");
        return 1;
    }
    Log.d("maxadlog" , "of can show video(" + as_page + ") = false." ) ;
    return 0;
}
/**
 * 视频播放状态   ,读取一次后将失效
 *    0 空
 *    1 成功
 *    2 失败
 *    9 正在播放
 */
public static long il_vedio_state = 0 ;
public static void of_vedio_play(String as_page, long al_level){

    // 如果没有广告,直接返回失败。
    if(of_vedio_can_play(as_page, al_level) == 0 ){
        AppActivity.buyItemOk("VIDEO_PLAY_CANCEL");
        return;
    }


    AppActivity.ib_video_have_award = false;


    Log.d("XXXXX" , "XXXXX SDKAgent.showVideo(  ls_page   ); "  + as_page ) ;
    il_vedio_state = 9 ;

    if( as_page == null) as_page = "";
    MaxAdHelper.of_show_video(as_page, al_level);

    Log.d("XXXXX" , "XXXXX SDKAgent.showVideo(  ls_page   ); "  + as_page ) ;

}

插屏

删去暂停插屏,只留下成功和失败

//PanelFinish.cpp
void PanelFinish::on_fail_continue(){
	g.of_inter_play("page_fail");
}
PanelFinish::PanelFinish(LayerGame* lay){
    if (g.ct->is_passed()) {
        g.of_inter_play("page_succ");
    }
}
//CandyManager.cpp
bool CandyManager::of_inter_can_play(const string& as_page)
{
	cocos2d::log("maxadlog call func CandyManager::of_inter_can_play(%s). bought=%f, game_level=%d", as_page.c_str(), g.cm->pub_money_buyed_total, g.game_level);;
	if (g.cm && g.cm->pub_money_buyed_total > 0.1f)
	{
		return false;
	}
	if (g.game_level < 10)
	{
		return false;
	}
	return PFJava::cpp_func_of_can_play_ad_inter(as_page, g.game_level);
}
void CandyManager::of_inter_play(const string& as_page)
{
	if (of_inter_can_play(as_page))
	{
		PFJava::cpp_func_of_play_inter_pub(as_page, g.game_level);
	}
}
//PF.cpp
bool PFJava::cpp_func_of_can_play_ad_inter(std::string as_page, long al_level)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) 
	JniMethodInfo t;
	if (JniHelper::getStaticMethodInfo(t, "org/cocos2dx/help/plugin/DreamPub", "java_func_of_inter_can_play", "(Ljava/lang/String;J)J"))
	{
		jstring k1 = t.env->NewStringUTF(as_page.c_str());
		jlong j1(al_level);
		long ret = t.env->CallStaticLongMethod(t.classID, t.methodID, k1, j1);
		if (ret == 1) {
			return true;
		}
	}
	return false;
#endif
	return false;
}
void PFJava::cpp_func_of_play_inter_pub(std::string as_page, long al_level)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	JniMethodInfo t;
	string ls_fun = "of_ad_interval_pub";
	if (JniHelper::getStaticMethodInfo(t, "org/cocos2dx/help/plugin/DreamPub", ls_fun.c_str(), "(Ljava/lang/String;J)V"))
	{
		jstring k1 = t.env->NewStringUTF(as_page.c_str());
		jlong j1(al_level);
		t.env->CallStaticVoidMethod(t.classID, t.methodID, k1, j1);
	}
	return;
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
	cocos2d::log("win32 platform:as_page=%s, al_level=%d", as_page.c_str(), al_level);
#endif
}
//DreamPub.java
public static void of_ad_interval_pub(final String as_page, long al_level) {
    if (_activity == null ) return;
    if (ib_noad ) return;
    Log.d("maxadlog" , "XXXXX of ad interval pub(" + as_page +  "," + al_level + "). begin") ;
    MaxAdHelper.of_show_inter(as_page, al_level);
    Log.d("maxadlog" , "XXXXX of ad interval pub(" + as_page +  "," + al_level + "). end") ;
}
public static long java_func_of_inter_can_play(String as_page, long al_level) {
    if (MaxAdHelper.of_can_show_inter(as_page, al_level)) {
        return 1;
    }
    return 0;
}
0%