martedì 10 gennaio 2017

Message Api in Android Wear

Le Message API permettono di scambiare messaggi tra dispositivi Android, nel caso specifico tra il telefono e l'orologio mediante Android Wear
Nell'esempio in esame vengono sincronizzati due NumberPicker



Il progetto completo e' disponibile su GitHub ed e' basato sull'esempio a questo link

Per NumberPicker sul telefono, piu' che altro per la gestione del font, e' stato usato questa modifica



Lato Telefono
build.gradle
--------------------------------------
apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.luca_innocenti.apticmetro"
        minSdkVersion 21
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    wearApp project(':wear')
    compile 'com.google.android.gms:play-services:10.0.1'
    compile 'com.android.support:appcompat-v7:25.1.0'
    compile 'com.shawnlin:number-picker:2.3.0'

    testCompile 'junit:junit:4.12'
}
--------------------------------------

MainActivity
--------------------------------------
package com.luca_innocenti.apticmetro;

import android.icu.lang.UCharacter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
//import android.widget.NumberPicker;
import com.shawnlin.numberpicker.NumberPicker;

import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;



// Applicazione Mobile
public class MainActivity extends AppCompatActivity implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener
{

    private static final String TAG = "MainActivity";
    private GoogleApiClient googleApiClient;

    private ImageButton play;
    private NumberPicker bpm;
    private int counter;

    public MainActivity() {
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        googleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        //play = (ImageButton) findViewById(R.id.imageButton);
        bpm = (NumberPicker) findViewById(R.id.number_picker);


        bpm.setMinValue(40);
        bpm.setMaxValue(150);
        bpm.setValue(80);
        bpm.setWrapSelectorWheel(false);


        bpm.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal){
                //Display the newly selected number from picker
                Log.d(TAG,Integer.toString(newVal));
                String sendMessage = Integer.toString(newVal);
                new SendToDataLayerThread("/path", sendMessage).start();
            }
        });



        /*play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Toast.makeText(MainActivity.this, "Inviato", Toast.LENGTH_SHORT).show();
                String sendMessage = "Start";
                counter++;

                new SendToDataLayerThread("/path", sendMessage).start();

                Log.d(TAG, "SendToDataLayerThread()");


            }
        });*/
    }


    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart()");
        googleApiClient.connect();
    }

    // data layer connection
    @Override
    public void onConnected(Bundle bundle) {
        Log.d(TAG, "onConnected()");
    }

    // Activity stop
    @Override
    protected void onStop() {
        if (null != googleApiClient && googleApiClient.isConnected()) {
            googleApiClient.disconnect();
        }
        super.onStop();

        Log.d(TAG, "onStop()");

    }

    @Override
    public void onConnectionSuspended(int cause) { }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) { }

    private class SendToDataLayerThread extends Thread{
        String path;
        String handheldMessage;

        public SendToDataLayerThread(String pth, String message) {
            //path = "/messaggio";
            path = pth;
            handheldMessage = message;
        }
        public void run() {
            Log.d(TAG, "SendToDataLayerThread()");

            NodeApi.GetConnectedNodesResult nodeResult = Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
            for (Node node : nodeResult.getNodes()) {
                MessageApi.SendMessageResult result =
                        Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), path, handheldMessage.getBytes()).await();

                if (result.getStatus().isSuccess()) {
                    Log.d(TAG, "To: " + node.getDisplayName());
                    Log.d(TAG, "Message = " + handheldMessage );
                }
                else {
                    Log.d(TAG, "Send error");
                }
            }
        }
    }
}
--------------------------------------


AndroidManifest.xml
--------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.luca_innocenti.apticmetro">

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.VIBRATE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
--------------------------------------



Lato Orologio 
build.gradle
--------------------------------------
apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.luca_innocenti.apticmetro"
        minSdkVersion 21
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.google.android.support:wearable:2.0.0-beta1'
    compile 'com.google.android.gms:play-services-wearable:10.0.1'
    provided 'com.google.android.wearable:wearable:2.0.0-beta1'
}
--------------------------------------

Manifest.xml
--------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.luca_innocenti.apticmetro">

    <uses-feature android:name="android.hardware.type.watch" />

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <uses-library android:name="com.google.android.wearable" android:required="false" />



    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@android:style/Theme.DeviceDefault">
        <uses-library
            android:name="com.google.android.wearable"
            android:required="false" />


        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.DeviceDefault.Light">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".WearService">
            <intent-filter>
                <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
                <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
                <data android:scheme="wear" android:host="*" android:pathPrefix="/path" />
            </intent-filter>
        </service>
    </application>


</manifest>
--------------------------------------

