2017年5月1日月曜日

cocos2d-x JNI(Java) の に関する覚書

調べたりした結果をずらずらと並べます

cocos2d-x 3.x系 android studioでのJNI headerの作成

cd proj.android-studio

 javah -classpath "app/build/intermediates/classes/debug/:../cocos2d/cocos/platform/android/libcocos2dx/build/intermediates/classes/debug:$ANDROID_SDK_ROOT/platforms/android-23/android.jar" -d "app/jni/NativeBridge" org.cocos2dx.cpp.AppActivity

#android-sdkのバージョンは環境に合わせてください
#一度ビルドする
#app/jni/NativeBridgeにheaderファイルが作成されます


SDKBOX Admobプラグインの位置修正

Admobプラグインは位置が上下左右固定なのでマージンを指定したい場合
次のようなコードで変更できてる模様 
 
ViewGroup rootView = AppActivity.getRootView(context);
if(rootView != null)
{
    for (int i = 0; i < rootView.getChildCount(); i++) {

        ViewGroup view = (ViewGroup)rootView.getChildAt(i);

        for (int j = 0; j < view.getChildCount(); j++ ) {
            if (view.getChildAt(j) instanceof AdView) {
                View child = view.getChildAt(j);
                int height = child.getBottom() - child.getTop();

                ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) child.getLayoutParams();
                lp.bottomMargin = 60 * height / 50;
                child.setLayoutParams(lp);
            }
        }

    }
}


追記予定...

2017年4月29日土曜日

cocos2d-x <- android UIスレッドからの値の取得

cocos2d-xなどでAndroidのUIスレッドから値を直接取得したいという場合
例えば、 クリップボードから取得する場合とか
runOnUiThreadから処理したのちにcallbackを呼ぶ 必要があります

大変面倒なのでwaitを使ってブロッキング処理をしてみましょう
ということでBlockingOnUIRunnableを少し改良してGeneric型を返すようにしてみました


BlockingOnUIRunnable.java

 
/**
 * Blocking Runnable executing on UI thread
 *
 * @author
 *
 */
public class BlockingOnUIRunnable<t>
{
    // Activity
    private Activity activity;

    // Event Listener
    private BlockingOnUIRunnableListener<t> listener;

    // UI runnable
    private Runnable uiRunnable;

    public T retValue;

    /**
     * Class initialization
     * @param activity Activity
     * @param listener Event listener
     */
    public BlockingOnUIRunnable( Activity activity, BlockingOnUIRunnableListener<t> listener )
    {
        this.activity = activity;
        this.listener = listener;

        uiRunnable = new Runnable()
        {
            public void run()
            {
                // Execute custom code
                if ( BlockingOnUIRunnable.this.listener != null ) {
                    retValue = BlockingOnUIRunnable.this.listener.onRunOnUIThread();
                }

                synchronized ( this )
                {
                    this.notify();
                }
            }
        };
    }


    /**
     * Start runnable on UI thread and wait until finished
     */
    public void startOnUiAndWait()
    {
        synchronized ( uiRunnable )
        {
            // Execute code on UI thread
            activity.runOnUiThread( uiRunnable );

            // Wait until runnable finished
            try
            {
                uiRunnable.wait();
            }
            catch ( InterruptedException e )
            {
                e.printStackTrace();
            }
        }
    }

}
 
 
 

BlockingOnUIRunnableListener.java

 
/**
 * Events for blocking runnable executing on UI thread
 *
 * @author
 *
 */
public interface BlockingOnUIRunnableListener<t>
{

    /**
     * Code to execute on UI thread
     */
    public T onRunOnUIThread();
}


使い方 


BlockingOnUIRunnable<String> actionRunnable 
  = new BlockingOnUIRunnable<String>( {{context}}, new BlockingOnUIRunnableListener()
{
    public String onRunOnUIThread()
    {
        ClipboardManager clipboard = (ClipboardManager) {{context}}.getSystemService(Context.CLIPBOARD_SERVICE);
        if (clipboard.hasPrimaryClip()) {
            ClipData data = clipboard.getPrimaryClip();
            ClipDescription description = clipboard.getPrimaryClipDescription();
            if (data != null && description != null && description.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN))
                return String.valueOf(data.getItemAt(0).getText());
        }
        
        return "";
    }
} );

actionRunnable.startOnUiAndWait();
return actionRunnable.retValue;
 
 
 
{{context}}はActivityのcontext, Cocos2dxActivity.getContext()等から取得する値 startOnUiAndWait()で処理を待って retValueから戻り値を取得します
wait中はGLThreadが停止するので重たい処理には使えません

