子供の頃、多くの人が母親、姉妹、祖母のために手作りのカードを描いたと思います。 学校では、確かに。 しかし、一定の年齢を過ぎても、そのようなものに魅了されるのは非常に少数の人々にとどまっています。 あなたが彼女/妻にそのような何かを与えたことはありそうにない。 しかし、彼らはおそらくそれを好きになるでしょう、 心理学とそのすべて 。

当然、私たちプログラマー、肩幅の広い人々、絹のような紙でおびき寄せられることはないので、厚紙と色紙で作られた膝に貼り付けるのではなく、モバイルアプリケーションの形でハガキを作成することにしました。 幸いなことに、ホームレスの人々でさえスマートフォンを持っています。
免責事項
投稿で提示されたプログラムコードの品質、アイデアの独創性、またはその実装を装うつもりはありません。
私はあなたの目に責任を負いません。ひどいコードから炎症を起こし、プログラマーの気持ちをin辱します。
開発中に下した決定のほとんどが不完全であったことを理解しており、この投稿が他の開発者を同様の間違いから救うことを願っています
アイデアとタスクの分析
だから、成功し、明るく記憶に残るお祝いをするには、何が必要ですか? そうです、すごい効果です! これを行うには、お祝いのオブジェクトに対して目立たないようにすべてを行い、プログラミングの魔法を少し追加する必要があります。 幸いなことに、Androidには白と黒の両方があります。
スマートフォンにアプリケーションを作成してインストールしたとします 犠牲者 事業全体の犯人、そして何? 「 あそこからそのアプリケーションを起動してください 」または「 ちょっと電話をくれ...見て! 」 すごい効果はありません、希望すらありません。
したがって、私に起こった最高のことは、アプリケーションをプリインストールすることでした(私はそれを偽装したかったのですが、一般的には必要ありませんでした)。
ハガキの記入は、記念写真と「美しい、スマート、親切、 幸福、健康であり続けてほしい」というスタイルの短いお祝いで構成されています。 セットは個性的で、あなたはあなたのお祝いがどんな感じか決してわかりません。
すでに設計段階で、最初で最も重大な間違いを犯しました。 私はすぐに、たくさんのアニメーションを含む美しいカードを作成する時間があると決めました 。 このアニメーションとその最適化の経験はありません 。 視覚的に悪い結果になったとは言いませんが、追加したアニメーションがなければ、すべてが素晴らしく、問題も少なくなります。
ツールキット

仕事には、次のものが必要です。
- Android開発用のIDE
- 写真
犠牲者はがきのストック画像 - Google FirebaseまたはGoogle Cloud Firestore
- curlユーティリティまたはPOSTリクエストを送信するその他の手段
実装
アニメーションを作成するには、 WowoViewPagerライブラリを使用しました 。 そのようなプロジェクトに使用することはお勧めしません。
このライブラリを使用すると、ViewPagerで機能するアニメーションスライドを作成できます。 デフォルトのスクロールは、スワイプによって行われます。 ビュー要素の動き、アニメーションの速度、種類を完全にカスタマイズできます。 GIFおよびsvgアニメーションがサポートされています。
私の意見では、主な欠点は、すべての要素を1つのxmlファイルに保存する必要があることです。 ライブラリは、明らかに、多数のスライド用に設計されていません(元の例では、最大4つあります)。 私の場合、21枚のスライドと16枚のjpeg写真により、200 MBを超えるメモリが「食べられ」ました。
各プログラマーは独自の松葉杖と自転車を持っているため、アニメーションの作成プロセスについては説明しません。 フラグを使用してツールバーと通知バーを非表示にできることを言及したいだけです
getWindow().requestFeature(Window.FEATURE_ACTION_BAR); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
アニメーションライブラリを操作する過程で、やや予想外のtrapが待っていました。 古典的な絶対センタリングフォーミュラ
(screenWidth-viewWidth)/2
動作しませんでした。 経験的に、まったく同じ式が望ましい効果をもたらすことがわかりました。
screenWidth/2 - viewWidth/2
ただし、1つの例外的なケースでは、写真は式によってのみ中央揃えされました
screenWidth/3.5 - viewWidth/3.5
サイズの違いはY軸に沿って3ピクセルしかないという事実にもかかわらず(!Sic)

