JavascriptProva

sabato 11 giugno 2016

Service con tts, chiamato dalla stessa App o da un'App diversa.

Ho trovato modi alternativi di inizializzare un oggetto TextToSpeech.
La sintassi che utilizzo io è:
  tts=new TextToSpeech(context,new TextToSpeech.OnInitListener() {
   
   @Override
   public void onInit(int status) {
    if(status==TextToSpeech.SUCCESS){
     int result=tts.setLanguage(Locale.ITALIAN);
    }
    
   }
  });
ma ora ne trovo di diverse.
Lascio un attimo i Broadcast Receiver per tornare sul TextToSpeech.
Un'altra sintassi che ho trovato usa un diverso costruttore di TextToSpeech:
tts = new TextToSpeech(this, this);
Vado a vedere sulla documentazione se ci sono diversi costruttori.

No.
Riceve come parametri il contesto (this) e il Listener, che è un'interfaccia.
Potrebbe ricevere come parametro anche il contesto se questo implementa un'interfaccia, dunque...

Proviamo:
public class MainActivity extends Activity implements OnInitListener {


 TextToSpeech tts=new TextToSpeech(this,this);
Questa va bene: dal momento che il secondo parametro del costruttore di TextToSpeech deve essere un oggetto che implementa l'interfaccia OnInitListener, anche questa sintassi va bene.
Ovviamente bisogna implementare il metodo onInit.

Torniamo al tts nel contesto del BroadcastReceiver...

Trovo una soluzione che istanzia tts in un Service.
Proviamo...

Ricreiamo un Service... Ecco, il metodo onStartCommand ha tre parametri che ho dimenticato completamente...

 @Override
 public int onStartCommand(Intent intent, int flags, int startId){
  return startId;
  
 }
ecco, una volta implementato, come appare onStartCommand...

Questo esprime le operazioni che il Service compie quando viene iniziato
Nel Service si può partire dal metodo onCreate.
Me lo accetta:
 @Override
 public void onCreate(){
  
 }
Ecco come creo un nuovo oggetto di tipo TextToSpeech nel Service, in onCreate:
public class Servizio extends Service{
 
 TextToSpeech tts;
 @Override
 public void onCreate(){
  tts=new TextToSpeech(this, new TextToSpeech.OnInitListener(){

   @Override
   public void onInit(int status) {
    if(status==TextToSpeech.SUCCESS){
     int result=tts.setLanguage(Locale.ITALIAN);
    }
    
   }
   
  });
 }
Bene.
Ora trovo un metodo onUtteranceCompleted Che significa?
Credo che faccia parte del Service...
Vediamo...

No, fa parte di TextToSpeech.
Dovrebbe essere chiamato alla fine dell'opera di TextToSpeech.
Ecco: ho risolto: faccio implementare alla classe sia l'interfaccia onInitListener sia l'interfaccia onUtteranceCompletedListener.
public class Servizio extends Service implements OnInitListener,OnUtteranceCompletedListener{
 
 TextToSpeech tts;
 @Override
 public void onCreate(){
  tts=new TextToSpeech(this,this);
 }
 
    @Override
    public void onUtteranceCompleted(String uttId) {
        stopSelf();
    }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO Auto-generated method stub
  return null;
 }
 
 @Override
 public int onStartCommand(Intent intent, int flags, int startId){
  return startId;
  
 }
 @Override
 public void onInit(int status) {
  // TODO Auto-generated method stub
  
 }


}
Distruggo il Mandala e riscrivo...
public class Servizio extends Service implements TextToSpeech.OnInitListener, TextToSpeech.OnUtteranceCompletedListener{

 
 @Override
 public void onInit(int status) {
  // TODO Auto-generated method stub
  
 }
 
 @Override
 public void onUtteranceCompleted(String utteranceId) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO Auto-generated method stub
  return null;
 }
 
}
Bene: facendo implementare le interfacce, i metodi vengono da soli.

public class Servizio extends Service implements TextToSpeech.OnInitListener, TextToSpeech.OnUtteranceCompletedListener{

 private TextToSpeech tts;
 
 @Override
 public void onCreate(){
  tts=new TextToSpeech(this,this);
  
 }
 @Override
 public void onInit(int status) {
  if(status==TextToSpeech.SUCCESS){
   int result=tts.setLanguage(Locale.ITALIAN);
   tts.speak("Ciao, mondo crudele", TextToSpeech.QUEUE_FLUSH, null);
  }
  
 }
 
 @Override
 public void onUtteranceCompleted(String utteranceId) {
  stopSelf();
  
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO Auto-generated method stub
  return null;
 }
 
 @Override
 public void onDestroy(){
  if(tts!=null){
   tts.stop();
   tts.shutdown();
  }
  super.onDestroy();
 }
 
}
Eccolo completo, spero.

Ora come si chiama il servizio? L'ho dimenticato.

Ecco, si chiama con un semplice Intent, che può essere esplicito nella chiamata di un Service creato nella stessa App ma deve necessariamente essere implicito se il Service appartiene a una App diversa.

Ecco il codice dell'App che ha creato il Service:
public class MainActivity extends Activity {


 

 Button button;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  button=(Button)findViewById(R.id.button1);
  
  button.setOnClickListener(new View.OnClickListener() {
   
   @Override
   public void onClick(View v) {
    Intent intent=new Intent(getApplicationContext(),Servizio.class);
    startService(intent);
    
   }
  });
  
  

  
 }
}
Con questo Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.esercizio5"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <uses-sdk
        android:minSdkVersion="18"
        android:targetSdkVersion="23" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <service 
            android:name="Servizio" 
            android:exported="true"/>
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <activity
            android:name=".Seconda"
            android:label="@string/title_activity_seconda" >
        </activity>

    </application>

</manifest> 


...mentre il codice dell'App che chiama questo Service dall'esterno è:
public class MainActivity extends Activity {

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

  button=(Button)findViewById(R.id.button1);
  button.setOnClickListener(new View.OnClickListener() {
   
   @Override
   public void onClick(View v) {
    Intent intent=new Intent();
    intent.setComponent(new ComponentName("com.example.esercizio5","com.example.esercizio5.Servizio"));
    startService(intent);
    
   }
  });
  
    
 }


}

Nessun commento:

Posta un commento