2016-05-12 38 views
6

我想創建一個按鈕,允許我通過服務錄製音頻,我希望按鈕有文字:"Start Recording"。在OnClick事件中,我希望按鈕文本更改爲:"Stop Recording"((按鈕)視圖)裏面的服務不工作

我有這段代碼工作,當它在一個類,但現在它不是在一個服務工作,但是,因爲我想音頻記錄作爲服務工作,我似乎無法得到按鈕的文本更改。我很新的編碼,所以任何幫助將不勝感激!

我的代碼如下:

類別:

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);  
    } 
} 

服務:

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(); 

    } 


} 

活動:

<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> 

回答

1

您要撥打的服務按鈕,嘗試使用廣播接收器

+0

如何在我現有的代碼中鏈接它?我在哪裏寫runOnUiThread方法,因爲我不能把它放在我的布爾值中,也不能用它創建一個新的方法? @hoanngothanh – Viverson

+0

@Viverson像Xema評論,嘗試使用otto庫 – hoanngothanh

1

這確實不能在這裏因爲你((按鈕)視圖)的工作在你的onCreate沒有實例()。

我的建議是從服務中調用一個執行你想要做的事情的功能(在這裏,改變文本)。您可以使用BroadcastReceiver實現此目的。

要做到這一點,你可以做到以下幾點:

內,您的活動:

@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(); 
} 

您的服務中:

// 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); 
} 

從服務更改文本按鈕,只需要調用sendMessage函數,根據你想要做什麼,使用true或false作爲參數!

你可以看到代碼,這是我適應您的情況,這裏的源: http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html#ownreceiver_localbroadcastmanager

0

像這樣的工作

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

即時通訊與我以前一樣,因爲服務不應該與用戶界面進行交互,因此我無法更改按鈕視圖 – Viverson

0

這可能是更好的更改文本活動,可能更適合服務的精神。你應該看看這個話題:Example: Communication between Activity and Service using Messaging

在我看來,在Messenger中創建一個處理程序是一種非常有用和高效的方式,可以在您的服務和活動之間創建通信橋樑。通過這種方式,您可能會創建代表服務中當前狀態的狀態標籤,克你的情況:

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

然後在你的活動,一旦你從您的Messenger得到了回調,您可以簡單地這樣做:

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

你爲什麼要更改的按鈕文中的服務? 也許這是你真正需要的。 公共類測試擴展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

意思是我需要兩個按鈕?因爲我想這些在點擊事件上基本上是兩種不同的,我怎樣才能在我的XML文件中給出一個按鈕,兩個點擊事件? @Guliash – Viverson

0

聲明你的按鈕,在您的活動如靜態

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

然後做你的服務,你想

WeakReference<Button> recordButton = new WeakReference<Button>(YourActivity.recordButton); 
recordButton.setText("Start Recording"); 
這樣的事情
+0

這不是一個好的解決方案,有更好的方法來處理這種情況,而不是靜態的視圖。 – JoxTraex