This is the work flow.
When selecting the music, I want it
to play it, and if I select it on another, it will reset and stop the
clip that was playing, then it will move to the other and play it.
The question: Simply these are three codes. I want to activate the
latter after the previous one is activated.
Note: I succeeded in adding the command to press the play button But If I delete the first code (reset&stop) that plays by simply selecting it on
the list, But it never stops playing music and piles on top of each other nonstop
sound.reset();
sound.stop();
btn_play.callOnClick();
The code part is complete
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
view.setSelected(true);
sound.reset();
sound.stop();
btn_play.callOnClick();
sound = MediaPlayer.create(SoundActivity.this, listitems.get(i).sound);
tvTitle.setText(listitems.get(i).getTitle());
SoundTime();
}
});
final boolean[] isPlay = {false};
btn_play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!sound.isPlaying()) {
Thread updateSeekBar;
updateSeekBar = new Thread() {
#Override
public void run() {
int SoundDuration = sound.getDuration();
int currentPostion = 0;
seekBar.setMax(SoundDuration);
while (currentPostion < SoundDuration) {
try {
sleep(100);
currentPostion = sound.getCurrentPosition();
seekBar.setProgress(currentPostion);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
sound.start();
updateSeekBar.start();
}
Thanks to those who tried to help me. I found a very simple solution
after effort and effort:>
I moved (btn_play.callOnClick) down like this
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
view.setSelected(true);
sound.stop();
sound.reset();
sound = MediaPlayer.create(SoundActivity.this, listitems.get(i).sound);
tvTitle.setText(listitems.get(i).getTitle());
SoundTime();
btn_play.callOnClick();
}
});
Now it remains for me to auto-switch to the next music
Related
I'm having some issues to make work a code i took from a tutorial :
https://developer.android.com/guide/topics/connectivity/bluetooth/transfer-data
I tried connecting this way :
_spinnerBT_Devices.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView adapterView, View view, int i, long l) {
_Selected_Device = (BluetoothDevice) _BT_Devices_list.get(i);
_printf.setText(_Selected_Device.getName());
_myThread = new ConnectThread(_Selected_Device);
_myThread.run();
_myService = new MyBluetoothService.ConnectedThread(_myThread.mmSocket);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
//_myThread.cancel();
}
});
And write on my serial bluetooth :
public void buttonUpClick() {
_buttonUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
_printf.setText("Debug : UP");
if(_myService.mmSocket.isConnected()){
_myService.write("z".getBytes(StandardCharsets.UTF_8));
}
}
});
}
But as soon as I try to write on it, the app crashes, like it can't use two threads at the same time.
edit : I can write but only one time and it crashes
Found the problem
It wasn't about having 2 threads but the code was crashing cause of that part :
// Share the sent message with the UI activity.
Message writtenMsg = handler.obtainMessage(
MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
writtenMsg.sendToTarget();
I'm making a launcher and I am stuck on making a long click listener for the widgets. I made a class that extends AppWidgetHost and another that extends AppWidgetHostView. They intercept the touch event and if it's action up it looks and sees if the action down lasted for 400L. It works ok unless there is no button on the widget. For example, the clock widget can not be long pressed.
Here is the implementation of the longClickListener on the host view:
hostView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
new AlertDialog.Builder(WidgetEdge.this)
.setTitle("Options")
.setMessage("Do you want to delete or resize widget?")
.setIcon(android.R.drawable.sym_def_app_icon)
.setNegativeButton("Delete", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int whichButton) {
removeWidget(hostView);
Toast.makeText(WidgetEdge.this, "Widget Deleted", Toast.LENGTH_SHORT).show();
}
})
.setPositiveButton("Resize", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
resizeView(hostView);
}
}).show();
return false;
}
});
Here is the AppWidgetHostView class:
public class LauncherAppWidgetHostView extends AppWidgetHostView{
private LayoutInflater mInflater;
WidgetEdge context;
private OnLongClickListener longClick;
private long down;
public LauncherAppWidgetHostView(Context context) {
super(context);
this.context = (WidgetEdge) context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public void setOnLongClickListener(OnLongClickListener l) {
this.longClick = l;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean trueOrFalse = false;
switch(ev.getAction()) {
case MotionEvent.ACTION_DOWN:
down = System.currentTimeMillis();
this.getParent().requestDisallowInterceptTouchEvent(true);
trueOrFalse = false;
break;
case MotionEvent.ACTION_UP:
boolean upVal = System.currentTimeMillis() - down > 400L;
if( upVal ) {
longClick.onLongClick(LauncherAppWidgetHostView.this);
trueOrFalse = true;
}
break;
}
return trueOrFalse;
}
#Override
protected View getErrorView() {
return mInflater.inflate(R.layout.appwidget_error, this, false);
}
}
Here is the AppWidgetHost:
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
class LauncherAppWidgetHost extends AppWidgetHost {
LauncherAppWidgetHost(Context context, int hostId) {
super(context, hostId);
}
#Override
protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
AppWidgetProviderInfo appWidget) {
return new LauncherAppWidgetHostView(context);
}
#Override
public void stopListening() {
super.stopListening();
clearViews();
}
}
I have tried using the code from this link but when I tested on the clock widget it launches the onLongClickListener twice. Also when the widget is scrolled, without a long press, it would also launch the onLongClick. Thank you for any help.
--UPDATE--
I was using the debugger and found out that when using the clock widget the only event intercepted was the first ACTION_DOWN. After that it never picked up the ACTION_UP.
If the widget doesn't behave like a button (so when it can't be clicked) you need to do something more advanced to detect the long click.
You can have a look at https://github.com/willli666/Android-Trebuchet-Launcher-Standalone/blob/master/src/com/cyanogenmod/trebuchet/LauncherAppWidgetHostView.java
If the Apache licence works for your project, you can copy-paste the whole file, you just need to remove getErrorView() and the inflater and you're good to go.
The idea is to start a timeout when detecting the initial ACTION_DOWN event, and when the timeout triggers, if the view still has focus, then you can performLongClick().
It's much harder to accomplish than one would expect, but at least this works on all widgets, even those that can't be clicked.
So I have a music application. I am trying to update the UI with the progress of the media player (like current time, current song, album cover) everytime the song changes. I found that using interfaces was a awesome magical way of communication between activity and fragments so I implemented an interface in my MusicManger class. My code will show what and how did it.
Two problems
1) Commented look below, ExecutorService seems to stop after one loop. No Errors in catch block (this is why I tagged with java)
2) Commented please look, All the System.out methods print but the UI doesn't update. I do believe I called the method from mainThread so it should update.
I'll show code in logical order will add titles in bold before code segment to tell you basic idea of code.
Passing UI references from fragment to MusicManager class, code below in Fragment class
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_item_songlist, container, false);
// Set the adapter
TextView musicManagerSongName, musicManagerCurrent, musicManagerTotal;
ProgressBar musicManagerProgress;
ImageView musicManagerImageView;
mListView = (AbsListView) view.findViewById(R.id.slist);
musicManagerSongName = (TextView)view.findViewById(R.id.textView12);
musicManagerCurrent = (TextView)view.findViewById(R.id.textView10);
musicManagerTotal = (TextView)view.findViewById(R.id.textView11);
musicManagerProgress = (ProgressBar)view.findViewById(R.id.progressBar);
musicManagerImageView = (ImageView)view.findViewById(R.id.imageView2);
MainActivity.mediaPlayer.passUIReferences(musicManagerSongName, musicManagerCurrent, musicManagerTotal, musicManagerProgress, musicManagerImageView, view);
// line above is a method within MusicManager that takes the references will show code next!
ImageButton playbutton = (ImageButton)view.findViewById(R.id.playbuttonbar);
ImageButton nextButton = (ImageButton)view.findViewById(R.id.nextbuttonbar);
ImageButton backButton = (ImageButton)view.findViewById(R.id.backbuttonbar);
ImageButton toggleButton = (ImageButton)view.findViewById(R.id.shufflebuttonbar);
ImageButton pausebutton = (ImageButton)view.findViewById(R.id.pausebuttonbar);
playbutton.setBackgroundResource(R.drawable.playbuttonbar);
playbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
MainActivity.mediaPlayer.stateChange(1);
}catch(Exception e) {
}
}
});
backButton.setBackgroundResource(R.drawable.backbutton1);
nextButton.setBackgroundResource(R.drawable.nextbutton1);
toggleButton.setBackgroundResource(R.drawable.shufflebuttonselected);
pausebutton.setBackgroundResource(R.drawable.pausebutton1);
pausebutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
MainActivity.mediaPlayer.stateChange(0);
} catch (Exception e){
}
}
});
mListView.setAdapter(mAdapter);
((MainActivity) mListener).restoreActionBar();
return view;
}
As Commended above the code that is located in MusicManager class that takes references and stores them. Also shows interface implementation with MusicManager class. And the Executor service
public void passUIReferences(View... views) {
this.uiElements = views;
}
private ExecutorService executorService = Executors.newSingleThreadExecutor();
private MediaplayerUpdateInterface uiUpdateInterface;
public MediaPlayerManager(MediaplayerUpdateInterface inter) {
this.player = new MediaPlayer();
this.uiUpdateInterface = inter;
// The below line starts the single thread while loop for excutorservice and only loops and prints "this" once after I start one song then it never loops again
executorService.submit(new Runnable() {
#Override
public void run() {
while(true) {
if (player.isPlaying() && uiElements != null) {
System.out.println("this");
uiUpdateInterface.updateUI(uiElements, 0);
}
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
public interface MediaplayerUpdateInterface {
public void updateUI(View[] views, int type);
}
Finally some code from MainActivity class that actually is suppose to update the UI note that both println's work as expected but only once as stated above because of the executorservice issue
public static MediaPlayerManager mediaPlayer = new MediaPlayerManager(new MediaPlayerManager.MediaplayerUpdateInterface() {
#Override
public void updateUI(View[] views, int type) {
System.out.println("check1 " + type);
updateMediaplayerViews(views, type);
}
});
private static void updateMediaplayerViews(View[] views, int type)
{
switch(type) {
case 0:
System.out.println("that?");
((TextView)views[0]).setText(mediaPlayer.getCurrentSongInfo().getName().length() > 22? mediaPlayer.getCurrentSongInfo().getName().substring(0, 19)+"..." : mediaPlayer.getCurrentSongInfo().getName());
break;
}
views[views.length - 1].invalidate();
}
The view array is shown perviously! Also the last view in the array is shown as the main view for songlist fragment.
I am sorry for all the code I've tried to debug it as you can see from my println's there is just something I am unaware of going on here.
Ok so there was an error that I needed to catch to see within the following code:
private static void updateMediaplayerViews(View[] views, int type)
{
switch(type) {
case 0:
System.out.println("that?");
((TextView)views[0]).setText(mediaPlayer.getCurrentSongInfo().getName().length() > 22? mediaPlayer.getCurrentSongInfo().getName().substring(0, 19)+"..." : mediaPlayer.getCurrentSongInfo().getName());
break;
}
views[views.length - 1].invalidate();
}
The issue is I was trying to change the view from a different thread then the one which created it. Solving it was pretty long and painful but basically I made it nonstactic used more interfaces then used the famous
Mainactivity.runOnUiThread(new Runnable(....));
I have survey about this subject in a day.
What I mean is how to show toast when tapping the Videoview for a while.
Below is what I've found,
Android: Why can't I give an onClickListener to a VideoView?
detect double tap (Double click) or long click in a videoview
But these really can't solve my problem.I really don't know what has happend?
And is there any function can fire up long pressing event in the video view?
here's my code
these two event really can't work.
mVideoView.setOnLongClickListener(new OnLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
final int arg2, long arg3) {
Log.e("devon","onitemlongclick");
return true;
}
#Override
public boolean onLongClick(View v) {
Log.e("devon","onLongClick");
return true;
}
});
need help !!!thanks!
add OnLongClickListener in your setupViewComponent call
try using onTouch
try attaching the OnLongClickListener to the videoview's surface
try wrapping the videoview with a transparent imageview/something that grabs focus, and use that as your 'touching pad'
post logcat.
This is a sample example on how to create your own TouchListsners for managing Click and LongClick on VideoView. In this example I pass to the listeners the idex of the data clicked and the index of the view (in behind I have several VideoView in arrays maps to data list, like in an Adapter)
/**
* Simple OnTouchListenerIndexed with Indexes for VideoView ClickListeners
* You have to handle longClick and click by yourself
*/
private abstract class OnTouchListenerIndexed implements OnTouchListener {
private static final int LONG_CLICK_DURATION=600;//in millis
int dataIndex = INDEX_NOT_DEFINED;
int imageViewIndex = INDEX_NOT_DEFINED;
long timeActionDown;
AtomicBoolean stillNotConsumed=new AtomicBoolean(true);
AtomicBoolean actionDone=new AtomicBoolean(false);
public OnTouchListenerIndexed(int dataIndex, int imageViewIndex) {
this.dataIndex = dataIndex;
this.imageViewIndex = imageViewIndex;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
timeActionDown=System.currentTimeMillis();
stillNotConsumed.set(true);
actionDone.set(false);
//launch LongClick in 1s
v.postDelayed(new Runnable() {
#Override
public void run() {
if(stillNotConsumed.get()){
stillNotConsumed.set(false);
actionDone.set(true);
onLongTouch(dataIndex, imageViewIndex);
}
}
},LONG_CLICK_DURATION);
//consumed
return true;
}else if(event.getAction() == MotionEvent.ACTION_UP){
long timeActionUp=System.currentTimeMillis();
stillNotConsumed.set(false);
if(actionDone.get()){
//do nothing
return true;//you have consumed it
}else {
actionDone.set(true);
//Check Click or LongClick
if (timeActionUp - timeActionDown > LONG_CLICK_DURATION) {
//une seconde plus tard
return onLongTouch(dataIndex, imageViewIndex);
} else {
return onTouch(dataIndex, imageViewIndex);
}
}
}else{
//don't consume it
return false;
}
}
public abstract boolean onTouch(int dataIndex, int imageViewIndex);
public abstract boolean onLongTouch(int dataIndex, int imageViewIndex);
}
I am having a problem updating the view in android every x seconds.
To get to know how android works I am writing a small game.
It has a GameController which holds the game loop. Inside the loop, the logic is executed and afterwards the gui will be informed about the changes.
The problem is that the changes cannot be seen in the view. The view stays the same until the game loop finishes and updates then only once.
Here is my code (the important parts):
GameController.java:
IGui gui;
public void play() {
while (playing) {
getAndProcessInput();
updateGui();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
}
}
}
private void updateGui() {
gui.setPlayer(x, y);
// ...
}
GameActivity.java:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
GridView gridview = (GridView) findViewById(R.id.GridView1);
TextAdapter = new TextAdapter(this);
gridview.setAdapter(textAdapter);
GameController c = new GameController();
// here, the game loop shoud start.
// what i tried:
// new Thread(c).start(); <-- causes crash
// c.play(); <-- causes view to frease until game loop is done
this.runOnUiThread(c); <-- causes view to frease until game loop is done
}
TextAdapter.java:
public class TextAdapter extends BaseAdapter implements IGui {
private final Context context;
private final String[] texts;
public TextAdapter(Context context) {
this.context = context;
texts = new String[height * width];
for (int i = 0; i < texts.length; i++) {
texts[i] = " ";
}
}
public int getCount() {
return height * width;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv;
if (convertView == null) {
tv = new TextView(context);
tv.setLayoutParams(new GridView.LayoutParams(25, 25));
} else {
tv = (TextView) convertView;
}
tv.setText(texts[position]);
return tv; // <-- this happens only when game loop is done, not everytime something changed
}
#Override
public void setPlayer(int x, int y) {
texts[width * y + x] = "X";
// this.notifyDataSetChanged(); <-- this does not help (view still freases)
// gridview.invalidateViews(); does not help either
}
}
I googled a lot and tried a lot as well (and I do know that similar questions where asked here already, but they did not help me either), but somehow it just does not work.
I cannot get it do work that the view and logic run on different theads in android, and if they run on the same thread the logic blocks the view.
Any help would be greatly appreciated.
// edit:
If I try new Thread(c).start(); LogCat sais:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
And if I add Looper.prepare(); :
java.lang.RuntimeException: Unable to start activity ComponentInfo{GameActivity}: java.lang.RuntimeException: Only one Looper may be created per thread
If I try this.runOnUiThread(c); there are no errors.
First, this doesn't seems like the way to crate a game, you will need to use SurfaceView, or GLSurfaceView to better do what you want.
You can also look for Cocos2d for android, it's a 2D platform (that was ported from iPhone) that makes you life easier:
http://code.google.com/p/cocos2d-android/
I muse warn you though, I tried it a couple months back, and it was not production grade yet, it did crash from time to time.
Anyway, if you still want to continue heading your way I'll try answering your question:
I think you are messing too much with the way these stuff should work. try understanding first how handlers work with threads.
Do anything you want on your thread:
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
calculateGameChangesHere();
handler.sendEmptyMessage(SUCCESS);
}
catch (Exception e)
{
handler.sendEmptyMessage(FAILURE);
}
}
}).start();
When your data is ready, tell the handler to put it in a view and show it:
protected Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (msg.what == SUCCESS)
{
setCalculatedDataToaView(); // the data you calculated from your thread can now be shown in one of your views.
}
else if (msg.what == FAILURE)
{
errorHandlerHere();//could be your toasts or any other error handling...
}
}
};
This goes to everything that requires heavy processing/networking that shouldn't block your UI thread.
Hope this helps.
Not sure what you are trying to achieve by refreshing a listView every few seconds. Anyways if you are writing some 2d games, you have to use SurfaceView , which is especially meant for continuous refreshing.
Had the same problem and solved it using a pretty simple code.
Tips:
GridView must be refreshed by the UI thread
To display every change you must keep the loop and the Sleep method away from the UI thread
Solution:
Method to update the grid (put on your Activity that you build your GridView at the first place or wherever)
public void UpdateGrid(){
//your logic
//your way to change grid values (there are tones of other ways)
CustomGridAdapter cga = new CustomGridAdapter(this, values);
gridView.setAdapter(cga);
gridView.invalidateViews();
}
Build the non UI Thread that does the work
public class DataReceiver implements Runnable {
private MainActivity mainActivity;
public DataReceiver(MainActivity ma) {
mainActivity = ma;
}
#Override
public void run() {
for (int i = 0; i < 100; i++) {
mainActivity.runOnUiThread(new Runnable() {
public void run() {
//update the grid here
mainActivity.UpdateGrid();
}
});
//sleep here
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}