それは私がその瞬間に感じた方法です。 Androidの座標機能、ライブラリのバグ、または不器用な手との関係がわかりません。 おそらくコメントで誰かが同様の問題にぶつかりました。
カード自体の実現後、それは魔法の変わり目でした。
まず、 Firebase Consoleで新しいプロジェクトを作成します。
プロジェクトを作成するときに、名前と国を指定します。
次のステップは、書かれたポストカードにFirebaseを接続することです。 から選択する2つのオプションがあります: Realtime DatabaseとCloud Firestore 。 この特定のケースでは、違いはありません。両方のサービスが完璧に機能します。 グローバルな違いは何ですか-私は知りません。 Cloud Firestoreを使用しました。 リンクには公式チュートリアルがあります。
1)プロジェクトレベルでGradleの依存関係を指定する
dependencies { ... classpath 'com.google.gms:google-services:3.2.0' ... }
2)アプリモジュールレベルでGradle依存関係を指定します。 プッシュ通知を受信するための依存関係をすぐに考慮する
compile 'com.google.firebase:firebase-core:11.8.0' compile 'com.google.firebase:firebase-firestore:11.8.0' compile 'com.google.firebase:firebase-messaging:11.8.0'
3)サービスを作成してマニフェストに追加し、Firebaseトークンを受け取り、Cloud Firestoreでさらに記録します。 アプリケーションのリモート起動にはトークンが必要です。 私は、データベースから古いトークンを削除する機能を持っていないことに注意し、実装することができませんでした。 必要な場合、例はリンクの上にあります。
<application> ... <service android:name=".FirebaseIdService"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> </intent-filter> </service> ... </application>
public class FirebaseIdService extends FirebaseInstanceIdService { @Override public void onTokenRefresh() { // String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d("TOKEN REFRESH", refreshedToken); // FirebaseFirestore db = FirebaseFirestore.getInstance(); Map<String, Object> data = new HashMap<>(); // hashmap data.put("token", refreshedToken); //devices - db.collection("devices") .add(data) .addOnSuccessListener(new OnSuccessListener<DocumentReference>() { @Override public void onSuccess(DocumentReference documentReference) { Log.d("FIREBASE", "Data added, id: " + documentReference.getId()); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.d("FIREBASE", "Data adding failed, exception: \n" + e); } }); } }
4)Firebaseからプッシュ通知を受信するサービスを作成してマニフェストに追加します。 以前、Gradleに依存関係を追加しました。
Androidでプッシュ通知を作成および使用する原理については説明しません。 これ専用のサイトがあります。 上記の例は、Android 4.2.2以降を搭載したほとんどのスマートフォンで動作します。
<application> ... <service android:name=".FirebaseMessageHandleService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service> ... </application>
public class FirebaseMessageHandleService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); { // Intent intent = new Intent(this, MainActivity.class); /** * Activity , * Activity, , * . * onNewIntent() */ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); /** * * - */ PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); // NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // , , . . NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this); // : , , , . notificationBuilder.setContentIntent(contentIntent); notificationBuilder.setSmallIcon(R.drawable.ic_launcher_background); notificationBuilder.setContentTitle(" !"); notificationBuilder.setContentText(" "); // Notification Notification notification = notificationBuilder.build(); notification.defaults = Notification.DEFAULT_SOUND; notificationManager.notify(1, notification); /** * . * * push- Firebase * */ Intent intent1 = new Intent(getApplicationContext(), MainActivity.class); intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent1); } } }
ポストカードは3月8日の早朝に完成しました。 私は破滅的にそれを成し遂げることができませんでした、目覚まし時計の数分前にありました、そして私はまだ少女のスマートフォンでアプリケーションがどのように動作するかを確認していませんでした(私たちは異なる画面解像度を持っています)。 指紋認証がありました。 USBデバッグをセットアップするとき、再起動が必要でした。 再起動後、グラフィックパスワードを覚えていなかったことが判明しました。 その瞬間、私は完全なバカのように感じました。 フィニッシュラインからのステップ、アプリケーション( facepalm )を確認できませんでした。 幸いなことに、少女を目覚めさせ、ロックを解除しなければなりませんでした。彼女は何も理解できず、マシンにパスワードを入力しました。
開発の最終段階。 プッシュ通知を開始するためにFirebaseに送信するリクエストを準備するだけです。
重要なポイント:
Firebaseでは、シンプルとカスタムの2つの方法で通知を送信できます。
簡単なオプションでは、ヘッダーと通知テキストの2つのフィールドのみを送信します。 このタイプのメッセージはFirebaseコンソールから直接送信できますが、通知は、動作中のアプリケーションプロセスがある場合にのみ受信されます。 アプリケーションは、瞬間Xまではいかなる形でも現れてはならないため、私たちには適していません。
カスタマイズ可能なオプションを使用すると、任意のコンテンツで最大4Kのjson形式でメッセージを送信できます。 このようなメッセージは、以前に起動したアプリケーションのスタックからメッセージがクリアされた場合でも送信されます。 (ただし、アプリケーションとそのサービスが何らかのメモリクリーナーによって強制終了された場合、アプリケーションが再起動されるまで通知は届きません)。 カスタマイズ可能なメソッドのマイナス面は、POST要求でのみFirebaseサーバーに送信できることです。
リクエストを送信するために、curlユーティリティを使用しました。 コードはLinux Mintで作成されているため、端末を起動するだけで十分です。 Postmanなどの他のツールを使用できます。
「認証:キー= <あなたのキー>」
キーは、Firebaseプロジェクトの設定で表示できます(ギアをクリックします)

「コンテンツタイプ:アプリケーション/ json」
{ "to":"Firebase- ", "data":{" ":" "}, "priority":10 // }
curl -X POST --header "Authorization: key=your_key" --Header "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d "{\"to\" : \"firebase_token\" , \"data\":{\"name\" : \"value\"} , \"priority\" : 10}"
現在、リクエストを送信するのは適切なタイミングでのみです!


女の子はそれを気に入って、すごい効果が達成されました:)