When I am connecting to the CC device form my Sender application, often the Custom Receiver does not launch properly.
It will load, but will never be in a ready state.
Here is the logcat output:
01-21 14:16:09.603 19396-19396/com.example.chromecast D/PlayActivity onRouteSelected
01-21 14:16:16.913 19396-19396/com.example.chromecast D/PlayActivity onConnected
01-21 14:16:16.953 19396-19396/com.example.chromecast D/ccl_BaseCastManager﹕ [v1.11] onConnected() reached with prior suspension: false
01-21 14:16:16.953 19396-19396/com.example.chromecast D/ccl_BaseCastManager﹕ [v1.11] launchApp() is called
01-21 14:16:16.953 19396-19396/com.example.chromecast D/ccl_BaseCastManager﹕ [v1.11] Launching app
01-21 14:16:17.003 19396-19396/com.example.chromecast D/ccl_DataCastManager﹕ [v1.11] onApplicationStatusChanged() reached:
01-21 14:16:19.513 19396-19396/com.example.chromecast D/ccl_DataCastManager﹕ [v1.11] onApplicationStatusChanged() reached: null
01-21 14:16:20.633 19396-19396/com.example.chromecast D/ccl_BaseCastManager﹕ [v1.11] launchApplication() -> failure result
01-21 14:16:20.633 19396-19396/com.example.chromecast D/ccl_BaseCastManager﹕ [v1.11] disconnectDevice(true,false)
01-21 14:16:20.633 19396-19396/com.example.chromecast D/ccl_BaseCastManager﹕ [v1.11] mConnectionSuspended: false
01-21 14:16:20.633 19396-19396/com.example.chromecast D/ccl_BaseCastManager﹕ [v1.11] clearPersistedConnectionInfo(): Clearing persisted data for 0
01-21 14:16:20.653 19396-19396/com.example.chromecast D/ccl_BaseCastManager﹕ [v1.11] onDisconnected() reached
01-21 14:16:20.653 19396-19396/com.example.chromecast D/ccl_BaseCastManager﹕ [v1.11] Trying to disconnect
01-21 14:16:37.295 19396-19396/com.example.chromecast D/PlayActivity ApplicationConnectionResultCallback.onResult: statusCode15
01-21 14:16:37.295 19396-19396/com.example.chromecast E/PlayActivity application could not launch
01-21 14:16:37.295 19396-19396/com.example.chromecast D/PlayActivity teardown
If I disconnect in my Sender app, then re-connect, the Receiver will get into the ready state and I can cast my content.
What would be causing this behaviour? (It happens more often then not and is very fustrating!)
Some code:
(Media Route initialisation)
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory(
CastMediaControlIntent.categoryForCast(getResources()
.getString(R.string.app_id))).build();
mMediaRouterCallback = new MyMediaRouterCallback();
mDataCastManager = DataCastManager.initialize(this, getResources().getString(R.string.app_id), getResources().getString(R.string.namespace));
mDataCastManager.reconnectSessionIfPossible(this, true, 20);
Media Route button
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat.getActionProvider(mediaRouteMenuItem);
mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector);
return super.onCreateOptionsMenu(menu);
}
Callbacks
private class MyMediaRouterCallback extends MediaRouter.Callback {
#Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
Log.d(TAG, "onRouteSelected");
// Handle the user route selection.
mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
launchReceiver();
}
#Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
Log.d(TAG, "onRouteUnselected: info=" + info);
teardown();
mSelectedDevice = null;
}
}
As you can see, most of my implementation is from the CastHelloText Android sample application. I have added in the CCL library to allow easy session management, but I think that is causing the issue.
Commenting out the DataCastManager seems to give much better results when connecting the the CC device for casting.
If you are using CCL, then stop managing the media router button, the direct callbacks from media router, launching receiver, etc since those are handled by CCL. If you want to do those things yourself, then stop using CCL; you are currently mixing two different things in a wrong way. Reading the docs on CCL can be helpful.
Related
I used the code from this link MediaSession onMediaButtonEvent works for a few seconds then quits - Android to capture the keyevents of the remote button and send it to the audio() function where the selection will be played by another mediaplayer.
I run into the same problems where the code will crash after a few seconds. I so far tried to do a loop and also made the audio track not to do at.stop() or do at.release but eventually it still crashes. This keeps the service alive for a bit but then will still crash. I have the code and logcat
public class PlayerService extends Service {
private MediaSessionCompat mediaSession;
AudioTrack at;
#Override
public void onCreate() {
super.onCreate();
MediaSession ms = new MediaSession(getApplicationContext(), getPackageName());
ms.setActive(true);
ms.setCallback(new MediaSession.Callback() {
#Override
public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
KeyEvent keyEvent = (KeyEvent) mediaButtonIntent.getExtras().get(Intent.EXTRA_KEY_EVENT);
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyEvent.getKeyCode()) {
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
audio("button0");
break;
case KeyEvent.KEYCODE_MEDIA_REWIND:
audio("button1");
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
audio("button2");
break;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
audio("button3");
break;
}
}
return super.onMediaButtonEvent(mediaButtonIntent);
}
});
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
ms.setMediaButtonReceiver(mediaButtonReceiverPendingIntent);
at = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT), AudioTrack.MODE_STREAM);
**//at.setLoopPoints(3, 10,10000000);
at.play();
at.stop();
at.release();**
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
mediaSession.release();
}
public void audio(String command) {
MediaPlayer player = new MediaPlayer();
try {
switch (command) {
case "button0":
player = MediaPlayer.create(this, R.raw.button0);
break;
case "button1":
player = MediaPlayer.create(this, R.raw.button1);
break;
case "button2":
player = MediaPlayer.create(this, R.raw.button2);
break;
case "button3":
player = MediaPlayer.create(this, R.raw.button3);
break;
}
player.start();
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
My logcat log
2022-02-13 19:08:01.568 19045-19060/com.example.medialistenercopy W/MediaPlayer-JNI: MediaPlayer finalized without being released
2022-02-13 19:08:01.568 19045-19060/com.example.medialistenercopy I/MediaPlayerNative: setListener
2022-02-13 19:08:01.569 19045-19060/com.example.medialistenercopy I/MediaPlayerNative: disconnect
2022-02-13 19:08:01.580 19045-19060/com.example.medialistenercopy I/MediaPlayerNative: destructor
2022-02-13 19:08:01.581 19045-19060/com.example.medialistenercopy I/MediaPlayerNative: disconnect
2022-02-13 19:08:56.467 19045-19045/com.example.medialistenercopy D/AndroidRuntime: Shutting down VM
--------- beginning of crash
2022-02-13 18:57:56.595 17903-17903/com.example.medialistenercopy E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.medialistenercopy, PID: 17903
java.lang.RuntimeException: Unable to stop service com.example.medialistenercopy.PlayerService#e1c144e: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.media.session.MediaSessionCompat.release()' on a null object reference
at android.app.ActivityThread.handleStopService(ActivityThread.java:3880)
at android.app.ActivityThread.access$1700(ActivityThread.java:208)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1733)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:205)
at android.app.ActivityThread.main(ActivityThread.java:6991)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:884)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.media.session.MediaSessionCompat.release()' on a null object reference
at com.example.medialistenercopy.PlayerService.onDestroy(PlayerService.java:114)
at android.app.ActivityThread.handleStopService(ActivityThread.java:3860)
at android.app.ActivityThread.access$1700(ActivityThread.java:208)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1733)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:205)
at android.app.ActivityThread.main(ActivityThread.java:6991)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:884)
2022-02-13 18:57:56.668 17903-17903/com.example.medialistenercopy I/Process: Sending signal. PID: 17903 SIG: 9
Is the problem because the fake audio track ended too soon or because I have another mediaplayer playing sounds too. I am tweeking everything I can.
I tried to tweek the audio track and I got
2022-02-13 20:58:55.609 27560-27560/com.example.medialistenercopy V/AudioTrack: getMinFrameCount=3844: afFrameCount=1920, afSampleRate=48000, afLatency=80
2022-02-13 20:58:55.610 27560-27560/com.example.medialistenercopy V/AudioTrack: set(): streamType -1, sampleRate 48000, format 0x1, channelMask 0x3, frameCount 3844, flags #0, notificationFrames 0, sessionId 0, transferType 3, uid -1, pid -1
2022-02-13 20:58:55.610 27560-27560/com.example.medialistenercopy V/AudioTrack: Building AudioTrack with attributes: usage=1 content=2 flags=0x0 tags=[]
2022-02-13 20:58:55.619 27560-27560/com.example.medialistenercopy W/AudioTrack: Use of stream types is deprecated for operations other than volume control
2022-02-13 20:58:55.619 27560-27560/com.example.medialistenercopy W/AudioTrack: See the documentation of AudioTrack() for what to use instead with android.media.AudioAttributes to qualify your playback use case
2022-02-13 20:58:55.625 27560-27560/com.example.medialistenercopy V/AudioTrack: ~AudioTrack, releasing session id 8857 from 27560 on behalf of 27560
2022-02-13 20:58:55.626 27560-27560/com.example.medialistenercopy W/MediaAnalyticsItem: Unable to record: [1:audiotrack:0:-1::0:-1:1:0:5:android.media.audiotrack.underrunframes=1922:android.media.audiotrack.type=AUDIO_CONTENT_TYPE_MUSIC:android.media.audiotrack.usage=AUDIO_USAGE_MEDIA:android.media.audiotrack.samplerate=48000:android.media.audiotrack.channelmask=3:] [forcenew=0]
The specific reason for your crash is likely because you do not assign the field mediaSession; you've instead assigned an instance of MediaSession to a variable in a function scope inside onCreate().
I would like to call out that we recommend handling the onPlay(), onPause(), onFastForward(), etc. callbacks from MediaSession.Callback, as opposed to implementing onMediaButtonEvent(). The reason for this, is that not all actions are provided as a media button, such as seek commands, ratings or custom actions.
For more information about media sessions, see also my contextual video on this topic and the dedicated codelab.
I keep getting this error message when i run my game:
01-21 16:14:00.911: E/AndroidRuntime(15779): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6373)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:878)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:361)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.ScrollView.requestLayout(ScrollView.java:1483)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:361)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.TextView.checkForRelayout(TextView.java:6914)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.TextView.setText(TextView.java:4096)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.TextView.setText(TextView.java:3954)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.TextView.setText(TextView.java:3929)
01-21 16:14:00.911: E/AndroidRuntime(15779): at com.gamerscave.corpboss.Game.Overview_Viewupdate(Game.java:305)
01-21 16:14:00.911: E/AndroidRuntime(15779): at com.gamerscave.corpboss.Game.tick(Game.java:174)
01-21 16:14:00.911: E/AndroidRuntime(15779): at com.gamerscave.corpboss.game.GameThread.run(GameThread.java:27)
this error code is caused by:
public void Overview_Viewupdate(){
tv1.setText("Balance: " + Maths.coustomFormat(DEFAULT_BIG_NUMBER_PATTERN, bal));
tv2.setText("Income: " + Maths.coustomFormat(DEFAULT_BIG_NUMBER_PATTERN, inc));
tv3.setText("Nett worth: " + Maths.coustomFormat(DEFAULT_BIG_NUMBER_PATTERN, NettWorth));
tv4.setText("Shares: " + sharePercent + "%");
tv5.setText("Share value: " + ShareVal);
tv6.setText("Date: " + Date);
}
and it is called at:
public void tick(){
player.tick();
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>1000)
{
nextDay(day, year, month);
System.out.println("New day: " + day);
startTime = System.nanoTime();
}
if(view1){
Overview_Viewupdate();
}
}
for some reason it isnt triggered on the launch. the launch change is called in the init method. the init method is called from the GameThread-class' run method. So how do I avoid this error and still have a game thread that works?
The error above happens because Android doesn’t want other threads, such as your timer, messing with its GUI. So, what you need to do is politely ask Android to make the update for you.
public void tick(){
player.tick();
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>1000)
{
nextDay(day, year, month);
System.out.println("New day: " + day);
startTime = System.nanoTime();
}
if(view1){
runOnUiThread(new Runnable() {
public void run(){
Overview_Viewupdate();
}
});
}
}
Your problem is that you are updating UI elements on a non-UI thread. There's a couple of ways around this. In your case, I believe the best way is to use a RunOnUiThread statement, as follows (Note, this has to be done on an Activity):
RuOnUiThread(new Runnable() {
void run() {
Overview_Viewupdate();
}
});
Your problem is that you are updating UI elements on a non-UI thread. There's a couple of ways around this. In your case, I believe the best way is to use a RunOnUiThread statement, as follows (Note, this has to be done on an Activity):
RuOnUiThread(new Runnable() {
void run() {
Overview_Viewupdate();
}
});
This code would replace your current calling of Overview_ViewUpdate. Alternatively, you could consider an AysncTask, where your OnPostExecute runs Overview_ViewUpdate() and your doInBackground() does the operations that must be run in the background.
Also, make sure your UI elements are created on the UI thread. This is usually done in OnCreate or OnStart. AddContentView(...) or SetContentView(...) counts as such.
So I have an app that uses a surface view that runs a separate thread for the UI. It was taken almost directly from the Lunar Landing sample app. The app also uses Bluetooth service on another thread but I am sure that this is not related to the problem because I can disable bluetooth all together and it still happens.
The problem in my app is that the app when closed and then reopened does not start running the UI thread afterthread.start() except it throws an error. In the Lunar example they have thread.start() in the onSurfaceCreated method. The problem is when I restart my app (it calls onPause then onSurfaceDestroy) the thread is already running and I get an error when I try to start it. My code for onSurfaceCreated, onPause, onResume and onSurfaceDestroyed is all the same as the example. I know I can use if (this.getState() == Thread.State.NEW) { but that seems like it will mask some of my other issues. I want to master the activity life cycle.
My question is how does the Lunar Lander stop the thread? And why is mine not stopping with the same code and running at the onSurfaceCreated method. Obviously I am missing something. As far as I know in the Lunar example the only thing that is called on the thread on a destroy is thread.join().
Edit 3: Here is the Lunar Lander Example Code if needed.
So these are the three override methods in my surfaceview...
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG, "surfaceCreated");
// start the bluetooth service
thread.startBluetoothService();
// start the game
//if (this.getState() == Thread.State.NEW) {
Log.d(TAG, "thread start");
// start running the thread
this.start();
//}
Log.d(TAG, "running to true");
// release the thread lock
setRunning(true);
}
// surfaceChanged is called at least once after surfaceCreated
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d(TAG, "surfaceChanged");
// reset the surface size
thread.setSurfaceSize(width, height);
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG, "surfaceDestroyed");
// make sure to shut down the thread cleanly
boolean retry = true;
// stop the running thread
thread.setRunning(false);
// continuously try to shut down the thread
while (retry){
try{
// blocks calling thread until termination
thread.join();
// stop the bluetooth service
//thread.stopBluetoothService();
retry = false;
}catch(InterruptedException e){
//try to shut it down again
}
}
}
I am really pretty lost with all of this. Any help would be very appreciated, thanks!
Edit:
So I did a little more testing. When the user hits home(which exits the app completely) onPause, then onSurfaceDestroy like I said before. Then when it restarts I get onResume followed by onSurfaceCreated. I think my issue is that it is not calling onCreate when you reenter the app.
Some more questions...
What distinguishes the difference between a onPause and a onDestroy? I think my problem is that since onCreate is not being called I don't have a newly created UI thread which seems like it is still running.
Should the thread be stopped even on a onPause? Because then I am not garenteed to run onCreate which re instantiates the thread. Here is the onCreate code...
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wobble);
// get view and thread
wobbleView = (WobbleView) findViewById(R.id.wobble);
wobbleThread = wobbleView.getThread();
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
// alert the user of bluetooth failure
Toast.makeText(this, "Bluetooth is not available, using internal devices sensors", Toast.LENGTH_LONG).show();
// set the data source to internal sensors - so we'll just use the devices accel
wobbleThread.setDataSource(WobbleThread.INTERNAL_SENSORS);
// bluetooth is supported so make sure its enabled and
}else{
// make sure bluetooth is enabled on the device
if (!mBluetoothAdapter.isEnabled()) {
Log.d(TAG, "starting request to enable bluetooth");
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
// all is well with bluetooth - use bluetooth
Log.d(TAG, "setting bluetooth to bluetooth");
wobbleThread.setDataSource(WobbleThread.BLUETOOTH);
}
// give the LunarView a handle to the TextView used for messages
wobbleView.setTextView(
(TextView) findViewById(R.id.text_accel),
(TextView) findViewById(R.id.game_msg),
(TextView) findViewById(R.id.text_score),
(TextView) findViewById(R.id.bluetooth_status)
);
if (savedInstanceState == null) {
// we were just launched: set up a new game
//wobbleThread.setState(wobbleThread.STATE_READY);
} else {
//wobbleThread.setRunning(true);
// we are being restored: resume a previous game
//wobbleThread.restoreState(savedInstanceState);
}
}
Edit 2:
Some logcat output
So this is what I get when the thread.start() is called after reopening the app.
11-18 22:50:44.104 4868-4868/com.bme.shawn.wobble E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalThreadStateException: Thread already started
at java.lang.Thread.checkNotStarted(Thread.java:871)
at java.lang.Thread.start(Thread.java:1025)
at com.bme.shawn.wobble.WobbleThread.startGame(WobbleThread.java:213)
at com.bme.shawn.wobble.WobbleView.surfaceCreated(WobbleView.java:94)
at android.view.SurfaceView.updateWindow(SurfaceView.java:580)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:240)
at android.view.View.dispatchWindowVisibilityChanged(View.java:7903)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1289)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1050)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5750)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791)
at android.view.Choreographer.doCallbacks(Choreographer.java:591)
at android.view.Choreographer.doFrame(Choreographer.java:561)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5406)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
And if I use the thread.getState check and bypass the error I get this when I close then reopen the app. (logs in basically everything) In this case when the app reopens the thread is not drawing at all. Which is very weird since without the check I get an error saying that the thread is already running.
11-18 22:59:13.444 5345-5345/com.bme.shawn.wobble D/WobbleActivity﹕ onPause
11-18 22:59:13.584 5345-5345/com.bme.shawn.wobble D/WobbleView﹕ surfaceDestroyed
11-18 22:59:17.794 5345-5345/com.bme.shawn.wobble D/WobbleActivity﹕ onResume
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleView﹕ surfaceCreated
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleThread﹕ running to true
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleView﹕ surfaceChanged
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleThread﹕ setting surface sizes
11-18 22:59:17.824 5345-5345/com.bme.shawn.wobble D/dalvikvm﹕ GC_FOR_ALLOC freed 3343K, 2% free 6585K/6668K, paused 13ms, total 13ms
11-18 22:59:17.844 5345-5345/com.bme.shawn.wobble E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 44
11-18 22:59:17.854 5345-5345/com.bme.shawn.wobble E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 50
Create a new instance of the thread in surfaceCreated() and start it. And call thread.join() in surfaceDestroyed()to destroy it.
I have been able to set up a connection between my socket server (running on ruby) and my client, which is an Android(java) application. I will explain what my goal is.
I have to send a string to my server through the socket. Depending on the contents of the string, the server would execute a process in the database (store, delete, view data, etc).
The first option is to validate the user name/password. Im able to send the correct string, and the server receives it and replies back to me with the correct response (after validating whether or not my username is capable of logging into the application). Now, depending on this response i need to change the current activity (loginActivity) with the next activity (MenuActivity) so that the user can proceed to use the application menu.
Since the socket has to run on a different thread other than the UIThread, im running it using the AsyncTask way. However im having problems triggering the activity change thing after the AsyncTask process is over.
What im doing is, after the whole Async task is done (onPostExecute method) im trying to call up the activity, but its not working. This is what i've tried (based on similar cases i've found during research):
(AsyncTask class)
Context context;
private void AppContext(Context context) {
this.context = context.getApplicationContext();
}
OnPostExecute
Intent NewActivity = new Intent();
NewActivity.setClass(context.getApplicationContext(),MainActivity.class);
context.startActivity(NewActivity);
However this is not working and its causing my app to crash with a "thread exciting with uncaught exception"
I've tried showing only a Toast message that says "Granted" or "Denied" just to test it with a simpler task, but i keep getting the same error so im assuming its got to do with handling the change between the thread on which the Async task is running and the UI thread. Any ideas?
P.S: I've checked the other questions that are similar to mine and tried the suggested code, but nothing's worked.
ERROR LOG
09-29 09:59:11.387: E/AndroidRuntime(2856): FATAL EXCEPTION: main
09-29 09:59:11.387: E/AndroidRuntime(2856): java.lang.NullPointerException
09-29 09:59:11.387: E/AndroidRuntime(2856): at com.example.prescoterm.SocketClass.onPostExecute(SocketClass.java:111)
09-29 09:59:11.387: E/AndroidRuntime(2856): at com.example.prescoterm.SocketClass.onPostExecute(SocketClass.java:1)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.AsyncTask.finish(AsyncTask.java:602)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.AsyncTask.access$600(AsyncTask.java:156)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.Handler.dispatchMessage(Handler.java:99)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.Looper.loop(Looper.java:137)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.app.ActivityThread.main(ActivityThread.java:4424)
09-29 09:59:11.387: E/AndroidRuntime(2856): at java.lang.reflect.Method.invokeNative(Native Method)
09-29 09:59:11.387: E/AndroidRuntime(2856): at java.lang.reflect.Method.invoke(Method.java:511)
09-29 09:59:11.387: E/AndroidRuntime(2856): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
09-29 09:59:11.387: E/AndroidRuntime(2856): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
09-29 09:59:11.387: E/AndroidRuntime(2856): at dalvik.system.NativeStart.main(Native Method)
Ok so i found a workaround this, now i would like to hear from you guys if you think this'd be a suitable solution.
Since the problem was that the context was coming up null at my AsyncTask class, i decided to load the value on a variable from the moment the application start.
context = this.getApplicationContext();
new SocketReception().setContext(context);
On my SocketReception Class i had a setContext(context) method.
public void setContext(Context context)
{
SocketReception.appContext= context;
};
Now, on my AsyncTask post.execute i call the new activity like this:
SocketReception.appContext.startActivity(NewActivity);
Its now working, but i want to know if this is a convenient approach or if i should keep looking for a different solution.
P.S: I had to add the unpopular "FLAG_ACTIVITY_NEW_TASK", will research on how to avoid this later on.
I have used this asynctask directly in activity and work fine, may be help. When i try call Intent i = new Intent(getApplicationContext(), VyberIcoActivitySD.class); in class without context ( class extended not Activity, Fragment... ) i have not result...
class SynchroAllIcosSD extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(SynchroIcoActivitySD.this);
pDialog.setMessage(getString(R.string.progdata));
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected String doInBackground(String... args) {
//do something
return null;
}
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
Intent i = new Intent(getApplicationContext(), VyberIcoActivitySD.class);
Bundle extras = new Bundle();
extras.putString("odkade", "100");
extras.putString("page", "1");
i.putExtras(extras);
startActivity(i);
finish();
}
});
}
}
i am trying to implement Runnable and run the Run() method when a thread is started. but when i run the program it crashed.
MainActivity
public class MainActivity extends Activity implements Runnable{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread t1;
t1=new Thread(this);
t1.start();
}
public void run() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "display something",
Toast.LENGTH_LONG).show();
}
i tried changing it to t1=new Thread(new MainActivity());(app crashed) or just t1=new Thread(); never crash but no output.
how do i implement a Runnable Run when a thread is started? i search all over the place but could not find an answer. i need to include this function in my main project code too. but i create a separate testing project just to get how this works so i can add it in my main project code myself. at my main project it crashed at this point too. it never reached the Run method.
after it crashed, this is the LogCat
01-21 13:03:06.460: W/dalvikvm(879): threadid=11: thread exiting with uncaught exception (group=0xb3a6fb90)
01-21 13:03:06.460: E/AndroidRuntime(879): FATAL EXCEPTION: Thread-51
01-21 13:03:06.460: E/AndroidRuntime(879): Process: com.example.testthreadrun, PID: 879
01-21 13:03:06.460: E/AndroidRuntime(879): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
01-21 13:03:06.460: E/AndroidRuntime(879): at android.os.Handler.<init>(Handler.java:200)
01-21 13:03:06.460: E/AndroidRuntime(879): at android.os.Handler.<init>(Handler.java:114)
01-21 13:03:06.460: E/AndroidRuntime(879): at android.widget.Toast$TN.<init>(Toast.java:327)
01-21 13:03:06.460: E/AndroidRuntime(879): at android.widget.Toast.<init>(Toast.java:92)
01-21 13:03:06.460: E/AndroidRuntime(879): at android.widget.Toast.makeText(Toast.java:241)
01-21 13:03:06.460: E/AndroidRuntime(879): at com.example.testthreadrun.MainActivity.run(MainActivity.java:29)
01-21 13:03:06.460: E/AndroidRuntime(879): at java.lang.Thread.run(Thread.java:841)
01-21 13:03:07.010: I/Choreographer(879): Skipped 126 frames! The application may be doing too much work on its main thread.
01-21 13:03:07.970: I/Choreographer(879): Skipped 165 frames! The application may be doing too much work on its main thread.
01-21 13:03:08.840: D/gralloc_goldfish(879): Emulator without GPU emulation detected.
01-21 13:03:10.770: I/Choreographer(879): Skipped 31 frames! The application may be doing too much work on its main thread.
01-21 13:03:26.670: I/Process(879): Sending signal. PID: 879 SIG: 9
Since you are trying to update the UI, you need to do it on the UI Thread. You should use something like runOnUiThread() or AsyncTask.
runOnUiThread(new Runnable()
{
#Override
public void run()
{
Toast.makeText(MainActivity.this, "display something",
Toast.LENGTH_LONG).show();
}
});
or
Example of AsyncTask
AsyncTask Docs
You can't update ui from a background thread. You can update ui from ui thread only.
You can use runOnUiThread. But to just display a toast why do you require a thread?.
http://developer.android.com/guide/components/processes-and-threads.html
You cannot do UI changes (like a toast) on a thread that is not the UI thread. Use this instead:
public void run() {
MainActivity.this.runOnUiThread(new Runnable(){
#Override
public void run(){
Toast.makeText(MainActivity.this, "display something",
Toast.LENGTH_LONG).show();
}
});
}
However, why are you creating a whole separate thread to show a toast? You're better off just putting Toast.makeText(MainActivity.this, "display something",
Toast.LENGTH_LONG).show(); in your onCreate method.