2016-05-12 21 views
6

Sto tentando di creare un pulsante che mi consenta di registrare l'audio tramite un servizio, voglio che il pulsante abbia il testo: "Start Recording". Nell'evento OnClick, voglio che il testo del pulsante cambi in: "Stop Recording".(visualizzazione (pulsante) all'interno di un servizio non funziona

Ho avuto questo codice funzionante quando era in una classe ma ora non funziona in un servizio, tuttavia, poiché desidero che il record audio funzioni come un servizio, non riesco a ottenere il testo del pulsante da modificare. Sono abbastanza nuovo nella programmazione, quindi qualsiasi aiuto sarà molto apprezzato!

Il mio codice è il seguente:

Classe:

public class Test extends AppCompatActivity {  

    public void Record(View view) { 
     Intent intent = new Intent(this, RecordService.class); 
     startService(intent); 
    }  

    public void Play(View view) { 
     Intent intent = new Intent(this, RecordService.class); 
     stopService(intent);  
    } 
} 

Servizio:

import android.app.Service; 
import android.content.Intent; 
import android.media.MediaRecorder; 
import android.os.Environment; 
import android.os.IBinder; 
import android.widget.Button; 
import android.view.View; 

import java.io.IOException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 

public class RecordService extends Service { 

    MediaRecorder mRecorder; 
    public static String audioFilePath; 
    public boolean isRecording = false; 

    public RecordService() { 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     // TODO: Return the communication channel to the service. 
     throw new UnsupportedOperationException("Not yet implemented"); 
    } 

    public void onCreate() { 

     if(mRecorder == null){ 

      SimpleDateFormat s = new SimpleDateFormat("ddMMyyyy_hhmmss"); 
      String format = s.format(new Date()); 

      audioFilePath = Environment.getExternalStorageDirectory(). 
        getAbsolutePath() + "/" + format + ".3gpp"; 

      mRecorder = new MediaRecorder(); 
      mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
      mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
      mRecorder.setOutputFile(audioFilePath); 
      mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
     } 

     if (isRecording) { 
      try{ 
       stopRecording(); 
       isRecording = false; 
       ((Button)view).setText("Start Recording"); 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } else { 
      try{ 
       startRecording(); 
       isRecording = true; 
       ((Button)view).setText("Stop Recording"); 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 

    public void startRecording() throws IllegalStateException, IOException{ 
     mRecorder.prepare(); 
     mRecorder.start(); 
    } 

    public void stopRecording() throws IllegalStateException, IOException{ 
     mRecorder.stop(); 
     mRecorder.release(); 
    } 


    public void onStartCommand() 
    { 
     SimpleDateFormat s = new SimpleDateFormat("ddMMyyyy_hhmmss"); 
     String format = s.format(new Date()); 

     audioFilePath = Environment.getExternalStorageDirectory(). 
       getAbsolutePath() + "/" + format + ".3gpp"; 

     mRecorder = new MediaRecorder(); 
     mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
     mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
     mRecorder.setOutputFile(audioFilePath); 
     mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
     try { 
      mRecorder.prepare(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     mRecorder.start(); 

    } 

    public void onDestroy() 
    { 
     super.onDestroy(); 
     mRecorder.stop(); 
     mRecorder.release(); 

    } 


} 

attività:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" 
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    tools:context="kyr.com.knowyourrights.Test"> 

    <TextView android:text="@string/hello_world" android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 

    <Button 
     android:text="Record" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/RecordButton" 
     android:layout_alignParentTop="true" 
     android:onClick="Record"> 
    </Button> 

</RelativeLayout> 

risposta

1

Volete pulsante per chiamare in servizio, tenta di utilizzare BroadcastReceiver

+0

Come si collega questo codice all'interno del mio codice esistente? dove dovrei scrivere il metodo runOnUiThread, dato che non posso inserirlo nel mio booleano e inoltre non posso creare un nuovo metodo con esso? @hoanngothanh – Viverson

+0

@Viverson come commento Xema, prova ad usare la libreria otto – hoanngothanh

1

Questo, infatti, non può lavorare qui dal momento che il ((tasto VIEW)) non è un'istanza in onCreate().

Quello che suggerisco è di chiamare, dal servizio, una funzione all'interno dell'attività che esegue ciò che si vuole fare (qui, cambiare il testo). È possibile ottenere questo utilizzando un BroadcastReceiver.

Per fare questo, è possibile effettuare le seguenti operazioni:

All'interno della vostra attività:

@Override 
public void onResume() { 
    super.onResume(); 

    // Register mMessageReceiver to receive messages. 
    LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, 
     new IntentFilter("change-text")); 
} 

// handler for received Intents for the "change-text" event 
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
    // Extract data included in the Intent 
    String message = intent.getStringExtra("message"); 
    button.setText(message); //Assuming you have instantiate properly your button inside your onCreate() 
    } 
}; 

@Override 
protected void onPause() { 
    // Unregister since the activity is not visible 
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); 
    super.onPause(); 
} 

All'interno del vostro servizio:

// Send an Intent with an action named "change-text". 
private void sendMessage(boolean startRecording) { 
    Intent intent = new Intent("change-text"); 
    // add data 
    if (startRecording) intent.putExtra("message", "Start Recording"); 
    else intent.putExtra("message","Stop Recording"); 
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent); 
} 

Per cambiare il pulsante di testo dal vostro servizio, è basterà chiamare la funzione sendMessage con true o false come parametro a seconda di cosa vuoi fare!

Si può vedere la sorgente del codice, che mi sono adattato alla vostra situazione, qui: http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html#ownreceiver_localbroadcastmanager

0

Qualcosa di simile a questo dovrebbe funzionare

if (isRecording) { 
      try { 
       stopRecording(); 
       isRecording = false; 
       yourcontext.runOnUiThread(new Runnable() { 
        public void run() { 
         ((Button) view).setText("Start Recording"); 
        } 
       }); 


      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } else { 
      try { 
       startRecording(); 
       isRecording = true; 
       yourcontext.runOnUiThread(new Runnable() { 
        public void run() { 
         ((Button) view).setText("Stop Recording"); 
        } 
       }); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
+0

Im ottenendo gli stessi problemi con questo come prima, immagino perché un servizio non dovrebbe interagire con l'interfaccia utente quindi non posso cambiare la vista Button – Viverson

0

Può essere meglio cambiare il testo nel attività, potrebbe adattarsi di più allo spirito del servizio. Dovresti dare un'occhiata a questo argomento: Example: Communication between Activity and Service using Messaging

Secondo me, creare un gestore all'interno di un Messenger è un modo molto utile ed efficace per creare un ponte di comunicazione tra il tuo servizio e l'attività. In questo modo probabilmente creerai tag di stato che rappresentano lo stato corrente nel tuo servizio, e.g nel tuo caso:

Message message = new Message(); 
message.setData(b); // bundle containing extra data if you need it 
message.what = MSG_RECORD_STOP; 
mActivity.send(message); 

Poi nella vostra attività, una volta che hai la richiamata dal tuo Messenger, si può semplicemente fare qualcosa di simile:

(TextView) mRecordButton =(TextView)rootView.findViewById(R.id.RecordButton); 
mRecordButton.setText("Stop Recording"); 
0

Perché si vuole cambiare il pulsante testo nel servizio? Forse è proprio quello di cui hai effettivamente bisogno. public class test estende AppCompatActivity {

public void Record(View view) { 
    Intent intent = new Intent(this, RecordService.class); 
    startService(intent); 
    yourButton.setText("Stop Recording"); 
} 



public void Play(View view) { 
    Intent intent = new Intent(this, RecordService.class); 
    stopService(intent); 
    yourButton.setText("Start Recording"); 

} 

}

+0

Does this significa che ho bisogno di due pulsanti? come immagino questi sono essenzialmente due diversi eventi di clic, come potrei dare un pulsante nel mio file xml due eventi di clic? @ Guliash – Viverson

0

Dichiarare il pulsante come statica nella vostra attività ad esempio

public static Button recordButton; 
public void onCreate(Bundle savedInstanceState) { 
    .... 
    recordButton =(Button) findViewById(R.id.RecordButton); 
    .... 
} 

poi fare qualcosa del genere nel vostro servizio in cui si desidera

WeakReference<Button> recordButton = new WeakReference<Button>(YourActivity.recordButton); 
recordButton.setText("Start Recording"); 
+0

Questa non è una buona soluzione, ci sono modi migliori per gestire questo tipo di condizione piuttosto che rendere statica una vista. – JoxTraex

Problemi correlati