Я пытаюсь создать простое приложение для загрузки и воспроизведения музыкального файла. Я сделал код, но, пытаясь его протестировать, приложение замерзает и показывает, что "Тайм-аут запуска истек, отказавшись от блокировки". Если у кого-то есть идея, не могли бы вы дать мне небольшой совет? Ниже мой код.
Кстати, файл образца, который я пытаюсь загрузить, имеет размер 9.1MB.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
setDataSource("http://cfs.tistory.com/custom/blog/66/661632/skin/images/Believe.mp3");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void setDataSource(String path) throws IOException {
URL url = new URL(path);
HttpURLConnection cn = (HttpURLConnection) url.openConnection();
cn.setRequestMethod("GET");
cn.setDoOutput(true);
cn.connect();
String file_path = Environment.getExternalStorageDirectory()+"/download/";
String fileName = "Temp.wav";
File file = new File(file_path);
file.mkdir();
InputStream is = cn.getInputStream();
File output_file = new File(file, fileName);
FileOutputStream fos = new FileOutputStream(output_file);
byte[] buffer = new byte[4096];
int read = 0;
while ((read = is.read(buffer)) > 0){
fos.write(buffer, 0, read);
}
is.close();
fos.close();
mp = new MediaPlayer();
mp.setDataSource(file_path+fileName);
mp.prepare();
mp.start();
}
}
** Модифицировано: ** Джастин научил меня, если я просто положил его onCreate(), тогда это вызывает проблему. Теперь я использую кнопку с потоком, но есть еще одна проблема, которая говорит, что только исходный поток, создавший иерархию представлений, может коснуться его представлений и, похоже, что это происходит в 'fos.close'. Если кто-нибудь знает, что делать, не могли бы вы мне помочь?
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.tv1);
tv2 = (TextView) findViewById(R.id.tv2);
tv.setText(Environment.getExternalStorageDirectory()+"/download/");
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
Thread thread;
Runnable r = new Runnable(){
public void run(){
try {
setDataSource("http://cfs.tistory.com/custom/blog/66/661632/skin/images/Believe.mp3");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
thread = new Thread(r);
thread.start();
}
});
}
** Сообщения об ошибках: **
07-15 04:31:45.321: ERROR/AndroidRuntime(313): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Проблема в том, что ваш метод блокирует поток пользовательского интерфейса в течение длительного периода времени, и поэтому Android является принудительным закрытием приложения.
Попробуйте запустить длительный процесс в фоновом потоке в onCreateMethod(), а затем обновите интерфейс после его завершения.
Лучший способ узнать, как применять многопоточность, - это фактически просмотреть один из приложений Google, которые его используют. Вот цитата из первой ссылки.
"We highly recommend reading the source code of Shelves to see how to
persist tasks across configuration changes and how to cancel them
properly when the activity is destroyed."
Обновление: вы должны переместить медиаплеер обратно в поток пользовательского интерфейса и запустить фоновый поток, а затем обновить строку, которая передает медиаплеер, когда он закончит. Возможно, вам понадобится рефакторинг для использования задачи Async и переместите создание медиаплеера в onPostExecute(). Вы можете остановиться здесь и поэкспериментировать с Async Task и посмотреть, как приложение Shelves выполняет многопоточность.
Вы можете найти ссылки на приложение "Полки" в первом URL-адресе, который я поставил выше (в нижней части страницы).
призвание. setDataSource как это
В вашей деятельности сделайте один обработчик, чтобы получить контроль, когда музыкальный файл был загружен.
Handler h1 = new Handler(){
public void handleMessage(Message msg){
// put the check here to see
}
};
new Thread(new Runnable(){
public void run(){
// set your datasource here
// back to your handler
}
}){
}.start();