构建真实世界的React Native应用(附代码示例)

156 阅读9分钟

上一章中,我们在React Native应用中配置了应用内购买功能。在本章中,我们将应用它来实现移除广告的功能。首先,我们要实现移除广告的屏幕,它将有一个隐私政策和使用条款,以及触发基于订阅的付款的按钮。这一章有点复杂,因为我们在这里处理的是实际的钱。但是,我们将一步一步地进行,使实施简单易懂。在本教程的最后,我们将能够使测试从应用程序本身删除广告购买。

让我们开始吧!

控制主屏幕上的横幅显示

因此,基于订阅的购买也是成功的。由于购买成功,广告会自动隐藏起来。

现在在主屏幕中,我们需要导入我们要使用的状态,以便切换广告状态。首先,我们需要导入IApContext,如下面的代码片段所示:

import { IApContext } from '../components/IApController'

然后,我们需要使用useContext钩子从IApContext获得showads函数,如下面的代码片段所示:

const { showads } = useContext(IApContext)

因此,我们现在可以把它作为渲染的条件,如下面的代码片段所示:

renderItem={({ item ,index}) => (
         <React.Fragment>
                <FlatlistItem item={item} navigation={navigation} />
                {showads && index % 3 == 0 ? renderBanner() : <View />}
          /React.Fragment>
  )}

因此,我们将得到下面截图中显示的结果:

Showing banner on home page

在主页上显示横幅

控制横幅在单篇文章屏幕上的显示

另一个屏幕是SinglePost帖子屏幕,我们在其中做同样的事情。我们首先导入上下文类,如下面的代码片断所示:

import { IApContext } from '../components/IApController'

然后,我们需要挑选可以用于切换的状态,如下面的代码片断所示:

const { showads } = useContext(IApContext)

因此,如下面的代码片断所示,将其应用于条件渲染:

</Card.Content>
                   {showads && renderBanner()}
                   <ImageLoad
                       style={{ width: '100%', height: 250 }}
                       loadingStyle={{ size: 'large', color: 'grey' }}
                       source={{ uri: post[0].jetpack_featured_media_url }}
               />

此外,我们还需要将其添加到奖励广告中,如下面的代码片断所示:

