基本的なアプリ内メッセージ開発者統合ガイドをお探しですか?ここで見つけてくださいhere.
上級実装ガイド
このオプションの上級実装ガイドでは、アプリ内メッセージコードに関する考慮事項、Braze チームが作成した 3 つのカスタムユースケース、付属のコードスニペットについて説明します。Braze Demo リポジトリにはこちらからアクセスできます。この実装ガイドは、Kotlin 実装を中心に扱っていますが、興味のある方のために Java のスニペットが提供されています。HTML の実装をお探しですか?Braze のHTML テンプレートリポジトリをご確認ください。
コードに関する考慮事項
次のガイドでは、デフォルトのアプリ内メッセージに加えてオプションで使用できる、開発者向けカスタム統合機能について説明します。各ユースケースにはカスタムビューコンポーネントとファクトリーが必要に応じて含まれており、機能を拡張したり、アプリ内メッセージの外観をネイティブにカスタマイズしたりするためのサンプルが用意されています。同様の結果を得る方法が複数ある場合があります。最適な実装は、特定のユースケースによって異なります。
カスタムファクトリー
Braze SDK を使用すると、開発者はカスタムファクトリーオブジェクトを通じて多くのデフォルトをオーバーライドできます。カスタムファクトリーオブジェクトを必要に応じて Braze SDK に登録して、目的の結果を得ることができます。ただし、ほとんどの場合、ファクトリーをオーバーライドする場合は、明示的にデフォルトに従うか、Braze デフォルトで提供される機能を再実装する必要があります。次のコードスニペットは、IInAppMessageViewFactory
および IInAppMessageViewWrapperFactory
インターフェイスのカスタム実装を提供する方法を示しています。デフォルトファクトリーのオーバーライドの背後にある概念をしっかりと理解したら、ユースケースを確認してカスタムのアプリ内メッセージング機能の実装を開始してください。
アプリ内メッセージのタイプ
1
2
3
4
5
6
7
8
class BrazeDemoApplication : Application(){
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(BrazeActivityLifecycleCallbackListener(true, true))
BrazeInAppMessageManager.getInstance().setCustomInAppMessageViewWrapperFactory(CustomInAppMessageViewWrapperFactory())
BrazeInAppMessageManager.getInstance().setCustomInAppMessageViewFactory(CustomInAppMessageViewFactory())
}
}
アプリ内メッセージのタイプ
1
2
3
4
5
6
7
8
9
public class BrazeDemoApplication extends Application {
@Override
public void onCreate{
super.onCreate();
registerActivityLifecycleCallbacks(new BrazeActivityLifecycleCallbackListener(true, true));
BrazeInAppMessageManager.getInstance().setCustomInAppMessageViewWrapperFactory(new CustomInAppMessageViewWrapperFactory());
BrazeInAppMessageManager.getInstance().setCustomInAppMessageViewFactory(new CustomInAppMessageViewFactory());
}
}
ユースケース
私たちは以下に3つのユースケースを提供しました。各ユースケースにはコードスニペットが含まれており、アプリ内メッセージがBrazeダッシュボードでどのように表示され、使用されるかを確認できます。
カスタムスライドアップアプリ内メッセージ
スライドアップのアプリ内メッセージを作成しているときに、デフォルトの方法ではメッセージの配置を変更できないことに気付くかもしれません。このような変更は、DefaultInAppMessageViewWrapper
クラスをサブクラス化してレイアウトパラメーターを調整することで可能になります。画面上の最終位置を調整するには、変更された LayoutParams
を返す getLayoutParams
メソッドを独自のカスタム位置決め値でオーバーライドします。開始するには、CustomSlideUpInAppMessageViewWrapper をご覧ください。
カスタムビューラッパー
カスタムレイアウトパラメーターをオーバーライドして返す
getLayoutParams
メソッド内では、スーパークラスメソッドを使用して、アプリ内メッセージの元の LayoutParameters
にアクセスできます。次に、必要に応じて加算または減算して位置を調整できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class CustomSlideUpInAppMessageViewWrapper(inAppMessageView: View?,
inAppMessage: IInAppMessage?,
inAppMessageViewLifecycleListener: IInAppMessageViewLifecycleListener?,
configurationProvider: BrazeConfigurationProvider?,
openingAnimation: Animation?,
closingAnimation: Animation?,
clickableInAppMessageView: View?) : DefaultInAppMessageViewWrapper(inAppMessageView,
inAppMessage,
inAppMessageViewLifecycleListener,
configurationProvider,
openingAnimation,
closingAnimation,
clickableInAppMessageView) {
override fun getLayoutParams(inAppMessage: IInAppMessage?): ViewGroup.LayoutParams {
val params = super.getLayoutParams(inAppMessage) as FrameLayout.LayoutParams
params.bottomMargin = params.bottomMargin + 500 //move the view up by 500 pixels
return params
}
}
カスタムレイアウトパラメーターをオーバーライドして返す
getLayoutParams
メソッド内では、スーパークラスメソッドを使用して、アプリ内メッセージの元の LayoutParameters
にアクセスできます。次に、必要に応じて加算または減算して位置を調整できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class CustomSlideUpInAppMessageViewWrapper extends DefaultInAppMessageViewWrapper {
public CustomInAppMessageViewWrapper(View inAppMessageView,
IInAppMessage inAppMessage,
IInAppMessageViewLifecycleListener inAppMessageViewLifecycleListener,
BrazeConfigurationProvider configurationProvider,
Animation openingAnimation,
Animation closingAnimation,
View clickableInAppMessageView){
super(inAppMessageView,
inAppMessage,
inAppMessageViewLifecycleListener,
configurationProvider,
openingAnimation,
closingAnimation,
clickableInAppMessageView)
}
@Override
public ViewGroup.LayoutParams getLayoutParams(IInAppMessage inAppMessage){
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)super.getLayoutParams(inAppMessage)
params.bottomMargin = params.bottomMargin + 500 //move the view up by 500 pixels
return params
}
}
カスタムラッパーを返すためのカスタムファクトリーを指定する
Braze SDK でカスタムラッパーを使用するには、カスタムラッパーを返すカスタム IInAppMessageViewWrapperFactory
実装も指定する必要があります。IInAppMessageViewWrapperFactory
を直接実装することも、BrazeInAppMessageViewWrapperFactory
をサブクラス化して createInAppMessageViewWrapper
メソッドのみをオーバーライドすることもできます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class CustomInAppMessageViewWrapperFactory : BrazeInAppMessageViewWrapperFactory() {
override fun createInAppMessageViewWrapper(
inAppMessageView: View?,
inAppMessage: IInAppMessage?,
inAppMessageViewLifecycleListener: IInAppMessageViewLifecycleListener?,
configurationProvider: BrazeConfigurationProvider?,
openingAnimation: Animation?,
closingAnimation: Animation?,
clickableInAppMessageView: View?
): IInAppMessageViewWrapper {
return if (inAppMessage is InAppMessageSlideup) {
CustomSlideUpInAppMessageViewWrapper( //return our custom view wrapper only for slideups
inAppMessageView,
inAppMessage,
inAppMessageViewLifecycleListener,
configurationProvider,
openingAnimation,
closingAnimation,
clickableInAppMessageView
)
} else {
super.createInAppMessageViewWrapper( //defer to the default implementation for all other IAM types
inAppMessageView,
inAppMessage,
inAppMessageViewLifecycleListener,
configurationProvider,
openingAnimation,
closingAnimation,
clickableInAppMessageView
)
}
}
}
カスタムラッパーを返すためのカスタムファクトリーを指定する
Braze SDK でカスタムラッパーを使用するには、カスタムラッパーを返すカスタム IInAppMessageViewWrapperFactory
実装を指定する必要があります。IInAppMessageViewWrapperFactory
を直接実装することも、BrazeInAppMessageViewWrapperFactory
をサブクラス化して createInAppMessageViewWrapper
メソッドのみをオーバーライドすることもできます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class CustomInAppMessageViewWrapperFactory extends BrazeInAppMessageViewWrapperFactory {
@Override
public IInAppMessageViewWrapper createInAppMessageViewWrapper(View inAppMessageView,
IInAppMessage inAppMessage,
IInAppMessageViewLifecycleListener inAppMessageViewLifecycleListener,
BrazeConfigurationProvider configurationProvider,
Animation openingAnimation,
Animation closingAnimation,
View clickableInAppMessageView){
if (inAppMessage instanceof InAppMessageSlideup){
return new CustomSlideUpInAppMessageViewWrapper( //return our custom view wrapper only for slideups
inAppMessageView,
inAppMessage,
inAppMessageViewLifecycleListener,
configurationProvider,
openingAnimation,
closingAnimation,
clickableInAppMessageView);
}else{
return super.createInAppMessageViewWrapper(//defer to the default implementation for all other IAM types
inAppMessageView,
inAppMessage,
inAppMessageViewLifecycleListener,
configurationProvider,
openingAnimation,
closingAnimation,
clickableInAppMessageView);
}
}
}
ファクトリーを Braze に登録する
カスタムラッパーファクトリーを作成したら、BrazeInAppMessageManager
を使用して Braze SDK に登録します。
1
BrazeInAppMessageManager.getInstance().setCustomInAppMessageViewWrapperFactory(CustomInAppMessageViewWrapperFactory())
ファクトリーを Braze に登録する
カスタムラッパーファクトリーを作成したら、BrazeInAppMessageManager
を使用して Braze SDK に登録します。
1
BrazeInAppMessageManager.getInstance().setCustomInAppMessageViewWrapperFactory(new CustomInAppMessageViewWrapperFactory());
カスタムモーダルアプリ内メッセージ
BrazeInAppMessageModalView
をサブクラス化すると、貴重なユーザー属性を収集する魅力的な方法となる Spinner
を活用できます。次の例は、コネクテッドコンテンツを使用して項目の動的リストからカスタム属性をキャプチャする方法を示しています。開始するには、TeamPickerView
にアクセスしてください。
UI 表示動作に view_type
を使用
IInAppMessage
オブジェクトの extras
ディクショナリをクエリすると、view_type
キー (ある場合) を検索して正しいタイプのビューを表示できます。アプリ内メッセージはメッセージごとに設定されるため、カスタムとデフォルトのモーダルビューが調和して機能することに注意してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
override fun createInAppMessageView(activity: Activity, inAppMessage: IInAppMessage): View {
return when {
inAppMessage.extras?.get("view_type") == "picker" -> {
getCustomPickerView(activity, inAppMessage)
}
//...
else -> {
//Defer to default
BrazeInAppMessageManager
.getInstance()
.getDefaultInAppMessageViewFactory(inAppMessage).createInAppMessageView(activity, inAppMessage)
}
}
}
UI 表示動作に view_type
を使用
IInAppMessage
オブジェクトの extras
ディクショナリをクエリすると、view_type
キー (ある場合) を検索して正しいタイプのビューを表示できます。アプリ内メッセージはメッセージごとに設定されるため、カスタムとデフォルトのモーダルビューが調和して機能することに注意してください。
1
2
3
4
5
6
7
8
9
10
11
12
@Override
public View createInAppMessageView(Activity activity, IInAppMessage inAppMessage) {
if("picker".equals(inAppMessage.getExtras().get("view_type"))){
return getCustomPickerView(activity, inAppMessage);
} else {
//Defer to default
BrazeInAppMessageManager
.getInstance()
.getDefaultInAppMessageViewFactory(inAppMessage)
.createInAppMessageView(activity, inAppMessage);
}
}
オーバーライドしてカスタムビューを提供する
標準のモーダルアプリ内メッセージを模倣したレイアウトを提供しますが、ビューをルート要素として指定し、そのレイアウトをインフレートします
1
2
3
4
5
6
7
8
9
10
11
<com.braze.advancedsamples.inapp.modal.TeamPickerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="0.0dp"
android:id="@+id/team_picker_view">
<!-- ... -->
<Spinner android:layout_width="match_parent" android:layout_height="wrap_content"
android:id="@+id/team_spinner"/>
<!-- ... -->
</com.braze.advancedsamples.inapp.modal.TeamPickerView>
ビューをインフレートしてカスタマイズする
Spinner
コンポーネントをリロードする前に、inAppMessage
メッセージ変数は文字列として出力されます。正しく表示するには、このメッセージを項目の配列としてフォーマットする必要があります。例として、これは String.split(",")
を使用して実現できます。
1
2
3
4
5
6
private fun getCustomView(activity: Activity, inAppMessage: IInAppMessage): TeamPickerView {
val view = activity.layoutInflater.inflate(R.layout.team_picker_dialog, null) as TeamPickerView
val teams = inAppMessage.message.split(",")
view.setTeams(teams)
return view
}
ビューをインフレートしてカスタマイズする
Spinner
コンポーネントをリロードする前に、inAppMessage
メッセージ変数は_文字列_として出力されます。正しく表示するには、このメッセージを項目の配列としてフォーマットする必要があります。例として、これは String.split(",")
を使用して実現できます。
1
2
3
4
5
6
private TeamPickerView getCustomView(Activity activity, IInAppMessage inAppMessage) {
TeamPickerView view = (TeamPickerView) activity.getLayoutInflater().inflate(R.layout.team_picker_dialog, null);
String[] teams = inAppMessage.getMessage().split(",");
view.setTeams(teams);
return view
}
カスタム属性を割り当てる
ユーザーが [送信] を押した後、ビューサブクラスを使用して、属性とそれに対応する選択済みの値を Braze に渡し、messageClickableView.performClick()
を呼び出してアプリ内メッセージを閉じます。
1
2
3
4
5
6
7
override fun onClick(v: View?) {
val selectedTeam = spinner.selectedItem as String
messageClickableView.performClick()
Braze.getInstance(ctx).getCurrentUser { brazeUser ->
brazeUser?.setCustomUserAttribute("FavoriteTeam", selectedTeam)
}
}
カスタム属性を割り当てる
ユーザーが [送信] を押した後、ビューサブクラスを使用して、属性とそれに対応する選択済みの値を Braze に渡し、messageClickableView.performClick()
を呼び出してアプリ内メッセージを閉じます。
1
2
3
4
5
6
7
8
@Override
public void onClick(View v) {
String selectedTeam = (String) spinner.getSelectedItem();
messageClickableView.performClick();
Braze.getInstance(ctx).getCurrentUser(brazeUser -> {
brazeUser.setCustomUserAttribute("FavoriteTeam", selectedTeam);
});
}
カスタムフルアプリ内メッセージ
完全にカスタムの没入型 (全画面) アプリ内メッセージを実装するには、カスタマイズされたモーダルアプリ内メッセージの実装に関するセクションで説明したのと同様のアプローチが必要です。ただし、この例では、単に BrazeInAppMessageFullView
を拡張し、必要に応じてカスタマイズします。ビューはアプリケーション UI 上に表示され、Android のビューはデフォルトで透明であることに注意してください。つまり、アプリ内メッセージによって背景の内容が見えにくくなるような背景を定義する必要があります。BrazeInAppMessageFullView
を拡張することにより、Braze SDK はビュー上のタッチイベントのインターセプトを処理し、適切なアクションを実行します。モーダルの例と同様に、特定のコントロール (Switch
コントロールなど) でこの動作をオーバーライドして、ユーザーからのフィードバックを収集できます。
UI 表示動作に view_type
を使用
新しい没入型カスタマイズのために、view_type
エクストラをもう 1 つ追加します。createInAppMessageView
メソッドをもう一度見直して、「スイッチ」UI のオプションを追加します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
override fun createInAppMessageView(activity: Activity, inAppMessage: IInAppMessage): View {
return when {
inAppMessage.extras?.get("view_type") == "picker" -> {
getCustomPickerView(activity, inAppMessage)
}
inAppMessage.extras?.get("view_type") == "switches" -> {
getCustomImmersiveView(activity, inAppMessage) // new customization
}
else -> {
//Defer to default
BrazeInAppMessageManager
.getInstance()
.getDefaultInAppMessageViewFactory(inAppMessage).createInAppMessageView(activity, inAppMessage)
}
}
}
UI 表示動作に view_type
を使用
新しい没入型カスタマイズのために、view_type
エクストラをもう 1 つ追加します。createInAppMessageView
メソッドをもう一度見直して、「スイッチ」UI のオプションを追加します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
public View createInAppMessageView(Activity activity, IInAppMessage inAppMessage) {
if("picker".equals(inAppMessage.getExtras().get("view_type"))){
return getCustomPickerView(activity, inAppMessage);
} else if ("switches".equals(inAppMessage.getExtras().get("view_type"))) {
return getCustomImmersiveView(activity, inAppMessage); // new customization
} else {
//Defer to default
BrazeInAppMessageManager
.getInstance()
.getDefaultInAppMessageViewFactory(inAppMessage)
.createInAppMessageView(activity, inAppMessage);
}
}
オーバーライドしてカスタムビューを提供する
標準のモーダルアプリ内メッセージを模倣したレイアウトを提供しますが、ビューをルート要素として指定し、そのレイアウトをインフレートします
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<com.braze.advancedsamples.immersive.CustomImmersiveInAppMessage
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- giving the parent layout a white backround color will obscure the app behind the IAM. You could also do this within your custom view -->
<LinearLayout android:background="@color/white" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center">
<!-- ... -->
<androidx.recyclerview.widget.RecyclerView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/option_list"/>
<!-- ... -->
</LinearLayout>
</com.braze.advancedsamples.immersive.CustomImmersiveInAppMessage>
ビューをインフレートしてカスタマイズする
RecyclerView
コンポーネントのオプションを設定する前に、inAppMessage
メッセージ変数が_文字列_として出力されます。正しく表示するには、このメッセージを項目の配列としてフォーマットする必要があります。例として、これは String.split(",")
を使用して実現できます。title
とsubtitle
もextras
バンドルから抽出されます。
1
2
3
4
5
6
7
8
private fun getCustomImmersiveView(activity: Activity, inAppMessage: IInAppMessage): CustomImmersiveInAppMessage{
val view = activity.layoutInflater.inflate(R.layout.full_screen_iam, null) as CustomImmersiveInAppMessage
val options = inAppMessage.message.split(",")
view.setOptions(options)
inAppMessage.extras?.get("title").let { view.setTitle(it) }
inAppMessage.extras?.get("subtitle").let {view.setSubtitle(it) }
return view
}
ビューをインフレートしてカスタマイズする
RecyclerView
コンポーネントのオプションを設定する前に、inAppMessage
メッセージ変数が_文字列_として出力されます。正しく表示するには、このメッセージを項目の配列としてフォーマットする必要があります。例として、これは String.split(",")
を使用して実現できます。title
とsubtitle
もextras
バンドルから抽出されます。
1
2
3
4
5
6
7
8
9
10
private CustomImmersiveInAppMessage getCustomImmersiveView(Activity activity, IInAppMessage inAppMessage) {
CustomImmersiveInAppMessage view = (CustomImmersiveInAppMessage) activity.layoutInflater.inflate(R.layout.full_screen_iam, null);
String[] options = inAppMessage.message.split(",");
view.setOptions(options);
String title = inAppMessage.getExtras().get("title");
view.setTitle(title);
String subtitle = inAppMessage.getExtras().get("subtitle");
view.setSubtitle(subtitle);
return view;
}
カスタム属性を割り当てる
ユーザーがいずれかのスイッチを切り替えた後、ビューサブクラスを使用して、関連する属性とトグルステータスを Braze に渡します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
fun logClick(value:String, checked:Boolean){
Braze.getInstance(ctx).logCustomEvent("SwitchChanged", BrazeProperties())
}
inner class OptionViewHolder(item: View): RecyclerView.ViewHolder(item), View.OnClickListener{
var value: String = ""
override fun onClick(p0: View?) {
if (p0 is Switch){
val checked = p0.isChecked
p0.isChecked = !p0.isChecked
logClick(value, checked)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionViewHolder {
return OptionViewHolder(mInflater.inflate(R.layout.switch_cell, null))
}
override fun onBindViewHolder(holder: OptionViewHolder, position: Int) {
holder.itemView.findViewById<TextView>(R.id.label).text = options[position]
holder.value = options[position]
}
カスタム属性を割り当てる
ユーザーがいずれかのスイッチを切り替えた後、ビューサブクラスを使用して、関連する属性とトグルステータスを Braze に渡します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private void logClick(String value, boolean checked){
Braze.getInstance(ctx).logCustomEvent("SwitchChanged", new BrazeProperties());
}
private class OptionViewHolder extends RecyclerView.ViewHolder, implements View.OnClickListener{
private String value = "";
public OptionViewHolder(View item){
super(item);
}
@Override
public void onClick(View view) {
if (view instanceof Switch){
Switch switchView = (Switch) view;
boolean checked = switchView.isChecked;
switchView.isChecked = !switchView.isChecked;
logClick(value, checked)
}
}
}
@Override
public OptionViewHolder onCreateViewHolder(ViewGroup parent, Int viewType) {
return new OptionViewHolder(mInflater.inflate(R.layout.switch_cell, null));
}
@Override
public void onBindViewHolder(OptionViewHolder holder, Int position) {
((TextView)holder.getItemView().findViewById(R.id.label)).setText(options.get(position));
holder.value = options.get(position);
}
アプリ内メッセージタッチのインターセプト
カスタムフルアプリ内メッセージボタンを正しく機能させるには、アプリ内メッセージのタッチをインターセプトすることが重要です。デフォルトでは、すべてのアプリ内メッセージビューにonClick
リスナーが追加されるため、ユーザーはボタンなしでメッセージを閉じることができます。カスタムボタンなど、ユーザー入力に応答するカスタムコントロールを追加する場合は、通常どおりビューにonClick
リスナーを登録できます。カスタムコントロールの外側をタッチすると、通常通りアプリ内メッセージが閉じられ、カスタムコントロールが受け取ったタッチはあなたのonClick
リスナーを呼び出します。