Hi,
I have created an app with webview and when I press a button jsp alert
an url. I handle this url in my webview app, I can handled the correct
url address but media player doesn't play my app forces down.
When I didn't use webview I can play any url with same media player
class. (Sorry for my english)
Where is my error?
WARN/dalvikvm(10312): threadid=1: thread exiting with uncaught
exception (group=0x4001d7d0)
INFO/(10312): PRODUCT_SHIP = false
ERROR/AndroidRuntime(10312): FATAL EXCEPTION: main
ERROR/AndroidRuntime(10312): java.lang.NullPointerException
ERROR/AndroidRuntime(10312): at com.basarimobile.mobilmp3.Main
$MyWebChromeClient.onJsAlert(Main.java:161)
ERROR/AndroidRuntime(10312): at
android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:515)
ERROR/AndroidRuntime(10312): at
android.os.Handler.dispatchMessage(Handler.java:99)
ERROR/AndroidRuntime(10312): at android.os.Looper.loop(Looper.java:
123)
ERROR/AndroidRuntime(10312): at
android.app.ActivityThread.main(ActivityThread.java:4627)
ERROR/AndroidRuntime(10312): at
java.lang.reflect.Method.invokeNative(Native Method)
ERROR/AndroidRuntime(10312): at
java.lang.reflect.Method.invoke(Method.java:521)
ERROR/AndroidRuntime(10312): at com.android.internal.os.ZygoteInit
$MethodAndArgsCaller.run(ZygoteInit.java:871)
ERROR/AndroidRuntime(10312): at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629)
ERROR/AndroidRuntime(10312): at
dalvik.system.NativeStart.main(Native Method)
WARN/ActivityManager(2487): Force finishing activity
com.basarimobile.mobilmp3/.Main
INFO/Launcher(4550): onResume(). mIsNewIntent : false
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
My Source Code;
##Main##
import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
public class Main extends Activity {
private Button streamButton;
private ImageButton playButton;
private TextView textStreamed;
WebView webview ;
ConnectivityManager cm ;
ProgressDialog myProgressDialog;
ConnectivityManager connectivity;
/** Called when the activity is first created. */
Context c= this;
private boolean isPlaying;
private StreamingMediaPlayer audioStreamer;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
connectivity =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
loadView();
}
@Override
public void onResume()
{
super.onResume();
}
public void loadView()
{
webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new MyWebChromeClient());
openURL("http://wap1.mobiloyuncu.com/android/mobilmp3/index.jsp");
}
private void openURL(String servis)
{
String
url="http://wap1.mobiloyuncu.com/android/mobilmp3/index.jsp";
webview.loadUrl(url);
webview.setWebViewClient(new MyWebViewClient());
}
private class MyWebViewClient extends WebViewClient
{
public boolean shouldOverrideUrlLoading(WebView view, String
url)
{
view.loadUrl(url);
return true;
}
public void onPageStarted(WebView view, String url, Bitmap
favicon)
{
myProgressDialog =
ProgressDialog.show(Main.this,getString(R.string.info_pleasewait)
,getString(R.string.info_pleasewait),
true);
myProgressDialog.setCancelable(true);
cm = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
if
(cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnectedOrConnecting()
||
cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting())
{
//System.out.println("onPageStarted: " + url);
}
else{
view.setVisibility(View.GONE);
AlertDialog alertDialog = new
AlertDialog.Builder(Main.this).create();
alertDialog.setTitle(getString(R.string.popupheader_warning));
alertDialog.setMessage(getString(R.string.info_noconnstatus));
alertDialog.setButton(getString(R.string.button_ok), new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface
dialog, int which) {
//here you can add functions
Main.this.finish();
}
});
alertDialog.show();
}
}
public void onPageFinished(WebView view, String url)
{
if(myProgressDialog!=null)
myProgressDialog.dismiss();
}
public void onReceivedError(WebView view, int errorCode, String
description, String failingUrl)
{
if(myProgressDialog!=null)
myProgressDialog.dismiss();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack())
{
webview.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
//-----------------------------------HANDLE
URL--------------------------------------------
final class MyWebChromeClient extends WebChromeClient
{
public void onCloseWindow(WebView window)
{
window.destroy();
}
public boolean onJsAlert(WebView view, String url, String
message,
JsResult result)
{
if(message.startsWith("start_"))
{
String uri = message;
uri = uri.substring(uri.indexOf("_")+1,
uri.length()).trim();
System.out.println("SONG URL::::::" + uri);
startStreamingAudio(uri);
System.out.println("Mobil
mp3::src::startStreamingAudio::Bilgi--
streaming sonrasi");
//This line gives error. (getMediaPlayer())
if (audioStreamer.getMediaPlayer().isPlaying()) {
System.out.println("Mobil
mp3::src::setOnClickListener::Bilgi--
isPlaying");
audioStreamer.getMediaPlayer().pause();
} else {
System.out.println("Mobil
mp3::src::setOnClickListener::Bilgi--
pause");
audioStreamer.getMediaPlayer().start();
audioStreamer.startPlayProgressUpdater();
}
isPlaying = !isPlaying;
System.out.println("Mobil
mp3::src::startStreamingAudio::Bilgi--
start sonrasi");
}
else if(message.equalsIgnoreCase("stop"))
{
audioStreamer.getMediaPlayer().pause();
}
else
{
AlertDialog alertDialog = new
AlertDialog.Builder(Main.this).create();
alertDialog.setTitle(getString(R.string.info_hata));
alertDialog.setMessage(message);
alertDialog.setButton(getString(R.string.button_ok), new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface
dialog, int which) {
//here you can add functions
}
});
alertDialog.show();
}
result.confirm();
return true;
}
}
private void startStreamingAudio(String uri) {
try {
final ProgressBar progressBar = (ProgressBar)
findViewById(R.id.progress_bar);
if ( audioStreamer != null) {
audioStreamer.interrupt();
}
audioStreamer = new StreamingMediaPlayer(this,textStreamed,
playButton, streamButton,progressBar);
//audioStreamer.startStreaming("http://www.pocketjourney.com/
downloads/pj/tutorials/audio.mp3",1717, 214);
audioStreamer.startStreaming(uri,5208, 216);
} catch (IOException e) {
Log.e(getClass().getName(), "Error starting to stream audio.",
e);
}
}
//----------------------------------END HANDLE
URL----------------------------------------------------
}
//--------------------------------------------------------------------------------------------------------------------------------------------
##StreamingMediaPlayer ##
package com.basarimobile.mobilmp3;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* MediaPlayer does not yet support streaming from external URLs so
this class provides a pseudo-streaming function
* by downloading the content incrementally & playing as soon as we
get enough audio in our temporary storage.
*/
public class StreamingMediaPlayer {
private static final int INTIAL_KB_BUFFER = 96*10/8;//assume
96kbps*10secs/8bits per byte
private TextView textStreamed;
private ImageButton playButton;
private ProgressBar progressBar;
// Track for display by progressBar
private long mediaLengthInKb, mediaLengthInSeconds;
private int totalKbRead = 0;
// Create Handler to call View updates on the main UI thread.
private final Handler handler = new Handler();
private MediaPlayer mediaPlayer;
private File downloadingMediaFile;
private boolean isInterrupted;
private Context context;
private int counter = 0;
public StreamingMediaPlayer(Context context,TextView textStreamed,
ImageButton playButton, Button streamButton,ProgressBar
progressBar)
{
this.context = context;
this.textStreamed = textStreamed;
this.playButton = playButton;
this.progressBar = progressBar;
}
/**
* Progressivly download the media to a temporary location and
update the MediaPlayer as new content becomes available.
*/
public void startStreaming(final String mediaUrl, long
mediaLengthInKb, long mediaLengthInSeconds) throws IOException {
this.mediaLengthInKb = mediaLengthInKb;
this.mediaLengthInSeconds = mediaLengthInSeconds;
Runnable r = new Runnable() {
public void run() {
try {
downloadAudioIncrement(mediaUrl);
} catch (IOException e) {
Log.e(getClass().getName(), "Unable to initialize the
MediaPlayer for fileUrl=" + mediaUrl, e);
return;
}
}
};
new Thread(r).start();
}
/**
* Download the url stream to a temporary location and then call
the setDataSource
* for that local file
*/
public void downloadAudioIncrement(String mediaUrl) throws
IOException {
URLConnection cn = new URL(mediaUrl).openConnection();
cn.connect();
InputStream stream = cn.getInputStream();
if (stream == null) {
Log.e(getClass().getName(), "Unable to create InputStream for
mediaUrl:" + mediaUrl);
}
downloadingMediaFile = new
File(context.getCacheDir(),"downloadingMedia.dat");
// Just in case a prior deletion failed because our code
crashed or
something, we also delete any previously
// downloaded file to ensure we start fresh. If you use this
code,
always delete
// no longer used downloads else you'll quickly fill up your
hard
disk memory. Of course, you can also
// store any previously downloaded file in a separate data
cache for
instant replay if you wanted as well.
if (downloadingMediaFile.exists()) {
downloadingMediaFile.delete();
}
FileOutputStream out = new
FileOutputStream(downloadingMediaFile);
byte buf[] = new byte[16384];
int totalBytesRead = 0, incrementalBytesRead = 0;
do {
int numread = stream.read(buf);
if (numread <= 0)
break;
out.write(buf, 0, numread);
totalBytesRead += numread;
incrementalBytesRead += numread;
totalKbRead = totalBytesRead/1000;
testMediaBuffer();
fireDataLoadUpdate();
} while (validateNotInterrupted());
stream.close();
if (validateNotInterrupted()) {
fireDataFullyLoaded();
}
}
private boolean validateNotInterrupted() {
if (isInterrupted) {
if (mediaPlayer != null) {
mediaPlayer.pause();
//mediaPlayer.release();
}
return false;
} else {
return true;
}
}
/**
* Test whether we need to transfer buffered data to the
MediaPlayer.
* Interacting with MediaPlayer on non-main UI thread can causes
crashes to so perform this using a Handler.
*/
private void testMediaBuffer() {
Runnable updater = new Runnable() {
public void run() {
if (mediaPlayer == null) {
// Only create the MediaPlayer once we have the minimum
buffered data
if ( totalKbRead >= INTIAL_KB_BUFFER) {
try {
startMediaPlayer();
} catch (Exception e) {
Log.e(getClass().getName(), "Error
copying buffered
conent.", e);
}
}
} else if ( mediaPlayer.getDuration() -
mediaPlayer.getCurrentPosition() <= 1000 ){
// NOTE: The media player has stopped at the end so
transfer any existing buffered data
// We test for < 1second of data because the media
player can stop when there is still
// a few milliseconds of data left to play
transferBufferToMediaPlayer();
}
}
};
handler.post(updater);
}
private void startMediaPlayer() {
try {
File bufferedFile = new
File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");
// We double buffer the data to avoid potential read/write
errors that could happen if the
// download thread attempted to write at the same time the
MediaPlayer was trying to read.
// For example, we can't guarantee that the MediaPlayer won't
open a file for playing and leave it locked while
// the media is playing. This would permanently deadlock the
file download. To avoid such a deadloack,
// we move the currently loaded data to a temporary buffer
file that we start playing while the remaining
// data downloads.
moveFile(downloadingMediaFile,bufferedFile);
Log.e(getClass().getName(),"Buffered File path: " +
bufferedFile.getAbsolutePath());
Log.e(getClass().getName(),"Buffered File length: " +
bufferedFile.length()+"");
mediaPlayer = createMediaPlayer(bufferedFile);
// We have pre-loaded enough content and started the MediaPlayer
so update the buttons & progress meters.
mediaPlayer.start();
startPlayProgressUpdater();
playButton.setEnabled(true);
} catch (IOException e) {
Log.e(getClass().getName(), "Error initializing the
MediaPlayer.", e);
return;
}
}
private MediaPlayer createMediaPlayer(File mediaFile)
throws IOException {
MediaPlayer mPlayer = new MediaPlayer();
mPlayer.setOnErrorListener(
new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int
what, int extra)
{
Log.e(getClass().getName(), "Error in
MediaPlayer: (" +
what +") with extra (" +extra +")" );
return false;
}
});
// It appears that for security/permission reasons, it is
better to
pass a FileDescriptor rather than a direct path to the File.
// Also I have seen errors such as "PVMFErrNotSupported" and
"Prepare failed.: status=0x1" if a file path String is passed to
// setDataSource(). So unless otherwise noted, we use a
FileDescriptor here.
FileInputStream fis = new FileInputStream(mediaFile);
mPlayer.setDataSource(fis.getFD());
mPlayer.prepare();
return mPlayer;
}
/**
* Transfer buffered data to the MediaPlayer.
* NOTE: Interacting with a MediaPlayer on a non-main UI thread
can cause thread-lock and crashes so
* this method should always be called using a Handler.
*/
private void transferBufferToMediaPlayer() {
try {
// First determine if we need to restart the player after
transferring data...e.g. perhaps the user pressed pause
boolean wasPlaying = mediaPlayer.isPlaying();
int curPosition = mediaPlayer.getCurrentPosition();
// Copy the currently downloaded content to a new buffered
File. Store the old File for deleting later.
File oldBufferedFile = new
File(context.getCacheDir(),"playingMedia" + counter + ".dat");
File bufferedFile = new
File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");
// This may be the last buffered File so ask that it be delete
on exit. If it's already deleted, then this won't mean anything. If
you want to
// keep and track fully downloaded files for later use, write
caching code and please send me a copy.
bufferedFile.deleteOnExit();
moveFile(downloadingMediaFile,bufferedFile);
// Pause the current player now as we are about to create and
start a new one. So far (Android v1.5),
// this always happens so quickly that the user never realized
we've stopped the player and started a new one
mediaPlayer.pause();
// Create a new MediaPlayer rather than try to re-prepare the
prior one.
mediaPlayer = createMediaPlayer(bufferedFile);
mediaPlayer.seekTo(curPosition);
// Restart if at end of prior buffered content or mediaPlayer
was previously playing.
// NOTE: We test for < 1second of data because the media
player
can stop when there is still
// a few milliseconds of data left to play
boolean atEndOfFile = mediaPlayer.getDuration() -
mediaPlayer.getCurrentPosition() <= 1000;
if (wasPlaying || atEndOfFile){
mediaPlayer.start();
}
// Lastly delete the previously playing buffered File as it's no
longer needed.
oldBufferedFile.delete();
}catch (Exception e) {
Log.e(getClass().getName(), "Error updating to newly loaded
content.", e);
}
}
private void fireDataLoadUpdate() {
Runnable updater = new Runnable() {
public void run() {
textStreamed.setText((totalKbRead + " Kb read"));
float loadProgress = ((float)totalKbRead/
(float)mediaLengthInKb);
progressBar.setSecondaryProgress((int)(loadProgress*100));
}
};
handler.post(updater);
}
private void fireDataFullyLoaded() {
Runnable updater = new Runnable() {
public void run() {
transferBufferToMediaPlayer();
// Delete the downloaded File as it's now been
transferred to the currently playing buffer file.
downloadingMediaFile.delete();
textStreamed.setText(("Audio full loaded: " +
totalKbRead +
" Kb read"));
}
};
handler.post(updater);
}
public MediaPlayer getMediaPlayer() {
return mediaPlayer;
}
public void startPlayProgressUpdater() {
float progress = (((float)mediaPlayer.getCurrentPosition()/1000)/
mediaLengthInSeconds);
progressBar.setProgress((int)(progress*100));
if (mediaPlayer.isPlaying()) {
Runnable notification = new Runnable() {
public void run() {
startPlayProgressUpdater();
}
};
handler.postDelayed(notification,1000);
}
}
public void interrupt() {
playButton.setEnabled(false);
isInterrupted = true;
validateNotInterrupted();
}
/**
* Move the file in oldLocation to newLocation.
*/
public void moveFile(File oldLocation, File newLocation)
throws IOException {
if ( oldLocation.exists( )) {
BufferedInputStream reader = new BufferedInputStream(
new
FileInputStream(oldLocation) );
BufferedOutputStream writer = new
BufferedOutputStream( new
FileOutputStream(newLocation, false));
try {
byte[] buff = new byte[8192];
int numChars;
while ( (numChars = reader.read( buff, 0, buff.length
) ) !
= -1) {
writer.write( buff, 0, numChars );
}
} catch( IOException ex ) {
throw new IOException("IOException when
transferring " +
oldLocation.getPath() + " to " + newLocation.getPath());
} finally {
try {
if ( reader != null ){
writer.close();
reader.close();
}
} catch( IOException ex ){
Log.e(getClass().getName(),"Error closing
files when
transferring " + oldLocation.getPath() + " to " +
newLocation.getPath() );
}
}
} else {
throw new IOException("Old location does not exist when
transferring " + oldLocation.getPath() + " to " +
newLocation.getPath() );
}
}
}
//------------------------------------------------------------------------------------------------------------------------------------
Thanks,
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en