Как подключиться к серверу OSC с Android?

Я пытаюсь написать действительно простое приложение для Android, которое подключается к серверу OSC и прослушивает сообщения от него.

Пока что я создал простое приложение на основе библиотеки OSCP5 и пример широковещательного клиента, вот что я пробовал:

package com.hirschandmann.colour.client;

import netP5.NetAddress;
import netP5.NetInfo;
import oscP5.OscArgument;
import oscP5.OscMessage;
import oscP5.OscP5;
import android.app.Activity;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;

import com.hirschandmann.colour.client.util.SystemUiHider;

//based on Fullscreen Activity template
public class FlatColour extends Activity implements OnClickListener {
    private static final String TAG = "FlatColour";
    private static final boolean AUTO_HIDE = true;
    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
    private static final boolean TOGGLE_ON_CLICK = true;
    private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;
    private SystemUiHider mSystemUiHider;
    private View contentView;

    private static final int PORT_IN = 12000;
    private static final int PORT_OUT = 32000;
    private NetAddress thisLocation;
    private OscP5 osc;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_flat_colour);

        contentView = findViewById(R.id.fullscreen_content);

        mSystemUiHider = SystemUiHider.getInstance(this, contentView,HIDER_FLAGS);
        mSystemUiHider.setup();

        contentView.setOnClickListener(this);

        osc = new OscP5(this,PORT_IN);
        String ip = getIpAddr();
        System.out.println(ip);
        thisLocation = new NetAddress(ip,PORT_OUT);
        try{
            connect();
        }catch(Exception e){
            e.printStackTrace();
        }
        //NetInfo.print();
    }
    public void connect(){
        OscMessage m = new OscMessage("/server/connect",new Object[0]);
        OscP5.flush(m,thisLocation);  
    }
    public void disconnect(){
        OscMessage m = new OscMessage("/server/disconnect",new Object[0]);
        OscP5.flush(m,thisLocation);
    }
    public void oscEvent(OscMessage m) {
        String pattern = m.addrPattern();
        Log.d(TAG, pattern);
        if(pattern.equals("/color")){
//          int color = Integer.parseInt(m.get(0).stringValue());
            OscArgument a = m.get(0);
            String s = a.stringValue();
            System.out.println(s);
            final int color = Integer.parseInt(s);
            //cannot update view from non view thread otherwise
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    contentView.setAlpha(0);
                    contentView.setBackgroundColor(color);
                }
            });

//          contentView.setBackgroundColor(color);
            Log.d(TAG, "color: " + a +" view: " + contentView);
        }
        if(pattern.equals("/animate")){
            int duration = m.get(0).intValue();
            int delay    = m.get(1).intValue();
            contentView.animate().alpha(1).setDuration(duration).setStartDelay(delay);
            Log.d(TAG, "duration: " + duration + " delay: " + delay);
        }
    }

    @Override
    public void onClick(View view) {
        if (TOGGLE_ON_CLICK) {
            mSystemUiHider.toggle();
        } else {
            mSystemUiHider.show();
        }
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        delayedHide(100);
    }

    View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (AUTO_HIDE) delayedHide(AUTO_HIDE_DELAY_MILLIS);
            return false;
        }
    };

    Handler mHideHandler = new Handler();
    Runnable mHideRunnable = new Runnable() {
        @Override
        public void run() {
            mSystemUiHider.hide();
        }
    };
    private void delayedHide(int delayMillis) {
        mHideHandler.removeCallbacks(mHideRunnable);
        mHideHandler.postDelayed(mHideRunnable, delayMillis);
    }
}

И вот дорожка стека, которую я получаю:

06-03 11:15:42.330: W/System.err(4766): android.os.NetworkOnMainThreadException
06-03 11:15:42.340: W/System.err(4766):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1126)
06-03 11:15:42.340: W/System.err(4766):     at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:175)
06-03 11:15:42.340: W/System.err(4766):     at libcore.io.IoBridge.sendto(IoBridge.java:484)
06-03 11:15:42.340: W/System.err(4766):     at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:182)
06-03 11:15:42.340: W/System.err(4766):     at java.net.DatagramSocket.send(DatagramSocket.java:304)
06-03 11:15:42.340: W/System.err(4766):     at oscP5.OscP5.flush(Unknown Source)
06-03 11:15:42.340: W/System.err(4766):     at oscP5.OscP5.flush(Unknown Source)
06-03 11:15:42.340: W/System.err(4766):     at com.hirschandmann.colour.client.FlatColour.connect(FlatColour.java:62)
06-03 11:15:42.340: W/System.err(4766):     at com.hirschandmann.colour.client.FlatColour.onCreate(FlatColour.java:54)
06-03 11:15:42.340: W/System.err(4766):     at android.app.Activity.performCreate(Activity.java:5008)
06-03 11:15:42.340: W/System.err(4766):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
06-03 11:15:42.340: W/System.err(4766):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2034)
06-03 11:15:42.350: W/System.err(4766):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2095)
06-03 11:15:42.350: W/System.err(4766):     at android.app.ActivityThread.access$600(ActivityThread.java:137)
06-03 11:15:42.350: W/System.err(4766):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1206)
06-03 11:15:42.350: W/System.err(4766):     at android.os.Handler.dispatchMessage(Handler.java:99)
06-03 11:15:42.350: W/System.err(4766):     at android.os.Looper.loop(Looper.java:213)
06-03 11:15:42.350: W/System.err(4766):     at android.app.ActivityThread.main(ActivityThread.java:4791)
06-03 11:15:42.350: W/System.err(4766):     at java.lang.reflect.Method.invokeNative(Native Method)
06-03 11:15:42.350: W/System.err(4766):     at java.lang.reflect.Method.invoke(Method.java:511)
06-03 11:15:42.350: W/System.err(4766):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
06-03 11:15:42.350: W/System.err(4766):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
06-03 11:15:42.350: W/System.err(4766):     at dalvik.system.NativeStart.main(Native Method)

Я не уверен, что делать с ошибкой.

Как я могу отправить сообщение OSC с телефона Android на все, что слушает OSC на определенном порту? Каков рекомендуемый метод? Я новичок в программировании для Android и пытаюсь использовать то, что я использовал в Processing раньше, что может быть не лучшим вариантом для Android.


person George Profenza    schedule 03.06.2013    source источник


Ответы (1)


Я еще немного почитал StrictMode и понял, что мой простое приложение отправляло/получало сетевые сообщения в том же потоке, что не рекомендуется. Сеть должна обрабатываться в отдельном потоке, поэтому простым решением является использование AsyncTask:

public void connect(){
        new AsyncTask<Void, Void, String>(){

            @Override
            protected String doInBackground(Void... params) {
                System.out.println("sending connect message: " + PORT_OUT);
                OscMessage m = new OscMessage("/server/connect",new Object[0]);
                OscP5.flush(m,new NetAddress("255.255.255.255",PORT_OUT)); 
                return "doing in background";
            }

            @Override
            protected void onPostExecute(String result) {
                System.out.println("done in background");
            }

        }.execute();
    }

Это можно было бы написать лучше, задача создания подклассов, но она иллюстрирует суть.

person George Profenza    schedule 05.06.2013