MainActivity
--------------------------------------
package com.luca_innocenti.apticmetro;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Vibrator;
import android.support.v4.content.LocalBroadcastManager;
import android.support.wearable.activity.WearableActivity;
import android.support.wearable.view.BoxInsetLayout;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.NumberPicker;
import android.os.Handler;

import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.MessageEvent;



// Lato orologio
public class MainActivity extends WearableActivity {

    private BoxInsetLayout mContainerView;
    private NumberPicker bpm;
    private ImageButton play;
    private int stato;
    long startTime = 0;
    long valore_bpm;

    private String receivedMessage = null;
    private String message = "";
    private static final String TAG = "WearMainActivity";




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setAmbientEnabled();

        Log.v(TAG, "onCreate()");
        IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
        MessageReceiver messageReceiver = new MessageReceiver();
        LocalBroadcastManager.getInstance(getApplication()).registerReceiver(messageReceiver, messageFilter);


        final Handler timerHandler = new Handler();
        final Runnable timerRunnable = new Runnable() {

            @Override
            public void run() {
                Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                vibrator.vibrate((100));
                timerHandler.postDelayed(this, valore_bpm);
            }
        };


        stato = 0;

        mContainerView = (BoxInsetLayout) findViewById(R.id.container);
        bpm = (NumberPicker) findViewById(R.id.numberPicker);
        play =(ImageButton) findViewById(R.id.imageButton);

        bpm.setMinValue(40);
        bpm.setMaxValue(150);
        bpm.setValue(80);
        bpm.setWrapSelectorWheel(false);

        play.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                Log.d("Aptic","BPM "+bpm.getValue());
                valore_bpm = Math.round((60.0/bpm.getValue())*1000.0);
                Log.d("Valore bmp millisecondi","BMP3 "+valore_bpm);
                if (stato == 0) {
                    play.setImageResource(R.drawable.stop_icon);
                    stato = 1;
                    startTime = System.currentTimeMillis();
                    //Toast.makeText(MainActivity.this, Long.toString(valore_bpm), Toast.LENGTH_SHORT).show();
                    timerHandler.postDelayed(timerRunnable, 0);
                }
                else
                {
                    play.setImageResource(R.drawable.play_icon);
                    stato = 0;
                    timerHandler.removeCallbacks(timerRunnable);

                }
            }
        });

    }

    public class MessageReceiver extends BroadcastReceiver {
        private static final String TAG = "MessageReceiver";

        @Override
        public void onReceive(Context context, Intent intent) {

            receivedMessage = intent.getStringExtra("message");
            Log.d("MessageReceiver", "onReceive() receivedMessage = "+receivedMessage);

            if (receivedMessage != null) {
                // Display message in UI
                message = receivedMessage;
                Log.d("MessageReceiver", "receivedMessage =" + receivedMessage);
                bpm.setValue(Integer.parseInt(receivedMessage));
            } else {
                receivedMessage = "No Message";
                Log.d("MessageReceiver", "receivedMessage = No Message");
            }


        }
    }




    @Override
    public void onEnterAmbient(Bundle ambientDetails) {
        super.onEnterAmbient(ambientDetails);
        updateDisplay();
    }

    @Override
    public void onUpdateAmbient() {
        super.onUpdateAmbient();
        updateDisplay();
    }

    @Override
    public void onExitAmbient() {
        updateDisplay();
        super.onExitAmbient();
    }

    private void updateDisplay() {
        if (isAmbient()) {
            mContainerView.setBackgroundColor(getResources().getColor(android.R.color.black));
            play.setVisibility(View.INVISIBLE);
        } else {
            mContainerView.setBackground(null);
            play.setVisibility(View.VISIBLE);
        }
    }




}
--------------------------------------

WearService
--------------------------------------
package com.luca_innocenti.apticmetro;

import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.WearableListenerService;

/**
 * Created by lucainnocenti on 05/01/17.
 */

public class WearService extends WearableListenerService {
    private static final String TAG = "WearService";

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        super.onDataChanged(dataEvents);
        Log.v(TAG, "onDataChanged" );
    }

    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        super.onMessageReceived(messageEvent);
        Log.v(TAG, "onMessageReceived" );

        if (messageEvent.getPath().equals("/path")) {

            final String message = new String(messageEvent.getData());

            Log.d(TAG, "Message path received on watch is: " + messageEvent.getPath());
            Log.d(TAG, "Message received on watch is: " + message);

            // Broadcast message to wearable activity for display
            Intent messageIntent = new Intent();
            messageIntent.setAction(Intent.ACTION_SEND);
            messageIntent.putExtra("message", message);
            LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);

        }
        else {
            super.onMessageReceived(messageEvent);
        }
    }

}





Nessun commento:

Posta un commento

Physics informed neural network Fukuzono

Visto che puro ML non funziona per le serie tempo di cui mi sto occupando ed le regressioni basate su formule analitiche mostrano dei limiti...