2016年2月12日金曜日

node.js サービス化 on ubuntu

ここから抜粋

/etc/init
以下にyourprogram.confとしてファイル作成

#yourprogram.conf
description "node.js server"
author      "kvz - http://kevin.vanzonneveld.net"

# used to be: start on startup
# until we found some mounts weren't ready yet while booting:
start on started mountall
stop on shutdown

# Automatically Respawn:
respawn
respawn limit 99 5

script
    # Not sure why $HOME is needed, but we found that it is:
    export HOME="/root"

    exec sudo -u www-data /usr/bin/node /where/yourprogram.js >> /var/log/node.log 2>&1
end script

post-start script
   # Optionally put a script here that will notifiy you node has (re)started
   # /root/bin/hoptoad.sh "node.js has started!"
end script
 
 
##/usr/local/bin/node → /usr/bin/nodeに修正
## ユーザwww-dataは作成しておく 
 
init-checkconf /etc/init/yourprogram.conf
を実行してみる
failed to ask Upstart to check conf fileと出るが
/tmpフォルダにinit-checkconf-upstart-outputが出力されているので
何もエラーがなければOkのはず
 
 
下記コマンドで実行 
start yourprogram   
停止
stop yourprogram 

いまさらながら Linq to SQL

必要だったのでLinq to SQL 触ってみましたが
いろいろ細かいところが面倒だったので
対応した内容をメモ


 Binary形式の比較ができない


下記のようなクラスを作成し

 public static class BinaryComparer
    {
        public static int Compare(this Binary b1, Binary b2)
        {
            throw new NotImplementedException();
        }
    }


where内で使う

hoge.Where(row =>BinaryComparer.Compare(binary, row.binary_column) == 0) ;



PropertyInfoを使ったカラム指定



public static Expression<Func<TItem, bool>> PropertyEquals<TItem, TValue>(
             PropertyInfo property, TValue value)
        {
            var param = Expression.Parameter(typeof(TItem));
            var body = Expression.Equal(Expression.Property(param, property),
                Expression.Constant(value));
            return Expression.Lambda<Func<TItem, boo>>(body, param);
        }


次のように利用する

hoge.Where(PropertyEquals<hogetype, byte>(propertyInfo, somebyte));


上記だとnullableに対応していないので
nullable対応版

public static Expression<Func<TItem, bool>> NullablePropertyEquals<TItem, TValue>(
             PropertyInfo property, TValue? value) where TValue : struct
        {
            var param = Expression.Parameter(typeof(TItem));
            var body = Expression.Equal(
                    Expression.Property(param, property),
                    Expression.Constant(value, typeof (TValue?)));
            return Expression.Lambda<Func<TItem, bool>>(body, param);
        }

nullableでしか動かないので注意
両方に対応したメソッドも作れるような気はするけど
取りあえずここまで




2015年10月27日火曜日

Orvibo S20

電源をWifi(LAN)上で操作できるデバイスです
外出することが多くなりそうなので導入
ただ、心配なのが操作するアプリがLAN外から操作する場合に
製造元のサーバーを経由するということ
中国のよくわからないメーカーなので心もとない
ということでハックされたスクリプトで操作することに



情報元はここです
https://stikonas.eu/wordpress/2015/02/24/reverse-engineering-orvibo-s20-socket/


結論から言うと下記PHPファイルで操作できる

<?php
ob_start();
error_reporting(E_ALL | E_STRICT);

$server = 'IPADDRESS';
$port = 10000;
$macAddress = 'AC:CF:23:56:6C:24';
$twenties = '202020202020';
$ma = strtolower(implode('',explode(':',$macAddress)));
$maReverse = strtolower(implode('',array_reverse(explode(':',$macAddress))));
$subscribe = pack('H*','6864001e636c' . $ma . $twenties . $maReverse . $twenties);
$on = pack('H*','686400176463' . $ma . $twenties . '0000000001');
$off = pack('H*','686400176463' . $ma . $twenties . '0000000000');

//Create a UDP socket
if(!($sock = socket_create(AF_INET, SOCK_DGRAM, 0))) {
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    die("Couldn't create socket: [$errorcode] $errormsg <br />");
}

echo "Socket created <br />";

// Bind the source address
if(!socket_bind($sock, "0.0.0.0" , $port)) {
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    die("Error binding socket. Error code was " . $errorcode . " and error message was " . $errormsg);
}

echo "Socket bound. Waiting for incoming data.<br />";

