忍者ブログ
  • 2024.04
  • 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
  • 2024.06
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

【2024/05/19 05:08 】 |
無題
androidでtwitter4jを使っていて、以下のエラーが出て投稿できないときがあった
認証は正常にできるが、投稿する時に例外が発生して以下のようになる


07-30 15:44:45.737 21142-21406/kazuma.saitou.mokou W/System.err: 401:Authentication credentials (https://dev.twitter.com/pages/auth) were missing or incorrect. Ensure that you have set valid consumer key/secret, access token/secret, and the system clock is in sync.
07-30 15:44:45.737 21142-21406/kazuma.saitou.mokou W/System.err: {"request":"\/1.1\/statuses\/update_with_media.json","error":"Read-only application cannot POST."}
07-30 15:44:45.737 21142-21406/kazuma.saitou.mokou W/System.err: Relevant discussions can be found on the Internet at:
07-30 15:44:45.737 21142-21406/kazuma.saitou.mokou W/System.err: http://www.google.co.jp/search?q=2fc5b7cb or
07-30 15:44:45.737 21142-21406/kazuma.saitou.mokou W/System.err: http://www.google.co.jp/search?q=0f1343da
07-30 15:44:45.737 21142-21406/kazuma.saitou.mokou W/System.err: TwitterException{exceptionCode=[2fc5b7cb-0f1343da], statusCode=401, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=4.0.4}
07-30 15:44:45.737 21142-21406/kazuma.saitou.mokou W/System.err: [Ljava.lang.StackTraceElement;@1359e913



コードを追いかけてみると、トークンやトークンシークレットは正しい値でリクエストを投げている
アプリ管理ページhttps://apps.twitter.com/app/ で TestOAuthを試してみると、なんか違うトークンとシークレットでテストしている

そこで、管理ページからトークンとシークレットを再生成(Regenerate)。
アプリも一度削除して再度実行

するとできた


どうやら、アプリ管理ページから作成するとき、間違えて違うアカウントで登録したので
別のアカウントでログインして再度登録したのだが
このとき、古い方のトークン情報が残っているかなんかしたのだろう
ツイッター側のサイトがどういう作りをしているのか知らないが…
PR
【2016/07/30 15:56 】 | cocos2d-x | 有り難いご意見(0)
android + Firebase のプッシュ通知概論
作成はだいぶ楽である

公式ドキュメント

メッセージの他、自由にデータ(payload)を含めて送信できる
SDKを入れ、permissionをmanifestに書き、google-services.json 入れたらもうそれだけで届くようになるはず。


・起動中にpush通知を受け取った場合
FirebaseMessagingService クラスを継承し
onMessageReceived(RemoteMessage remoteMessage) メソッドをオーバーライドする。この関数が呼び出される

メッセージ本文は
remoteMessage.getNotification().getBody()

データpayloadは
Map<String, String> data = remoteMessage.getData();
となる。data.get("key") みたいな感じで取得。



・バックグラウンドでpush通知を受け取った場合
受け取った瞬間にアプリ内のどこかのコードが走るわけではない(たぶん)
push通知から起動した場合、iOSのように特別なメソッドが呼び出されることはないが、
MainActivity::onStart()内で、getIntent()をすることにより、どう起動されたかがある程度判別可能。

Intent intent = getIntent();
Bundle dataPayload = intent.getExtras();
if (dataPayload != null) {
String value = dataPayload.getString("key");
}


という感じで取得できる。


【2016/07/28 18:21 】 | Android | 有り難いご意見(0)
androidのローカル通知概論
iOSでローカル通知と呼んでいるものと同等のことをAndroidで行おうとする場合

・AlarmManager
指定時刻に処理を発動させる機能を持つクラス
自身のアプリがバックグラウンドにいても問題ない

 AlarmManager を作成する。
指定すべき事柄は大きく2つ
1. 時刻
 発動させたい時刻。long型で、1970/1/1 からのミリ秒
2. 内容
 発動させたい内容。
 つまり、指定のメッセージで通知を実行するということ
 Intent型。起動すべきクラスの指定と(後述)、extraに随時データを格納する(メッセージ本文など)


AlarmManager が発動したのを受け取るためには
BroadcastReceiver を継承し onReceive() を実装する(仮にAlarmReceiverクラスとする)
かつ、AndroidManifest.xmlにも記述を行う

・AlarmReceiver::onReceive() で行う内容
Notification.notifyを行う
つまり、通知を送信

指定すべき事柄は
・表示内容
 通知のタイトル、テキスト、アイコンなど
 テキストなど、毎回変わるような事柄は AlarmManager から伝達してもらうのが良い
 onReceiveの引数にintentがあるので、intent.getExtra()などする
・タップ時の挙動
 通知をタップした時に実行させる内容
 つまり、自身のアプリの起動
 Intent型
  自身のMainActivity クラスを引数に指定しておけば良い

【2016/07/28 18:14 】 | Android | 有り難いご意見(0)
cocos2d-xのプロジェクト作成コマンドの流れ
前回の記事と基本は同じ


COCOS_CONSOLE_ROOT
以下の
plugins/new_project/new_project.py
CCPluginNewクラス

に書いてある

テンプレートとなるプロジェクトは
$ COCOS_TEMPLATES_ROOT/cpp-template-default
である。他にもjs-templateやlua-templateなどがある

ここのディレクトリをコピーして作っている
(ただし、cocos-project-template.jsonを除く)


プロジェクトの
PROJECT_DIR/cocos
は、SDKから持ってくる。
大元は、cocos2d-x-v.v/ の直下。

ただし、全部をコピーするわけではない。(tests/ とか setup.py とかはいらない)
どのファイルをコピーするかは、
cocos2d-x-v.v/templates/cocos2dx_files.json
に書いてある。
"common", "cpp", "js", "lua" とそれぞれ書いてある。cppの場合、"common"と"cpp"のファイル群がコピーされる

その他のディレクトリは
このcpp-template-default
からコピーしてきている


【2016/07/25 20:38 】 | cocos2d-x | 有り難いご意見(0)
cocos2d-xのandroidビルドの流れ
PROJ_DIR/proj.android-studio
の中で、
$ cocos compile -p android --android-studio
を実行する。

この時、どう処理が流れるのかを調べた


$ which cocos
の場所。
COCOS_CONSOLE_ROOT ディレクトリ配下にある。

cocos はシェルスクリプトで、
同じディレクトリにある cocos.py を実行している

cocos.py はpythonスクリプトで
引数に応じたプラグインを実行する

プラグインの設定ファイルは、これも同じディレクトリにある
cocos2d.ini に書いてある。
コンパイルするためのプラグインは以下の記述。

[plugins]
:
project_compile.CCPluginCompile
:


ファイル名.クラス名となっている。

プラグインは、
COCOS_CONSOLE_ROOT/../plugins
にある

コンパイル系のプラグインは
project_compile ディレクトリ下にあり
project_compile.py ファイルのCCPluginCompileクラスになる。

【2016/07/25 20:22 】 | cocos2d-x | 有り難いご意見(0)
cocos2d-xのライブラリを修正する時は
結論から言うと、ゲームプロジェクトのルートディレクトリ配下にあるファイルを書き換えれば、あとは通常の手順で良い


PROJ_DIR/cocos2d/cocos/ 以下のファイルを適宜書き換える


iOSの場合
プロジェクトでビルドする。
ライブラリプロジェクトの方からビルドが走る。


Androidの場合
$ cocos compile -p android --android-studio
で良い。
更新されたファイルがあれば、そのライブラリを自動で生成する。


【2016/07/25 18:49 】 | cocos2d-x | 有り難いご意見(0)
JNI
Android5.0から、VMが変わった(Darvik -> ART)
その為、過去のコードだと実行時例外がポンポン発生するように

以下のページをよく見て
公式


JNIはベンダーに依存しない。
動的にshared libraryをロードする。
時に扱いづらいが、概ね効率的だ。


JNIには、2つの重要なデータ構造がある
JavaVM
JNIEnv

どちらも、関数テーブルやメンバー関数へのポインタを保持するクラス。

JavaVMクラスは、"invocation interface" functions を提供し、それを使ってJavaVMクラスを生成、破棄できる
理屈的には、JavaVMクラスはプロセスごとに1つ持たせることができるが、Androidは1つしか許可していない

JNIEnvクラスは、JNIのほとんどのメソッドを提供している
ネイティブ関数呼び出しは、必ず第1引数がJNIEnvになる

JNIEnvはスレッド固有に保持する為、スレッド間共有は不可
どうしても必要な場合は、JavaVMの方を共有し、JavaVM.GetEnv()で取得すること

CとC++では、JavaVM,JNIEnvの定義が異なる。
jni.hの中身を見るとわかる。
C/C++が混在する場合、ヘッダファイルからjni.hをインクルードするときは要注意



スレッドについて

スレッドとは、Linuxスレッドである。
通常はコード上から作成する(java.lang.Thread.start)。
それ以外の手で作られたスレッドの場合、JNIに明示的にアタッチする必要がある(AttachCurrentThread または AttachCurrentThreadAsDaemon関数。なおすでにアタッチ済みのスレッドに対してAttachCurrentThreadを実行しても、何も起こらない)。
そうしないと、そのスレッドにはJNIEnvが生成されず、JNI呼び出しができない。


ネイティブコードからJavaオブジェクトのフィールドにアクセスする場合
FindClass
GetFieldID
GetIntField
の順に使用する

メソッドを呼び出す場合
FindClass
GetMethodID
の順に使用する

IDとは通常ポインタのことである。
文字列比較によって検索している。最初は検索するので遅いが、2度目以降は早い
はじめに一度検索しておき、結果をキャッシュしておくことは有効だ

クラス参照は、クラスがアンロードされるまでは保証される。クラスがアンロードされることは滅多にないが、Androidでは起きうる。ClassLoaderに関連づいているクラスが全てガベージコレクトされた時にアンロードされる。
jclass オブジェクトは、クラス参照である


フィールドやメソッドのIDをキャッシュし、クラスがアンロード&リロードされた時に再キャッシュする正しいコードは以下

private static native void nativeInit();

static {
nativeInit();
}





LocalReference と GlobalReference
ネイティブのメソッドに引数として渡ってくる変数は、ローカル参照
そのメソッドが終了すると向こうになる。普通のローカル変数と同じ。(参照元のJavaオブジェクトが生存していても、参照は無効になる)
jobject の子クラスである jclass, jstring, jarray などは全てこれ。

グローバル参照は、明示的に削除しない限りずっと参照を保持し続ける

使用例

jclass localClass = env->FindClass("MyClass");
jclass globalClass = reinterpret_cast(env->NewGlobalRef(localClass));


まずローカル参照を取得し、それをグローバル参照に変換する。
ローカル参照かグローバル参照かで型が変わるわけではない。

全てのJNIメソッドは、ローカル参照もグローバル参照も引数として受け付ける(型が同じだから当然だろう)。

複数の参照が同じオブジェクトを指しているかどうかを判定するには、IsSameObject メソッドを使用すること。==で判定してはいけない。

jfieldIDとjmethodIDは、オブジェクトへの参照ではないため、NewGlobalRefしてはいけない
GetStringUTFChars や GetByteArrayElementsも同様である

ローカル参照は、明示的にdeleteする必要がある。
ローカル参照が自動的にdeleteされるのは、スレッドが削除された時である。



UTFについて

JavaはUTF16を使っている。
JNIはM-UTF8も対応している

M-UTF8についてはこちら参照。簡単に言うとJava独自のUTF8。
M-UTF8は、0x0000を0xc0, 0x80という2文字に変換する。
これの利点は、通常のC文字列同様、NULL文字(0x00)を文字列の終端として扱うことができる。(0x0000のままだと、この文字をC文字列終端と認識してしまうから)
欠点は、UTF8からの変換の手間が必要な事。

可能なら、UTF16を使うのが早い。

GetStringCharsは、jstringをUnicode配列に変換する
GetStringUTFChars は、jstringをMUTF8に変換する

NewStringUTFに渡す文字列は、MUTF8でないといけない。
ここが要注意。ASCII文字列しかないとわかっていれば良いが、そうでなければ変換をする事
でないと、内部でUTF16変換した時、望んでいない結果になる



例外について

例外処理を怠ると、実行時エラーで落とされる

if (methodInfo.env->ExceptionCheck()) {
methodInfo.env->ExceptionDescribe();
methodInfo.env->ExceptionClear();
}


jclass _clazz = (jclass) env->CallObjectMethod(cocos2d::JniHelper::classloader,
cocos2d::JniHelper::loadclassMethod_methodID,
_jstrClassName);

if (nullptr == _clazz) {
LOGE("Classloader failed to find class of %s", className);
env->ExceptionClear();
}


など。

【2016/07/25 15:13 】 | Android | 有り難いご意見(0)
AndroidStudioでcocos2d-xのプロジェクトを動かした話 その2
前回は、初めて動かしたのでAndroidStudio周りの設定などを色々やった

今回、それが住んでいるものとして、
より簡潔に起動した時の手順

まず、AndroidStudioを開き、
File -> New -> Import Project から
cocosプロジェクトのproj.android-studio/ディレクトリを指定して開く

build.gradle
apps/build.gradle
apps/AndroidManifest.xml
などを修正


Firebaseに対応するので(参考
Firebaseからgoogle-service.jsonをダウンロード、
apps/ディレクトリに配置(置き換え)


この公式ページを参考に、Firebase周りの設定を行う

サンプルコードはここ

この辺りを見て色々コピー。

build.gradleをSyncすると、
failed to resolve firebase-xxx:v.v.v 


とか出ることがあるが
SDK ManagerでSDKやGoogle Play Services, Google Repositoryなどをアップデートすれば良い。

【2016/07/23 15:01 】 | cocos2d-x | 有り難いご意見(0)
uGUIのZソート方法
Transformクラスのメソッド
SetSiblingIndex(int)
GetSiblingIndex(int)
を使う。
数値が大きいほど手前に表示される
【2016/07/17 21:00 】 | UNITY | 有り難いご意見(0)
Awakeの呼ばれるタイミング
Awakeは、そのオブジェクトが生成された時に呼び出される

コード中からInstantiateされた時などは、その場で呼び出される

シーン上に初めから配置されていた場合は、起動直後に呼び出される

…とは限らない!
【activeでない】場合は、シーン上にあっても呼び出されない。
初めてactiveになった時に呼び出される。


だから、Awakeの中に書いたことは必ず起動時に呼び出されると思っていてはいけない
【2016/07/17 18:02 】 | UNITY | 有り難いご意見(0)
<<前ページ | ホーム | 次ページ>>