const renderContent = () => {
 
       if (point <= 0 && showads) {
           return renderRewardAdsButton();
       }

因此,我们得到的结果如下面的截图所示:

AdSense banner in single post screen

单篇文章屏幕中的AdSense横幅

检查产品状态

现在,当我们再次加载应用程序时,我们还需要通过使用getAvaliablePurchase函数来检查用户状态,即用户是否已经购买了产品。这方面的编码实现在下面的代码片段中提供:

checkValidPurchase = async () => {
       try {
           const purchases = await RNIap.getAvailablePurchases();
 
           purchases.forEach(async (purchase) => {
               switch (purchase.productId) {
                   case 'kriss.once.removeads':
                       // await AsyncStorage.setItem('removeadsmonthly', JSON.stringify(res));
                       toggleAds(false)
                       break
 
                   case 'kriss.sub.removeads':
                       //   await AsyncStorage.setItem('removeadsmonthly', JSON.stringify(res));
                       toggleAds(false)
                       break
                   case 'com.kriss.remove_ads_monthly':
                       // await AsyncStorage.setItem('removeadsmonthly', JSON.stringify(res));
                       toggleAds(false)
                       break
                   case 'com.kriss.remove_ad_forever':
                       //   await AsyncStorage.setItem('removeadsmonthly', JSON.stringify(res));
                       toggleAds(false)
                       break
                   default: console.warn('your did not have any purchase');
 
               }
           })
 
       } catch (err) {
           console.warn(err);
       }
   }

然后,我们需要在Navigator.js文件中激活它,如下面的代码片断所示:

const { initIAp, checkValidPurchase } = useContext(IApContext);
 
   useEffect(() => {
       initIAp()
       checkValidPurchase()
   }, [])

在安卓上设置应用内购买

安卓系统的设置比iOS系统更复杂。在安卓系统中,我们需要发布APK,以便在激活Playstore仪表板上的计费功能之前添加计费权限。

首先,我们需要打开 AndroidManifest.xml文件并添加以下一行代码:

<uses-permission android:name="com.android.vending.BILLING" />

然后,我们需要通过使用以下命令为发布APK生成一个keystore文件:

keytool -genkeypair -v -keystore myupload.keystore -alias mykeyalias -keyalg RSA -keysize 2048 -validity 10000

密钥库文件将出现在app文件夹中,如下面的截图所示:

Keystore location

钥匙库位置

现在,我们需要打开build.gradle文件,按照下面的代码片段的指示添加keystore文件名:

signingConfigs {
       debug {
           storeFile file('debug.keystore')
           storePassword 'android'
           keyAlias 'androiddebugkey'
           keyPassword 'android'
       }
        release {
           storeFile file('myuploadkey.keystore')
           storePassword '111111'
           keyAlias 'my-key-alias'
           keyPassword '111111'
       }
      
   }
   buildTypes {
       debug {
           signingConfig signingConfigs.debug
       }
       release {
            crunchPngs false
       
           signingConfig signingConfigs.release
           minifyEnabled enableProguardInReleaseBuilds
           proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
       }
   }

现在,我们可以通过运行以下命令为我们的应用程序生成发布APK:

cd android/ ; ./gradlew bundleRelease

然后,我们的APK文件将出现在以下路径中:

android/app/build/outputs/bundle/release/app.aab

接下来,我们需要去Playstore仪表板,并创建一个新的应用程序,如下面的屏幕截图所示:

Create a new Playstore app

创建一个新的Playstore应用程序

然后,我们需要进入应用内购买,在那里我们将看到APK要求的信息,如下面的截图所示,具有计费权限。

Playstore dashboard

Playstore仪表板

接下来,我们需要选择APK并上传新的APK。然后,我们需要滚动到内部应用程序共享,如下面的截图所示:

Playstore APK management dashboard

Playstore APK管理仪表板

然后,我们需要挑选已发布的APK,并填写版本和描述信息,如下截图所示:

Playstore app release description

Playstore应用发布描述

最后一步是邀请测试者使用他们的电子邮件在Android设备上注册,如下图所示:

Invite tester on Playstore

在Playstore上邀请测试者

现在,我们也可以在Android上测试应用内购买选项了:

Release summary in Playstore app

在Playstore应用程序中发布摘要

如果我们得到以下状态,我们也可以在安卓平台上安装并开始测试:

app status in playstore

Playstore中的应用程序状态

对于测试人员,他们将收到电子邮件邀请,如下图所示:

Playstore invite tester with email

Playstore用电子邮件邀请测试者

因此,他们现在也可以安装该应用程序。

Install app on early access

在早期访问中安装应用程序

因此,我们已经成功地为该应用程序设置了测试人员,如下图所示:

Install android app in tester mode

在测试者模式下安装安卓应用

创建应用内产品

现在,我们也可以在Android中创建应用内购买产品。首先,让我们了解一下应用内购买产品的一些类型。

应用内购买产品的类型

应用内购买产品有很多类型:

  • 消耗性产品:消耗性产品是那些用户每次重新安装或更换设备时都需要购买的产品。这些产品一旦购买就不能免费使用。因此,需要反复购买。一些例子可以是游戏应用程序中的货币、提示和健康。
  • 非消耗性产品:这是买了一次就可以在未来永远免费使用的产品。一旦订阅或购买,用户在未来不需要再次购买。即使重新安装或更换设备,对这类产品的订阅也不会丢失。一些例子可以是订阅专业版或删除广告。
  • 不续约的订阅:这类产品可以由用户在一个固定的时间段内使用。一旦期限结束,用户必须再次购买或订阅它们。该服务在一定时期内是免费的。
  • 自动续订:这类服务有重新订阅重新购买的到期日,在结束期到来时自动完成。项目一经购买,在一定时期内可以使用,一旦期限结束,项目将自动重新购买。

现在,让我们开始创建Android应用内购买产品。

首先,我们需要进入管理产品选项卡,并插入产品ID,如下图所示:

Add new in-app product

添加新的应用内产品

接下来,我们需要添加描述,如下面的截图所示:

Add in-app product description

添加应用内产品描述

最后,我们需要设置价格信息,如下面的截图所示:

Add in-app product price

添加应用内产品价格

因此,我们已经配置了一次性购买产品,如下图所示:

in-app product on playstore

Playstore上的应用内产品

接下来,我们转向基于订阅的购买。为此,我们需要到订阅标签创建订阅产品,如下图所示:

Add new subscription product in Playstore

在Playstore添加新的订阅产品

然后,我们需要添加产品ID,如下图所示:

Add id to subscription product

为订阅产品添加ID

添加订阅产品ID接下来,我们需要添加价格、期限和描述细节,如下截图所示:

Add in-app subscription description

添加应用内订阅描述

因此,我们已经成功设置了基于订阅的购买,如下图所示。

Successfully add new in-app subscription playstore

成功地添加新的应用内订阅Playstore

请注意,我们需要等待大约6-12小时的批准。

进行静态测试

在等待批准时,我们可以使用这三个产品ID进行测试:

  • android.test.purched 成功案例
  • android.test.canceled - 取消情况
  • android.test.item_unavailable - 不可用的情况

因此,我们可以按照下面的截图指示改变产品ID:

const itemSkus = Platform.select({
   ios: [
       'kriss.once.removeads',
       'kriss.sub.removeads'
   ],
   android: [
       'android.test.purchased',
       'android.test.canceled',
       'android.test.item_unavailable'
   ]
});

因此,在模拟器设备上购买产品的结果显示如下:

Result of testing in-app purchase on android

在安卓上测试应用内购买的结果

真实测试

一旦我们的应用内产品在Playstore上发布,我们可以在实际设备上进行实时测试。在这里,我们将能够从Playstore获取真实数据。

如下面的截图所示,也有一个多种支付选项的选项:

The result from display real in-app product

显示真实应用内产品的结果

付费阅读

我们可以在这个应用程序中实现应用内购买的另一种方式是限制用户对帖子的可读性。并且,实施一种机制,要求用户支付信用,以获得完整的帖子阅读。

首先,我们在App.js上给出初始信用额度为10

async function initPoint() {
    let initPoint = await AsyncStorage.getItem('yourcanreadfreepost');
    if (initPoint == null) {
      await AsyncStorage.setItem('yourcanreadfreepost', '10')
    }
  }

然后,我们在应用程序每次启动时调用该函数,如下图代码片段所示:

export default function App() {
  React.useEffect(() => {
    SplashScreen.hide()
    initPoint()
............other code.......

接下来,我们需要添加触发支付事件的函数:

const renderPaymentButton = () => {
    return (
      <View>
        <Title style={{textAlign: 'center'}}>
          Pay {products.products[1].localizedPrice} for read more 10 post
        </Title>
        <Button
          icon="bullhorn"
          color={'#53ccf9'}
          mode="contained"
          onPress={() => makePurchase(products.products[1].productId)}>
          Pay now
        </Button>
      </View>
    );
  };

现在在IAPController中,我们需要对该函数进行更新,以使支付成功。首先,我们需要检查产品的SKU,如果它在获取信贷时匹配。如果不匹配,那么我们需要添加新的信用,并将点设置为立即进入屏幕的状态。下面的代码片段中提供了整体的编码实现:

const [pointfromiap, setPointfromiap] = useState()
 
  makePurchase = async sku => {
    try {
      await RNIap.requestPurchase(sku, false).then(async res => {
        toggleAds(false);
        if(sku == 1){
          await AsyncStorage.setItem('yourcanreadfreepost', '10').then(res => {
            setPointfromiap(10)
        });
        }
      });
    } catch (err) {
      console.warn(err.code, err.message);
    }
  };

现在,如果用户用完了信用,我们将看到以下结果。

Payment result on playstore

playstore上的支付结果

最后,当支付成功时,将增加10个信用额度,并随后解除对用户的屏幕访问限制。

结语

嗯,这一章有点复杂。我们继续上一章的内容。我们找到了一个使用应用内购买的方法来赚点钱。我们在这里处理了实际的钱,以进行应用内购买,以去除应用中的广告。我们得到了如何在安卓和iOS平台上整合一次性和基于订阅的应用内购买的分步指导。我们实现了这一功能,为用户提供了去除恼人广告的选择。我们还在安卓和iOS中配置了测试员选项,以便也能启用测试机制。