echo "Sending subscribe packet ..";
socket_sendto($sock, $subscribe, strlen($subscribe), 0, $server, $port);
sleep(2);
echo "Sending ON packet ..";
socket_sendto($sock, $on, strlen($on), 0, $server, $port);
sleep(2);
echo "Sending OFF packet ..";
//socket_sendto($sock, $off, strlen($off), 0, $server, $port);



ob_flush();
//Do some communication, this loop can handle multiple clients
while(1) {
    //Receive some data
    $r = socket_recvfrom($sock, $buf, 512, 0, $remote_ip, $remote_port);
    $buf = ascii2hex($buf);
    echo "Data from " . $remote_ip . ": " . $buf . "<br />";
       ob_flush();
}

function ascii2hex($ascii) {
    $hexadecimal = '';
    for ($i = 0; $i < strlen($ascii); $i++) {
        $byte = strtoupper(dechex(ord($ascii{$i})));
        $byte = str_repeat('0', 2 - strlen($byte)).$byte;
        $hexadecimal.=$byte." ";
    }
    return $hexadecimal;
}

socket_close($sock);

?>

TODO Ctrl+Cしないと終了しない

2015年10月26日月曜日

iPhoneでのOpenSSHの安全な設定

いつもiPhoneにOpenSSH入れる時に見ていたサイトから
いつの間にか記事がなくなっていたのでメモしておく


●ssh でユーザーmobileにアクセスする


ssh mobile@ipaddress

デフォルトのパスワードはalpine


●rootのパスワード変更


su
passwd
新しいパスワード


●共通鍵の生成


ssh-keygen -t rsa
保存先は空白
任意のパスフレーズ
 

autorized_keyに保存する
 
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
rm ~/.ssh/id_rsa.pub
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys


 ●秘密キーの設置

作成したid_rsaをPCもしくはMacに持ってくる
WinSCPやFileZilla等利用

 OpenSSHの場合はそのまま、puttyの場合はputty-genで置換する必要がある



●SSHdの設定を変更する

 該当行を次のように変更

sudo vim /etc/ssh/sshd_config #vimはcydiaからインストールしておく

# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key #version1は使わない   
PermitRootLogin no #rootユーザではログインさせない   

#RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys #公開鍵方式を使う   

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no #パスワード認証は行わない



ちなみにviのコマンド(i:インサートモード,esc:ノーマルモード,x:一文字削除,dd:行削除,:wq:保存,:q!:保存せずに閉じる)


● サービスの再起動


su 
launchctl unload /Library/LaunchDaemons/com.openssh.sshd.plist
launchctl load /Library/LaunchDaemons/com.openssh.sshd.plist

2015年2月21日土曜日

Windows 8 スリープからの自動復帰を切る

自宅のメインマシンはWindows 8機で基本的にスリープで運用しています。
スリープまたは休止状態から勝手に復帰するようになって
睡眠を妨げるようになったのでイラついた勢いで設定を見直しました


原因として考えられるのは、
WakeOnLan
マウス等デバイスの (誤)操作
タスクスケジュールの実行

 

1.原因究明


直近の起動理由を知るには次のコマンドを実行します

>powercfg lastwake


マウスでの実行であれば次のような出力
切ってみましたが効果なし

Wake History [0]
  Wake Source Count - 1
  Wake Source [0]
    Type: Device
    Instance Path: ACPI\PNP0303\4&6
    Friendly Name:
    Description: 標準 PS/2 キーボー
    Manufacturer: (標準キーボード)



復帰予定のスケジュールを探す

>powercfg waketimers


次のような出力があります。
原因はmcupdate_scheduledというスケジュールのようです。


Timer set by [SERVICE] \Device\HarddiskVolume1\Windows\System32\svchost.exe (Sys
temEventsBroker) expires at 3:31:08 on 2015/02/18.
  Reason: Windows は、スリープ状態の解除を要求したスケジュールされたタスク 'NT T
ASK\Microsoft\Windows\Media Center\mcupdate_scheduled' を実行します。


2.スリープ解除をきる


WakeOnLanの場合、

 デバイスマネージャから対象のネットワークアダプタのプロパティを開く
電源の管理タブから
” Magic Packetでのみ、コンピュータのスタンバイ状態を解除できるようにする”
 のチェックを外すか選択できない状態にする


マウス、キーボードの場合、

デバイスマネージャから対象のデバイスのプロパティを開く
電源の管理タブの ”このデバイスで、コンピュータのスタンバイ状態を解除できるようにする”
のチェックを外す


スケジュールの場合、

”管理ツール>タスクスケジューラ”から対象のスケジュール(mcupdate_scheduled)を捜し
条件タブの”タスクを実行するためにスリープを解除する”のチェックを外す