我是一名学习者并正在开发Android应用以播放直播。它正常工作,除了1个问题。我想显示当前播放的曲目的标题,该标题可在webpge上获得。为此,我使用了一个textView并尝试使用Asynchronous Task并在该异步任务中调用一个包含Runnable的方法,我可以用30秒的间隔更新textView的文本。在runnable中我调用了一个加载网页的方法并将其内容作为字符串。
问题:当它尝试更新textView的文本时,应用程序崩溃。感谢提前。
以下是我的代码:
import java.io.IOException;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import android.app.ProgressDialog;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Handler;
import java.net.URLConnection;
import java.net.URL;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import android.util.Log;
import java.net.MalformedURLException;
import android.widget.TextView;
import android.os.AsyncTask;
public class MusicAndroidActivity extends Activity {
static MediaPlayer mPlayer;
Button buttonPlay;
Button buttonStop;
Button buttonPause;
public TextView txtMessage;
private StringBuilder response;
private String text="***";
ProgressDialog progDailog;
private final static int INTERVAL = 1000 * 30; //2 minutes
Handler mHandler;
int length=0;
String url = "http://www.s8.voscast.com:9630/;stream.mp3";
private final Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonStop = (Button) findViewById(R.id.stop);
txtMessage=(TextView)findViewById(R.id.txtMessage);
buttonStop.setEnabled(false);
buttonPause=(Button) findViewById(R.id.pause);
buttonPause.setEnabled(false);
buttonPlay = (Button) findViewById(R.id.play);
buttonPlay.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mPlayer = new MediaPlayer();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
buttonPlay.setEnabled(false);
buttonStop.setEnabled(true);
buttonPause.setEnabled(true);
//txtMessage.setText("Loading...");
progDailog = ProgressDialog.show(MusicAndroidActivity.this, "", "Buffering ... \n It can take upto 1 Minute, depending upon your internet speed", true);
mPlayer.setDataSource(url);
} catch (IllegalArgumentException e) {
Toast.makeText(getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (SecurityException e) {
Toast.makeText(getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (IllegalStateException e) {
Toast.makeText(getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
try {
mPlayer.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mPlayer) {
// TODO Auto-generated method stub
mPlayer.start();
progDailog.dismiss();
LoadWebPageASYNC task = new LoadWebPageASYNC();
task.execute(new String[]{"http://khilare.com/swltest/sms.html"});
}
});
mPlayer.prepareAsync();
} catch (IllegalStateException e) {
Toast.makeText(getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} //catch (IOException e) {
//Toast.makeText(getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
//}
}
});
buttonStop.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if(mPlayer!=null && mPlayer.isPlaying()){
mPlayer.stop();
buttonPlay.setEnabled(true);
buttonStop.setEnabled(false);
buttonPause.setEnabled(false);
}
}
});
buttonPause.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if(mPlayer!=null && mPlayer.isPlaying()){
mPlayer.pause();
length=mPlayer.getCurrentPosition();
buttonPause.setText("Resume");
//buttonPlay.setEnabled(true);
buttonStop.setEnabled(true);
buttonPlay.setEnabled(false);
//sapp();
//getHTML();
//txtMessage.setText(text);
txtMessage.setText(text);
}
else {
//mPlayer.seekTo(length);
mPlayer.start();
// mPlayer.seekTo(length);
buttonPause.setText("Pause");
}
}
});
}
protected void onDestroy() {
super.onDestroy();
// TODO Auto-generated method stub
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
private class LoadWebPageASYNC extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
getHTML();
//sapp();
txtMessage.setText(text);
return null;
}
}
private void sapp()
{
//Runnable updater1 = new Runnable() {
handler.postDelayed(new Runnable() {
//@Override
public void run() {
getHTML();
txtMessage.setText(text);
}
}, INTERVAL);
/*public void run() {
getHTML();
txtMessage.setText(text);
}
};*/
//handler.post(updater1);
}
private void getHTML()
{
try {
URLConnection connection = new URL("http://khilare.com/swltest/sms.html").openConnection();
connection.setRequestProperty("Accept-Charset", "UTF-8");
InputStream responseStream = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(responseStream));
response = new StringBuilder();
String line;
line = br.readLine();
{
response.append(line);
}
text = response.toString();
//txtMessage.setText(text);
//Log.i("Output", text);
} catch (MalformedURLException e) {
txtMessage.setText(e.getMessage());
e.printStackTrace();
} catch (IOException e) {
txtMessage.setText(e.getMessage());
e.printStackTrace();
}
//textStreamed.setText(text);
}
}
这是Logcat:
java.lang.SecurityException: Permission denial: writing to settings requires android.permission.WRITE_SETTINGS
at com.android.providers.settings.SettingsProvider.callFromPackage(SettingsProvider.java:645)
at android.content.ContentProvider$Transport.call(ContentProvider.java:279)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:273)
at android.os.Binder.execTransact(Binder.java:388)
at dalvik.system.NativeStart.run(Native Method)
05-29 10:56:45.772 302-302/? E/Parcel﹕ Reading a NULL string not supported here.
05-29 10:56:45.772 302-302/? E/Parcel﹕ Reading a NULL string not supported here.
05-29 10:56:48.462 302-302/? E/Parcel﹕ Reading a NULL string not supported here.
05-29 10:56:48.462 302-302/? E/Parcel﹕ Reading a NULL string not supported here.
05-29 10:56:50.702 302-302/? E/Parcel﹕ Reading a NULL string not supported here.
05-29 10:56:50.702 302-302/? E/Parcel﹕ Reading a NULL string not supported here.
05-29 10:56:50.712 302-302/? E/Parcel﹕ Reading a NULL string not supported here.
05-29 10:56:50.712 302-302/? E/Parcel﹕ Reading a NULL string not supported here.
05-29 10:57:01.772 28164-28569/com.prgguru.example E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:299)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
at java.util.concurrent.FutureTask.run(FutureTask.java:239)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:841)
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5969)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:921)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:4276)
at android.view.View.invalidate(View.java:10552)
at android.view.View.invalidate(View.java:10507)
at android.widget.TextView.checkForRelayout(TextView.java:6531)
at android.widget.TextView.setText(TextView.java:3789)
at android.widget.TextView.setText(TextView.java:3643)
at android.widget.TextView.setText(TextView.java:3618)
at com.prgguru.example.MusicAndroidActivity$LoadWebPageASYNC.doInBackground(MusicAndroidActivity.java:158)
at com.prgguru.example.MusicAndroidActivity$LoadWebPageASYNC.doInBackground(MusicAndroidActivity.java:152)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:841)
答案 0 :(得分:0)
我明白了。
我使用了TimeTask,它每10秒调用一次方法 UpdateGUI(); 。这种方法&#34; UpdateGUI(); &#34;进一步调用方法&#34; getHTML(); &#34;将网页内容加载到String文本。此方法也可通过 myHandler 调用 myRunnable
myHandler.post(myRunnable);
和 myRunnable 设置textView的文本 txtMessage
要完全了解此过程,请阅读this Article
代码现在是:
import java.io.IOException;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import android.app.ProgressDialog;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Handler;
import java.net.URLConnection;
import java.net.URL;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import android.util.Log;
import java.net.MalformedURLException;
import android.widget.TextView;
import java.util.TimerTask;
import java.util.Timer;
public class MusicAndroidActivity extends Activity {
static MediaPlayer mPlayer;
Button buttonPlay;
Button buttonStop;
Button buttonPause;
public TextView txtMessage;
private StringBuilder response;
private String text="***";
ProgressDialog progDailog;
final Handler myHandler = new Handler();
int length=0;
String url = "http://www.example.com:port/;stream.mp3";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonStop = (Button) findViewById(R.id.stop);
txtMessage=(TextView)findViewById(R.id.txtMessage);
buttonStop.setEnabled(false);
buttonPause=(Button) findViewById(R.id.pause);
buttonPause.setEnabled(false);
buttonPlay = (Button) findViewById(R.id.play);
buttonPlay.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mPlayer = new MediaPlayer();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
buttonPlay.setEnabled(false);
buttonStop.setEnabled(true);
buttonPause.setEnabled(true);
progDailog = ProgressDialog.show(MusicAndroidActivity.this, "", "Buffering ... \n It can take upto 1 Minute, depending upon your internet speed", true);
mPlayer.setDataSource(url);
} catch (IllegalArgumentException e) {
Toast.makeText(getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (SecurityException e) {
Toast.makeText(getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (IllegalStateException e) {
Toast.makeText(getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
try {
mPlayer.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mPlayer) {
// TODO Auto-generated method stub
mPlayer.start();
progDailog.dismiss();
}
});
mPlayer.prepareAsync();
Timer myTimer = new Timer(); // Declared Timer
myTimer.schedule(new TimerTask() { // Started Time Task, it will repeat as per given duration (Ours is 1000 or 10 Second)
@Override
public void run() {
UpdateGUI(); // Called Method UdateGUI
} // v
}, 0, 10000); // After Every 10 Seconds
} catch (IllegalStateException e) {
Toast.makeText(getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
}
}
});
buttonStop.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if(mPlayer!=null && mPlayer.isPlaying()){
mPlayer.stop();
buttonPlay.setEnabled(true);
buttonStop.setEnabled(false);
buttonPause.setEnabled(false);
}
}
});
buttonPause.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if(mPlayer!=null && mPlayer.isPlaying()){
mPlayer.pause();
length=mPlayer.getCurrentPosition();
buttonPause.setText("Play");
buttonStop.setEnabled(true);
buttonPlay.setEnabled(false);
}
else {
mPlayer.start();
buttonPause.setText("Pause");
}
}
});
}
protected void onDestroy() {
super.onDestroy();
// TODO Auto-generated method stub
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
private void UpdateGUI() {
getHTML();
myHandler.post(myRunnable); // Posted MyRunnable to myHandler
}
final Runnable myRunnable = new Runnable() {
public void run() {
txtMessage.setText(text); //Set txtMessage's value to text (text is a string declared above)
}
};
private void getHTML()
{
try {
URLConnection connection = new URL("http://example.com/stats/index.php").openConnection();
connection.setRequestProperty("Accept-Charset", "UTF-8");
InputStream responseStream = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(responseStream));
response = new StringBuilder();
String line;
line = br.readLine();
{
response.append(line);
}
text = response.toString();
} catch (MalformedURLException e) {
txtMessage.setText(e.getMessage());
e.printStackTrace();
} catch (IOException e) {
txtMessage.setText(e.getMessage());
e.printStackTrace();
}
}
}